Skip to content

Commit 19e1513

Browse files
authored
Parallel grid generation in lsWriteVisualizationMesh (#110)
* Change iterator logic when creating grid in lsWriteVisualizationMesh * Parallel gird generation * Remove debug output
1 parent 19d68c9 commit 19e1513

File tree

1 file changed

+122
-126
lines changed

1 file changed

+122
-126
lines changed

include/viennals/lsWriteVisualizationMesh.hpp

Lines changed: 122 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ template <class T, int D> class WriteVisualizationMesh {
224224
// The full domain contains values, which are capped at numLayers * gridDelta
225225
// gridExtraPoints layers of grid points are added to the domain according to
226226
// boundary conditions
227-
template <bool removeBottom = false, int gridExtraPoints = 0>
227+
template <int gridExtraPoints = 0>
228228
vtkSmartPointer<vtkRectilinearGrid>
229229
LS2RectiLinearGrid(SmartPointer<Domain<T, D>> levelSet,
230230
const double LSOffset = 0.,
@@ -239,7 +239,8 @@ template <class T, int D> class WriteVisualizationMesh {
239239
vtkSmartPointer<vtkFloatArray>
240240
coords[3]; // needs to be 3 because vtk only knows 3D
241241
int gridMin = 0, gridMax = 0;
242-
int openJumpDirection = -1; // direction above the open boundary direction
242+
// int openJumpDirection = -1; // direction above the open boundary
243+
// direction
243244

244245
// fill grid with offset depending on orientation
245246
for (unsigned i = 0; i < D; ++i) {
@@ -253,8 +254,7 @@ template <class T, int D> class WriteVisualizationMesh {
253254
// overall minimum can be chosen
254255
gridMax = std::max(domain.getMaxRunBreak(i), infiniteMaximum) + 1;
255256

256-
openJumpDirection = i + 1;
257-
257+
// openJumpDirection = i + 1;
258258
} else {
259259
gridMin = grid.getMinGridPoint(i) - gridExtraPoints;
260260
gridMax = grid.getMaxGridPoint(i) + gridExtraPoints;
@@ -281,131 +281,125 @@ template <class T, int D> class WriteVisualizationMesh {
281281
rgrid->SetYCoordinates(coords[1]);
282282
rgrid->SetZCoordinates(coords[2]);
283283

284-
// now iterate over grid and fill with LS values
285-
// initialise iterator over levelset and pointId to start at gridMin
286-
vtkIdType pointId = 0;
287-
bool fixBorderPoints = (gridExtraPoints != 0);
288-
289-
// typename levelSetType::const_iterator_runs it_l(levelSet);
290-
// use dense iterator to got to every index location
291-
hrleConstDenseIterator<typename Domain<T, D>::DomainType> it(
292-
levelSet->getDomain());
284+
// bool fixBorderPoints = (gridExtraPoints != 0);
293285

294286
// need to save the current position one dimension above open boundary
295287
// direction, so we can register a jump in the open boundary direction when
296288
// it occurs, so we can fix the LS value as follows: if remove_bottom==true,
297289
// we need to flip the sign otherwise the sign stays the same
298-
int currentOpenIndex =
299-
it.getIndices()[(openJumpDirection < D) ? openJumpDirection : 0];
290+
// int currentOpenIndex =
291+
// it.getIndices()[(openJumpDirection < D) ? openJumpDirection : 0];
300292

301293
// Make array to store signed distance function
294+
auto const numGridPoints = rgrid->GetNumberOfPoints();
302295
vtkSmartPointer<vtkFloatArray> signedDistances =
303296
vtkSmartPointer<vtkFloatArray>::New();
304297
signedDistances->SetNumberOfComponents(1);
298+
signedDistances->SetNumberOfTuples(numGridPoints);
305299
signedDistances->SetName("SignedDistances");
306300

307-
// iterate until all grid points have a signed distance value
308-
while ((pointId < rgrid->GetNumberOfPoints())) {
309-
double p[3];
310-
rgrid->GetPoint(pointId, p);
311-
// create index vector
312-
hrleVectorType<hrleIndexType, D> indices(
313-
grid.globalCoordinates2GlobalIndices(p));
314-
315-
// write the corresponding LSValue
316-
T value;
317-
318-
// if indices are outside of domain mark point with max value type
319-
if (grid.isOutsideOfDomain(indices)) {
320-
fixBorderPoints = true;
321-
signedDistances->InsertNextValue(
322-
signedDistances->GetDataTypeValueMax());
323-
} else {
324-
// if inside domain just write the correct value
325-
if (it.getValue() == Domain<T, D>::POS_VALUE || it.isFinished()) {
301+
#pragma omp parallel
302+
{
303+
// use dense iterator to got to every index location
304+
hrleConstDenseIterator<typename Domain<T, D>::DomainType> it(
305+
levelSet->getDomain());
306+
307+
#pragma omp for
308+
for (vtkIdType pointId = 0; pointId < numGridPoints; ++pointId) {
309+
// iterate until all grid points have a signed distance value
310+
311+
double p[3];
312+
rgrid->GetPoint(pointId, p);
313+
// create index vector
314+
hrleVectorType<hrleIndexType, D> indices(
315+
grid.globalCoordinates2GlobalIndices(p));
316+
317+
// write the corresponding LSValue
318+
T value;
319+
320+
// if indices are outside of domain map to local indices
321+
if (grid.isOutsideOfDomain(indices)) {
322+
indices = grid.globalIndices2LocalIndices(indices);
323+
// fixBorderPoints = true;
324+
// signedDistances->InsertNextValue(
325+
// signedDistances->GetDataTypeValueMax());
326+
}
327+
328+
it.goToIndices(indices);
329+
if (it.getValue() == Domain<T, D>::POS_VALUE) {
326330
value = numLayers;
327331
} else if (it.getValue() == Domain<T, D>::NEG_VALUE) {
328332
value = -numLayers;
329333
} else {
330334
value = it.getValue() + LSOffset;
331335
}
332336

333-
if (removeBottom) {
334-
// if we jump from one end of the domain to the other and are not
335-
// already in the new run, we need to fix the sign of the run
336-
if (currentOpenIndex != indices[openJumpDirection]) {
337-
currentOpenIndex = indices[openJumpDirection];
338-
if (indices >= it.getIndices()) {
339-
value = -value;
340-
}
341-
}
342-
}
337+
// if (removeBottom) {
338+
// // if we jump from one end of the domain to the other and are not
339+
// // already in the new run, we need to fix the sign of the run
340+
// if (currentOpenIndex != indices[openJumpDirection]) {
341+
// currentOpenIndex = indices[openJumpDirection];
342+
// if (indices >= it.getIndices()) {
343+
// value = -value;
344+
// }
345+
// }
346+
// }
343347

344-
signedDistances->InsertNextValue(value * gridDelta);
348+
signedDistances->SetValue(pointId, value * gridDelta);
349+
// signedDistances->InsertNextValue(value * gridDelta);
345350
}
346351

347-
// move iterator if point was visited
348-
if (it.isFinished()) { // when iterator is done just fill all the
349-
// remaining points
350-
++pointId;
351-
} else {
352-
while (it.getIndices() <= indices) {
353-
it.next();
354-
}
355-
356-
++pointId;
357-
358-
// // advance iterator until it is at correct point
359-
// while (compare(it_l.end_indices(), indices) < 0) {
360-
// it_l.next();
361-
// if (it_l.is_finished())
362-
// break;
363-
// }
364-
// // now move iterator with pointId to get to next point
365-
// switch (compare(it_l.end_indices(), indices)) {
366-
// case 0:
367-
// it_l.next();
368-
// default:
369-
// ++pointId;
370-
// }
371-
}
352+
// // advance iterator until it is at correct point
353+
// while (compare(it_l.end_indices(), indices) < 0) {
354+
// it_l.next();
355+
// if (it_l.is_finished())
356+
// break;
357+
// }
358+
// // now move iterator with pointId to get to next point
359+
// switch (compare(it_l.end_indices(), indices)) {
360+
// case 0:
361+
// it_l.next();
362+
// default:
363+
// ++pointId;
364+
// }
365+
// }
372366
}
373367

374368
// now need to go through again to fix border points, this is done by
375369
// mapping existing points onto the points outside of the domain according
376370
// to the correct boundary conditions
377-
if (fixBorderPoints) {
378-
pointId = 0;
379-
while ((pointId < rgrid->GetNumberOfPoints())) {
380-
if (signedDistances->GetValue(pointId) ==
381-
signedDistances->GetDataTypeValueMax()) {
382-
double p[3];
383-
rgrid->GetPoint(pointId, p);
384-
385-
// create index vector
386-
hrleVectorType<hrleIndexType, D> indices(
387-
grid.globalCoordinates2GlobalIndices(p));
388-
389-
// vector for mapped point inside domain
390-
hrleVectorType<hrleIndexType, D> localIndices =
391-
grid.globalIndices2LocalIndices(indices);
392-
393-
// now find Id of point we need to take value from
394-
int originalPointId = 0;
395-
for (int i = D - 1; i >= 0; --i) {
396-
originalPointId *=
397-
coords[i]->GetNumberOfTuples(); // extent in direction
398-
originalPointId += localIndices[i] - indices[i];
399-
}
400-
originalPointId += pointId;
401-
402-
// now put value of mapped point in global point
403-
signedDistances->SetValue(pointId,
404-
signedDistances->GetValue(originalPointId));
405-
}
406-
++pointId;
407-
}
408-
}
371+
// if (fixBorderPoints) {
372+
// vtkIdType pointId = 0;
373+
// while ((pointId < rgrid->GetNumberOfPoints())) {
374+
// if (signedDistances->GetValue(pointId) ==
375+
// signedDistances->GetDataTypeValueMax()) {
376+
// double p[3];
377+
// rgrid->GetPoint(pointId, p);
378+
379+
// // create index vector
380+
// hrleVectorType<hrleIndexType, D> indices(
381+
// grid.globalCoordinates2GlobalIndices(p));
382+
383+
// // vector for mapped point inside domain
384+
// hrleVectorType<hrleIndexType, D> localIndices =
385+
// grid.globalIndices2LocalIndices(indices);
386+
387+
// // now find Id of point we need to take value from
388+
// int originalPointId = 0;
389+
// for (int i = D - 1; i >= 0; --i) {
390+
// originalPointId *=
391+
// coords[i]->GetNumberOfTuples(); // extent in direction
392+
// originalPointId += localIndices[i] - indices[i];
393+
// }
394+
// originalPointId += pointId;
395+
396+
// // now put value of mapped point in global point
397+
// signedDistances->SetValue(pointId,
398+
// signedDistances->GetValue(originalPointId));
399+
// }
400+
// ++pointId;
401+
// }
402+
// }
409403

410404
// Add the SignedDistances to the grid
411405
rgrid->GetPointData()->SetScalars(signedDistances);
@@ -483,13 +477,14 @@ template <class T, int D> class WriteVisualizationMesh {
483477
vtkSmartPointer<vtkTableBasedClipDataSet> clipper =
484478
vtkSmartPointer<vtkTableBasedClipDataSet>::New();
485479
auto topGrid = vtkSmartPointer<vtkRectilinearGrid>::New();
486-
if (bottomRemoved) {
487-
topGrid = LS2RectiLinearGrid<true>(levelSets.back(), 0, totalMinimum,
488-
totalMaximum);
489-
} else {
490-
topGrid = LS2RectiLinearGrid<false>(levelSets.back(), 0, totalMinimum,
491-
totalMaximum);
492-
}
480+
// if (bottomRemoved) {
481+
topGrid =
482+
LS2RectiLinearGrid(levelSets.back(), 0, totalMinimum, totalMaximum);
483+
// } else {
484+
// topGrid = LS2RectiLinearGrid<false>(levelSets.back(), 0,
485+
// totalMinimum,
486+
// totalMaximum);
487+
// }
493488
#ifdef LS_TO_VISUALIZATION_DEBUG
494489
{
495490
auto gwriter = vtkSmartPointer<vtkXMLRectilinearGridWriter>::New();
@@ -537,16 +532,17 @@ template <class T, int D> class WriteVisualizationMesh {
537532
if (it->get()->getNumberOfPoints() == 0)
538533
continue; // ignore empty levelSets
539534

540-
// create grid of next LS with slight offset and project into current mesh
535+
// create grid of next LS with slight offset and project into current
536+
// mesh
541537
vtkSmartPointer<vtkRectilinearGrid> rgrid =
542538
vtkSmartPointer<vtkRectilinearGrid>::New();
543-
if (bottomRemoved || counter == levelSets.size() - 1) {
544-
rgrid = LS2RectiLinearGrid<true, 1>(*it, -LSEpsilon * counter,
545-
totalMinimum, totalMaximum);
546-
} else {
547-
rgrid = LS2RectiLinearGrid<false, 1>(*it, -LSEpsilon * counter,
548-
totalMinimum, totalMaximum);
549-
}
539+
// if (bottomRemoved) {
540+
rgrid = LS2RectiLinearGrid<1>(*it, -LSEpsilon * counter, totalMinimum,
541+
totalMaximum);
542+
// } else {
543+
// rgrid = LS2RectiLinearGrid<false, 1>(*it, -LSEpsilon * counter,
544+
// totalMinimum, totalMaximum);
545+
// }
550546

551547
#ifdef LS_TO_VISUALIZATION_DEBUG
552548
{
@@ -588,7 +584,7 @@ template <class T, int D> class WriteVisualizationMesh {
588584
insideClipper->GenerateClippedOutputOn();
589585
insideClipper->Update();
590586

591-
materialMeshes.rbegin()[0] = insideClipper->GetOutput();
587+
materialMeshes.back() = insideClipper->GetOutput();
592588
materialMeshes.push_back(insideClipper->GetClippedOutput());
593589
int material = counter;
594590
if (useMaterialMap)
@@ -621,9 +617,9 @@ template <class T, int D> class WriteVisualizationMesh {
621617
materialNumberArray);
622618

623619
// delete all point data, so it is not in ouput
624-
// TODO this includes signed distance information which could be conserved
625-
// for debugging also includes wheter a cell was vaild for cutting by the
626-
// grid
620+
// TODO this includes signed distance information which could be
621+
// conserved for debugging also includes wheter a cell was vaild for
622+
// cutting by the grid
627623
vtkSmartPointer<vtkPointData> pointData =
628624
materialMeshes[materialMeshes.size() - 1 - i]->GetPointData();
629625
const int numberOfArrays = pointData->GetNumberOfArrays();
@@ -650,8 +646,8 @@ template <class T, int D> class WriteVisualizationMesh {
650646
if (extractVolumeMesh) {
651647
appendFilter->Update();
652648

653-
// remove degenerate points and remove cells which collapse to zero volume
654-
// then
649+
// remove degenerate points and remove cells which collapse to zero
650+
// volume then
655651
volumeVTK = appendFilter->GetOutput();
656652
#ifdef LS_TO_VISUALIZATION_DEBUG
657653
{
@@ -666,8 +662,8 @@ template <class T, int D> class WriteVisualizationMesh {
666662
}
667663
#endif
668664

669-
// use 1/1000th of grid spacing for contraction of two similar points, so
670-
// that tetrahedralisation works correctly
665+
// use 1/1000th of grid spacing for contraction of two similar points,
666+
// so that tetrahedralisation works correctly
671667
removeDuplicatePoints(volumeVTK, 1e-3 * gridDelta);
672668

673669
#ifdef LS_TO_VISUALIZATION_DEBUG
@@ -719,7 +715,7 @@ template <class T, int D> class WriteVisualizationMesh {
719715
writer->Write();
720716
}
721717
}
722-
};
718+
}; // namespace viennals
723719

724720
// add all template specialisations for this class
725721
PRECOMPILE_PRECISION_DIMENSION(WriteVisualizationMesh)

0 commit comments

Comments
 (0)