106 if (levelSet ==
nullptr) {
107 Logger::getInstance()
108 .addWarning(
"No level set passed to GeometricAdvect. Not Advecting.")
112 if (dist ==
nullptr) {
113 Logger::getInstance()
114 .addWarning(
"No GeometricAdvectDistribution passed to "
115 "GeometricAdvect. Not "
124 if (maskLevelSet !=
nullptr) {
130 auto &domain = levelSet->getDomain();
132 auto &grid = levelSet->getGrid();
133 auto gridDelta = grid.getGridDelta();
137 auto surfaceMesh = SmartPointer<Mesh<hrleCoordType>>::New();
138 auto pointIdTranslator =
139 SmartPointer<typename ToDiskMesh<T, D>::TranslatorType>::New();
142 *pointIdTranslator = inverseTranslator(*pointIdTranslator);
145 auto distBounds = dist->getBounds();
148 hrleVectorType<hrleIndexType, D> distMin, distMax;
150 bool minPointNegative = domain.getDomainSegment(0).definedValues[0] < 0.;
151 bool maxPointNegative =
152 domain.getDomainSegment(domain.getNumberOfSegments() - 1)
153 .definedValues.back() < 0.;
154 bool distIsPositive =
true;
157 hrleIndexType bounds[6];
158 domain.getDomainBounds(bounds);
159 hrleVectorType<hrleIndexType, D> min, max;
160 for (
unsigned i = 0; i <
D; ++i) {
163 distBounds[2 * i] / gridDelta + ((distBounds[2 * i] < 0) ? -2 : 2);
164 distMax[i] = distBounds[2 * i + 1] / gridDelta +
165 ((distBounds[2 * i + 1] < 0) ? -2 : 2);
166 if (distBounds[2 * i] >= 0) {
167 distIsPositive =
false;
173 min[i] = surfaceMesh->minimumExtent[i] / gridDelta;
175 if (grid.isNegBoundaryInfinite(i) && minPointNegative && distMin[i] < 0) {
178 if (distIsPositive) {
179 min[i] += distMin[i];
181 min[i] -= distMin[i];
186 if (min[i] < grid.getMinGridPoint(i)) {
187 min[i] = grid.getMinGridPoint(i);
190 max[i] = surfaceMesh->maximumExtent[i] / gridDelta;
191 if (grid.isPosBoundaryInfinite(i) && maxPointNegative && distMax[i] > 0) {
194 if (distIsPositive) {
195 max[i] += distMax[i];
197 max[i] -= distMax[i];
200 if (max[i] > grid.getMaxGridPoint(i)) {
201 max[i] = grid.getMaxGridPoint(i);
208 if (maskLevelSet !=
nullptr) {
210 auto &maskDomain = maskLevelSet->getDomain();
211 auto values = surfaceMesh->cellData.getScalarData(
"LSValues");
212 auto valueIt = values->begin();
214 auto newSurfaceMesh = SmartPointer<Mesh<hrleCoordType>>::New();
216 hrleConstSparseIterator<DomainType> maskIt(maskDomain);
217 for (
auto &node : surfaceMesh->getNodes()) {
218 hrleVectorType<hrleIndexType, D> index;
219 for (
unsigned i = 0; i <
D; ++i) {
220 index[i] = std::round(node[i] / gridDelta);
224 maskIt.goToIndicesSequential(index);
226 if (!maskIt.isDefined() || !(maskIt.getValue() < *valueIt + 1e-5)) {
227 newSurfaceMesh->insertNextNode(node);
228 newValues.push_back(*valueIt);
230 std::array<unsigned, 1> vertex;
231 vertex[0] = newSurfaceMesh->nodes.size();
232 newSurfaceMesh->insertNextVertex(vertex);
236 newSurfaceMesh->cellData.insertNextScalarData(newValues,
"LSValues");
238 newSurfaceMesh->minimumExtent = surfaceMesh->minimumExtent;
239 newSurfaceMesh->maximumExtent = surfaceMesh->maximumExtent;
240 surfaceMesh = newSurfaceMesh;
245 Logger::getInstance()
246 .addDebug(
"GeomAdvect: Writing debug meshes")
249 "DEBUG_lsGeomAdvectMesh_contributewoMask.vtp")
251 auto mesh = SmartPointer<Mesh<T>>::New();
252 if (maskLevelSet !=
nullptr) {
255 "DEBUG_lsGeomAdvectMesh_mask.vtp")
260 "DEBUG_lsGeomAdvectMesh_initial.vtp")
266 typedef std::vector<std::array<hrleCoordType, 3>> SurfaceNodesType;
267 const SurfaceNodesType &surfaceNodes = surfaceMesh->getNodes();
270 typename hrleDomain<T, D>::hrleIndexPoints segmentation;
273 unsigned long long numPoints = 1;
274 unsigned long long pointsPerDimension[
D];
275 for (
unsigned i = 0; i <
D; ++i) {
276 pointsPerDimension[i] = numPoints;
277 numPoints *= max[i] - min[i];
279 unsigned long numberOfSegments = domain.getNumberOfSegments();
280 unsigned long long pointsPerSegment = numPoints / numberOfSegments;
281 unsigned long long pointId = 0;
282 for (
unsigned i = 0; i < numberOfSegments - 1; ++i) {
283 pointId = pointsPerSegment * (i + 1);
284 hrleVectorType<hrleIndexType, D> segmentPoint;
285 for (
int j =
D - 1; j >= 0; --j) {
286 segmentPoint[j] = pointId / (pointsPerDimension[j]) + min[j];
287 pointId %= pointsPerDimension[j];
289 segmentation.push_back(segmentPoint);
293 typedef std::vector<std::pair<hrleVectorType<hrleIndexType, D>,
T>>
295 std::vector<PointValueVector> newPoints;
296 newPoints.resize(domain.getNumberOfSegments());
298 const T initialDistance = (distIsPositive)
299 ? std::numeric_limits<double>::max()
300 : std::numeric_limits<double>::lowest();
304 std::ostringstream oss;
305 oss <<
"GeomAdvect: Min: " << min <<
", Max: " << max << std::endl;
306 Logger::getInstance().addDebug(oss.str()).print();
310#pragma omp parallel num_threads(domain.getNumberOfSegments())
314 p = omp_get_thread_num();
317 hrleVectorType<hrleIndexType, D> startVector;
321 startVector = segmentation[p - 1];
322 incrementIndices(startVector, min, max);
325 hrleVectorType<hrleIndexType, D> endVector =
326 (p !=
static_cast<int>(domain.getNumberOfSegments() - 1))
328 : grid.incrementIndices(max);
330 hrleConstSparseIterator<DomainType> checkIt(levelSet->getDomain(),
334 SmartPointer<hrleConstSparseIterator<DomainType>> maskIt =
nullptr;
335 if (maskLevelSet !=
nullptr) {
336 maskIt = SmartPointer<hrleConstSparseIterator<DomainType>>::New(
337 maskLevelSet->getDomain(), startVector);
341 for (hrleVectorType<hrleIndexType, D> currentIndex = startVector;
342 currentIndex <= endVector;
343 incrementIndices(currentIndex, min, max)) {
345 checkIt.goToIndicesSequential(currentIndex);
346 T oldValue = checkIt.getValue();
348 if (distIsPositive) {
349 if (oldValue < -cutoffValue) {
352 }
else if (oldValue > cutoffValue) {
356 std::array<hrleCoordType, 3> currentCoords{};
357 std::array<hrleCoordType, 3> currentDistMin{};
358 std::array<hrleCoordType, 3> currentDistMax{};
360 for (
unsigned i = 0; i <
D; ++i) {
361 currentCoords[i] = currentIndex[i] * gridDelta;
363 currentDistMin[i] = currentIndex[i] - std::abs(distMin[i]);
364 if (currentDistMin[i] < grid.getMinGridPoint(i)) {
365 currentDistMin[i] = grid.getMinGridPoint(i);
367 currentDistMin[i] *= gridDelta;
369 currentDistMax[i] = currentIndex[i] + std::abs(distMax[i]);
370 if (currentDistMin[i] > grid.getMaxGridPoint(i)) {
371 currentDistMin[i] = grid.getMaxGridPoint(i);
373 currentDistMax[i] *= gridDelta;
376 T distance = initialDistance;
378 unsigned long currentPointId = 0;
380 for (
typename SurfaceNodesType::const_iterator surfIt =
381 surfaceNodes.begin();
382 surfIt != surfaceNodes.end(); ++surfIt, ++currentPointId) {
384 auto ¤tNode = *surfIt;
388 bool outside =
false;
389 for (
unsigned i = 0; i <
D; ++i) {
390 if ((currentNode[i] < currentDistMin[i]) ||
391 (currentNode[i] > currentDistMax[i])) {
402 if (!dist->isInside(currentNode, currentCoords, 2 * gridDelta)) {
407 T tmpDistance = dist->getSignedDistance(
408 currentNode, currentCoords,
409 pointIdTranslator->find(currentPointId)->second) /
413 if (distIsPositive) {
414 if (tmpDistance <= -cutoffValue) {
415 distance = std::numeric_limits<T>::lowest();
419 if (tmpDistance < distance) {
420 distance = tmpDistance;
423 if (tmpDistance >= cutoffValue) {
424 distance = std::numeric_limits<T>::max();
428 if (tmpDistance > distance) {
429 distance = tmpDistance;
437 if (maskLevelSet !=
nullptr) {
438 maskIt->goToIndicesSequential(currentIndex);
442 (std::abs(oldValue - maskIt->getValue()) < 1e-6)) {
443 if (!distIsPositive && std::abs(oldValue) <= cutoffValue) {
444 newPoints[p].push_back(std::make_pair(currentIndex, oldValue));
448 if (distance != initialDistance) {
449 distance = std::min(maskIt->getValue(), distance);
450 }
else if (distIsPositive || oldValue >= 0.) {
451 newPoints[p].push_back(std::make_pair(currentIndex, oldValue));
457 if (std::abs(distance) <= cutoffValue) {
459 if (distIsPositive && oldValue >= 0.) {
460 newPoints[p].push_back(std::make_pair(currentIndex, distance));
461 }
else if (!distIsPositive && oldValue <= 0.) {
463 if (maskIt ==
nullptr || maskIt->getValue() > -cutoffValue) {
464 newPoints[p].push_back(std::make_pair(currentIndex, distance));
468 newPoints[p].push_back(std::make_pair(currentIndex, oldValue));
476 unsigned long long numberOfPoints = newPoints[0].size();
477 for (
unsigned i = 1; i < domain.getNumberOfSegments(); ++i) {
478 numberOfPoints += newPoints[i].size();
480 newPoints[0].reserve(numberOfPoints);
481 for (
unsigned i = 1; i < domain.getNumberOfSegments(); ++i) {
482 std::move(std::begin(newPoints[i]), std::end(newPoints[i]),
483 std::back_inserter(newPoints[0]));
487 auto mesh = SmartPointer<Mesh<T>>::New();
490 std::vector<T> scalarData;
491 for (
auto it = newPoints[0].begin(); it != newPoints[0].end(); ++it) {
492 std::array<T, 3> node = {};
493 for (
unsigned i = 0; i <
D; ++i) {
494 node[i] =
T((it->first)[i]) * gridDelta;
497 mesh->insertNextNode(node);
498 std::array<unsigned, 1> vertex;
499 vertex[0] = mesh->vertices.size();
500 mesh->insertNextVertex(vertex);
501 scalarData.push_back(it->second);
503 mesh->cellData.insertNextScalarData(scalarData,
"LSValues");
507 Logger::getInstance().addDebug(
"GeomAdvect: Writing final mesh...").print();
515 Logger::getInstance().addDebug(
"GeomAdvect: Writing final LS...").print();
523 levelSet->getDomain().segment();
524 levelSet->finalize(1);