ViennaLS
Loading...
Searching...
No Matches
lsFromSurfaceMesh.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <hrleIndexType.hpp>
6
7#include <lsDomain.hpp>
8#include <lsMesh.hpp>
9
10namespace viennals {
11
12using namespace viennacore;
13
15template <class T, int D> class FromSurfaceMesh {
16
18 class box {
19 hrleVectorType<hrleIndexType, D - 1> xMin, xMax;
20
21 public:
24 box(const hrleVectorType<hrleIndexType, D - 1> &idx0,
25 const hrleVectorType<hrleIndexType, D - 1> &idx1) {
26 xMin = Min(idx0, idx1);
27 xMax = Max(idx0, idx1);
28 }
29
31 box(const box &box) {
32 xMin = box.xMin;
33 xMax = box.xMax;
34 }
35
37 box(const hrleVectorType<hrleIndexType, D - 1> &idx) {
38 xMin = idx;
39 xMax = idx;
40 }
41
42 box operator=(const box &b) {
43 xMin = b.xMin;
44 xMax = b.xMax;
45 return *this;
46 }
47
49 bool is_empty() const {
50 for (int i = 0; i < D - 1; i++)
51 if (xMax[i] < xMin[i])
52 return true;
53 return false;
54 }
55
57 const hrleVectorType<hrleIndexType, D - 1> &min() const { return xMin; }
59 const hrleVectorType<hrleIndexType, D - 1> &max() const { return xMax; }
60
62 class iterator {
63 hrleVectorType<hrleIndexType, D - 1> pos;
64 const box &b;
65
66 public:
67 iterator(const box &bx) : pos(bx.min()), b(bx) {}
68
70 int i;
71 for (i = 0; i < D - 2; i++) {
72 pos[i]++;
73 if (pos[i] <= b.xMax[i]) {
74 break;
75 } else {
76 pos[i] = b.xMin[i];
77 }
78 }
79 if (i == D - 2)
80 pos[i]++;
81 return *this;
82 }
83
85 iterator tmp = *this;
86 ++(*this);
87 return tmp;
88 }
89
90 bool is_finished() const { return (pos[D - 2] > b.xMax[D - 2]); }
91
92 const hrleVectorType<hrleIndexType, D - 1> &operator*() const {
93 return pos;
94 }
95 };
96 };
97
98 SmartPointer<Domain<T, D>> levelSet = SmartPointer<Domain<T, D>>::New();
99 SmartPointer<Mesh<T>> mesh = SmartPointer<Mesh<T>>::New();
100 // bool removeBoundaryTriangles = true;
101 std::array<bool, 3> removeBoundaryTriangles{true, true, true};
102 T boundaryEps = 1e-5;
103 T distanceEps = 1e-4;
104 T signEps = 1e-6;
105
112 int calculateGridlineTriangleIntersection(hrleVectorType<T, 2> Point,
113 const hrleVectorType<T, 2> *c,
114 int dir, T &intersection) {
115
116 bool inside_pos = true;
117 bool inside_neg = true;
118
119 T A[2];
120
121 const int dirA = (dir + 1) % 2;
122
123 for (int k = 0; k < 2; k++) {
124 A[k] = c[(k + 1) % 2][dirA] - Point[dirA];
125 if (k == dir)
126 A[k] = -A[k];
127 if (A[k] < T(0))
128 inside_pos = false;
129 if (A[k] > T(0))
130 inside_neg = false;
131 }
132
133 if ((!inside_pos && inside_neg) || (inside_pos && !inside_neg)) {
134 T sum = A[0] + A[1];
135 int k = 0;
136 for (int i = 1; i < 2; ++i) {
137 if (inside_pos) {
138 if (A[i] > A[k])
139 k = i;
140 } else {
141 if (A[i] < A[k])
142 k = i;
143 }
144 }
145 intersection = c[k][dir] +
146 (c[(k + 1) % 2][dir] - c[k][dir]) * (A[(k + 1) % 2] / sum);
147 return (inside_pos) ? 1 : -1;
148 } else {
149 return 0;
150 }
151 }
152
159 int calculateGridlineTriangleIntersection(hrleVectorType<T, 3> Point,
160 const hrleVectorType<T, 3> *c,
161 int dir, T &intersection) {
162
163 bool inside_pos = true;
164 bool inside_neg = true;
165
166 T A[3];
167
168 const int dirA = (dir + 1) % 3;
169 const int dirB = (dir + 2) % 3;
170
171 for (int k = 0; k < 3; k++) {
172 bool swapped =
173 (c[(k + 1) % 3] <
174 c[(k + 2) % 3]); // necessary to guarantee anti commutativity
175 const hrleVectorType<T, 3> &v1 =
176 (swapped) ? c[(k + 2) % 3] : c[(k + 1) % 3];
177 const hrleVectorType<T, 3> &v2 =
178 (swapped) ? c[(k + 1) % 3] : c[(k + 2) % 3];
179
180 A[k] = (v1[dirA] - Point[dirA]) * (v2[dirB] - Point[dirB]) -
181 (v2[dirA] - Point[dirA]) * (v1[dirB] - Point[dirB]);
182
183 if (swapped)
184 A[k] = -A[k];
185
186 if (A[k] < T(0))
187 inside_pos = false;
188 if (A[k] > T(0))
189 inside_neg = false;
190 }
191
192 if ((!inside_pos && inside_neg) || (inside_pos && !inside_neg)) {
193 T sum = A[0] + A[1] + A[2];
194 int k = 0;
195 for (int i = 1; i < 3; ++i) {
196 if (inside_pos) {
197 if (A[i] > A[k])
198 k = i;
199 } else {
200 if (A[i] < A[k])
201 k = i;
202 }
203 }
204 intersection =
205 c[k][dir] +
206 (c[(k + 1) % 3][dir] - c[k][dir]) * (A[(k + 1) % 3] / sum) +
207 (c[(k + 2) % 3][dir] - c[k][dir]) * (A[(k + 2) % 3] / sum);
208 return (inside_pos) ? 1 : -1;
209 } else {
210 return 0;
211 }
212 }
213
214public:
216
217 FromSurfaceMesh(SmartPointer<Domain<T, D>> passedLevelSet,
218 SmartPointer<Mesh<T>> passedMesh,
219 bool passedRemoveBoundaryTriangles = true)
220 : levelSet(passedLevelSet), mesh(passedMesh),
221 removeBoundaryTriangles{passedRemoveBoundaryTriangles,
222 passedRemoveBoundaryTriangles,
223 passedRemoveBoundaryTriangles} {}
224
225 void setLevelSet(SmartPointer<Domain<T, D>> passedLevelSet) {
226 levelSet = passedLevelSet;
227 }
228
229 void setMesh(SmartPointer<Mesh<T>> passedMesh) { mesh = passedMesh; }
230
234 void setRemoveBoundaryTriangles(bool passedRemoveBoundaryTriangles) {
235 removeBoundaryTriangles.fill(passedRemoveBoundaryTriangles);
236 }
237
242 template <std::size_t N>
244 std::array<bool, N> passedRemoveBoundaryTriangles) {
245 for (unsigned i = 0; i < D && i < N; ++i) {
246 removeBoundaryTriangles[i] = passedRemoveBoundaryTriangles[i];
247 }
248 }
249
250 void apply() {
251 if (levelSet == nullptr) {
252 Logger::getInstance()
253 .addWarning("No level set was passed to FromSurfaceMesh.")
254 .print();
255 return;
256 }
257 if (mesh == nullptr) {
258 Logger::getInstance()
259 .addWarning("No mesh was passed to FromSurfaceMesh.")
260 .print();
261 return;
262 }
263
264 const auto &grid = levelSet->getGrid();
265
266 // caluclate which directions should apply removeBoundaryTriangles
267 // it only makes sense to keep boundary triangles for periodic BNC
268 bool removeBoundaries[D];
269 for (unsigned i = 0; i < D; ++i) {
270 if (!removeBoundaryTriangles[i] && grid.isBoundaryPeriodic(i)) {
271 removeBoundaries[i] = false;
272 } else {
273 removeBoundaries[i] = true;
274 }
275 }
276
277 std::vector<std::pair<hrleVectorType<hrleIndexType, D>, T>> points2;
278
279 // setup list of grid points with distances to surface elements
280 {
281 typedef typename std::vector<
282 std::pair<hrleVectorType<hrleIndexType, D>, std::pair<T, T>>>
283 point_vector;
284 point_vector points;
285 T gridDelta = grid.getGridDelta();
286
287 hrleVectorType<T, D> gridMin, gridMax;
288 for (unsigned i = 0; i < D; ++i) {
289 gridMin[i] = grid.getMinIndex(i) * gridDelta;
290 gridMax[i] = grid.getMaxIndex(i) * gridDelta;
291 }
292
293 // for each surface element do
294 std::vector<std::array<unsigned, D>> &elements =
295 mesh->template getElements<D>();
296
297 for (unsigned currentElement = 0; currentElement < elements.size();
298 currentElement++) {
299 hrleVectorType<T, D> nodes[D]; // nodes of element
300 hrleVectorType<T, D> center(T(0)); // center point of triangle
301
302 std::bitset<2 * D> flags;
303 flags.set();
304 bool removeElement = false;
305
306 for (int dim = 0; dim < D; dim++) {
307 for (int q = 0; q < D; q++) {
308 nodes[q][dim] = mesh->nodes[elements[currentElement][q]][dim];
309 if (std::abs(nodes[q][dim] - gridMin[dim]) <
310 boundaryEps * gridDelta)
311 nodes[q][dim] = gridMin[dim];
312 if (std::abs(nodes[q][dim] - gridMax[dim]) <
313 boundaryEps * gridDelta)
314 nodes[q][dim] = gridMax[dim];
315
316 if (nodes[q][dim] > gridMin[dim])
317 flags.reset(dim);
318 if (nodes[q][dim] < gridMax[dim])
319 flags.reset(dim + D);
320
321 center[dim] += nodes[q][dim]; // center point calculation
322 }
323 if (removeBoundaries[dim] && (flags[dim] || flags[dim + D])) {
324 removeElement = true;
325 }
326 }
327
328 if (removeElement)
329 continue;
330
331 // center point calculation
332 center /= static_cast<T>(D);
333
334 // hrleVectorType<T,D> normal=NormalVector(c); //normalvector
335 // calculation
336
337 // determine the minimum and maximum nodes of the element, based on
338 // their coordinates
339 hrleVectorType<T, D> minNode = nodes[0];
340 hrleVectorType<T, D> maxNode = nodes[0];
341 for (int i = 1; i < D; ++i) {
342 minNode = Min(minNode, nodes[i]);
343 maxNode = Max(maxNode, nodes[i]);
344 }
345
346 // find indices which describe the triangle
347 hrleVectorType<hrleIndexType, D> minIndex, maxIndex;
348 for (int q = 0; q < D; q++) {
349 minIndex[q] =
350 static_cast<hrleIndexType>(std::ceil(minNode[q] / gridDelta));
351 maxIndex[q] =
352 static_cast<hrleIndexType>(std::floor(maxNode[q] / gridDelta));
353 }
354
355 // Only iterate over indices which are actually inside the domain
356 // if boundary conditions should be ignored
357 for (unsigned i = 0; i < D; ++i) {
358 if (removeBoundaries[i]) {
359 minIndex[i] = std::max(minIndex[i], grid.getMinIndex(i));
360 // for Periodic BNC, MaxGridPoint is MaxIndex-1
361 maxIndex[i] = std::min(maxIndex[i], grid.getMaxGridPoint(i));
362 }
363 }
364
365 // each cartesian direction
366 for (int z = 0; z < D; z++) {
367 hrleVectorType<hrleIndexType, D - 1> min_bb, max_bb;
368
369 for (int h = 0; h < D - 1; ++h) {
370 min_bb[h] = minIndex[(z + h + 1) % D];
371 max_bb[h] = maxIndex[(z + h + 1) % D];
372 }
373
374 box bb(min_bb, max_bb);
375
376 if (bb.is_empty())
377 continue;
378
379 for (typename box::iterator it_bb(bb); !it_bb.is_finished();
380 it_bb++) {
381
382 hrleVectorType<hrleIndexType, D> it_b;
383 for (int h = 0; h < D - 1; ++h)
384 it_b[(z + h + 1) % D] = (*it_bb)[h];
385
386 hrleVectorType<T, D> p;
387 for (int k = 1; k < D; k++)
388 p[(k + z) % D] = grid.gridPositionOfGlobalIndex(
389 (k + z) % D, it_b[(k + z) % D]);
390
391 T intersection;
392 int intersection_status = calculateGridlineTriangleIntersection(
393 p, nodes, z, intersection);
394
395 if (intersection_status != 0) {
396 // if there is an intersection
397 assert(intersection >= minNode[z] &&
398 "Intersection should be inside Domain!");
399 assert(intersection <= maxNode[z] &&
400 "Intersection should be inside Domain!");
401 // intersection = std::max(intersection, minNode[z]);
402 // intersection = std::min(intersection, maxNode[z]);
403
404 if (removeBoundaries[z] &&
405 intersection > gridDelta * (grid.getMaxIndex(z)))
406 continue;
407 if (removeBoundaries[z] &&
408 intersection < grid.getMinLocalCoordinate(z))
409 continue;
410
411 T intersection2 =
412 grid.globalCoordinate2LocalIndex(z, intersection);
413
414 hrleIndexType floor = static_cast<hrleIndexType>(
415 std::floor(intersection2 - distanceEps));
416 hrleIndexType ceil = static_cast<hrleIndexType>(
417 std::ceil(intersection2 + distanceEps));
418
419 floor = std::max(floor, minIndex[z] - 1);
420 ceil = std::min(ceil, maxIndex[z] + 1);
421 floor = std::max(floor, grid.getMinIndex(z));
422 ceil = std::min(ceil, grid.getMaxIndex(z));
423
424 if (!removeBoundaries[z]) {
425 floor = grid.globalIndex2LocalIndex(z, floor);
426 ceil = grid.globalIndex2LocalIndex(z, ceil);
427 }
428
429 hrleVectorType<T, D> t = center;
430 t[z] -= intersection;
431 for (int k = 1; k < D; k++)
432 t[(z + k) % D] -= p[(z + k) % D];
433 t = Normalize(t);
434
435 for (it_b[z] = floor; it_b[z] <= ceil; ++(it_b[z])) {
436
437 T RealDistance = it_b[z] - intersection2;
438
439 T SignDistance = RealDistance;
440
441 SignDistance -= signEps * t[z];
442
443 if (intersection_status < 0) {
444 RealDistance = -RealDistance;
445 SignDistance = -SignDistance;
446 }
447
448 if (RealDistance < 0.)
449 SignDistance = -SignDistance;
450
451 RealDistance *= (1. - distanceEps * 1e-3);
452 if (RealDistance > 1.)
453 RealDistance = 1.;
454 if (RealDistance < -1.)
455 RealDistance = -1.;
456
457 if (RealDistance == 0.)
458 RealDistance = 0.; // to avoid zeros with negative sign
459
460 points.push_back(
461 std::make_pair(grid.globalIndices2LocalIndices(it_b),
462 std::make_pair(SignDistance, RealDistance)));
463 }
464 }
465 }
466 }
467 }
468
469 std::sort(points.begin(), points.end()); // sort points lexicographically
470
471 // setup list of index/distance pairs for level set initialization
472 typename point_vector::iterator it_points = points.begin();
473 while (it_points != points.end()) {
474 hrleVectorType<hrleIndexType, D> tmp = it_points->first;
475 points2.push_back(
476 std::make_pair(it_points->first, it_points->second.second));
477
478 do {
479 ++it_points;
480 } while ((it_points != points.end()) && (it_points->first == tmp));
481 }
482 }
483
484 levelSet->insertPoints(points2); // initialize level set function
485 levelSet->getDomain().segment(); // distribute points evenly across threads
486 levelSet->finalize(2);
487 }
488};
489
490// add all template specialisations for this class
491PRECOMPILE_PRECISION_DIMENSION(FromSurfaceMesh)
492
493} // namespace viennals
Class containing all information about the level set, including the dimensions of the domain,...
Definition lsDomain.hpp:28
Iterator over all grid points, contained by a box.
Definition lsFromSurfaceMesh.hpp:62
iterator & operator++()
Definition lsFromSurfaceMesh.hpp:69
const hrleVectorType< hrleIndexType, D - 1 > & operator*() const
Definition lsFromSurfaceMesh.hpp:92
iterator operator++(int)
Definition lsFromSurfaceMesh.hpp:84
iterator(const box &bx)
Definition lsFromSurfaceMesh.hpp:67
bool is_finished() const
Definition lsFromSurfaceMesh.hpp:90
Construct a level set from an explicit mesh.
Definition lsFromSurfaceMesh.hpp:15
void setRemoveBoundaryTriangles(bool passedRemoveBoundaryTriangles)
Set whether all triangles outside of the domain should be ignored (=true) or whether boundary conditi...
Definition lsFromSurfaceMesh.hpp:234
void setRemoveBoundaryTriangles(std::array< bool, N > passedRemoveBoundaryTriangles)
Set whether all triangles outside of the domain should be ignored (=true) or whether boundary conditi...
Definition lsFromSurfaceMesh.hpp:243
FromSurfaceMesh(SmartPointer< Domain< T, D > > passedLevelSet, SmartPointer< Mesh< T > > passedMesh, bool passedRemoveBoundaryTriangles=true)
Definition lsFromSurfaceMesh.hpp:217
void setLevelSet(SmartPointer< Domain< T, D > > passedLevelSet)
Definition lsFromSurfaceMesh.hpp:225
void apply()
Definition lsFromSurfaceMesh.hpp:250
void setMesh(SmartPointer< Mesh< T > > passedMesh)
Definition lsFromSurfaceMesh.hpp:229
FromSurfaceMesh()
Definition lsFromSurfaceMesh.hpp:215
This class holds an explicit mesh, which is always given in 3 dimensions. If it describes a 2D mesh,...
Definition lsMesh.hpp:21
#define PRECOMPILE_PRECISION_DIMENSION(className)
Definition lsPreCompileMacros.hpp:24
Definition lsAdvect.hpp:46
constexpr int D
Definition pyWrap.cpp:65
double T
Definition pyWrap.cpp:63