ViennaLS
Loading...
Searching...
No Matches
lsFromVolumeMesh.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <map>
6
7#include <lsDomain.hpp>
9#include <lsMesh.hpp>
10
11#include <vcLogger.hpp>
12#include <vcSmartPointer.hpp>
13
14namespace viennals {
15
16using namespace viennacore;
17
22template <class T, int D> class FromVolumeMesh {
23public:
24 using LevelSetType = SmartPointer<Domain<T, D>>;
25 using LevelSetsType = std::vector<LevelSetType>;
27
28private:
29 LevelSetsType levelSets;
30 SmartPointer<Mesh<T>> mesh = nullptr;
31 GridType grid;
32 bool removeBoundaryTriangles = true;
33 bool gridSet = false;
34
35public:
36 FromVolumeMesh() = default;
37
38 FromVolumeMesh(const GridType &passedGrid, SmartPointer<Mesh<T>> passedMesh,
39 bool passedRemoveBoundaryTriangles = true)
40 : mesh(passedMesh), grid(passedGrid),
41 removeBoundaryTriangles(passedRemoveBoundaryTriangles), gridSet(true) {}
42
43 void setGrid(const GridType &passedGrid) {
44 grid = passedGrid;
45 gridSet = true;
46 }
47
48 void setMesh(SmartPointer<Mesh<T>> passedMesh) { mesh = passedMesh; }
49
50 void setRemoveBoundaryTriangles(bool passedRemoveBoundaryTriangles) {
51 removeBoundaryTriangles = passedRemoveBoundaryTriangles;
52 }
53
54 std::vector<LevelSetType> getLevelSets() const { return levelSets; }
55
56 void apply() {
57 if (!gridSet) {
58 Logger::getInstance()
59 .addWarning("No grid has been set in FromVolumeMesh.")
60 .print();
61 return;
62 }
63 if (mesh == nullptr) {
64 Logger::getInstance()
65 .addWarning("No mesh was passed to FromVolumeMesh.")
66 .print();
67 return;
68 }
69
70 // get the unique material numbers for explicit booling
71 std::vector<int> materialInts;
72 typename PointData<T>::ScalarDataType *materialData =
73 mesh->cellData.getScalarData("Material", true);
74 if (materialData != nullptr) {
75 // make unique list of materialIds
76 materialInts =
77 std::vector<int>(materialData->begin(), materialData->end());
78 std::sort(materialInts.begin(), materialInts.end());
79 auto it = std::unique(materialInts.begin(), materialInts.end());
80 materialInts.erase(it, materialInts.end());
81 } else {
82 // no materials are defined
83 materialInts.push_back(0);
84 }
85
86 // Map for all surfaceElements and their corresponding material
87 typedef std::map<VectorType<unsigned int, D>, std::pair<int, int>>
88 triangleMapType;
89 triangleMapType surfaceElements;
90
91 unsigned numberOfElements =
92 (D == 3) ? mesh->tetras.size() : mesh->triangles.size();
93 for (unsigned int i = 0; i < numberOfElements; ++i) {
94 for (int j = 0; j < D + 1; j++) {
95 VectorType<unsigned int, D> currentSurfaceElement;
96 for (int k = 0; k < D; k++) {
97 currentSurfaceElement[k] =
98 mesh->template getElements<D + 1>()[i][(j + k) % (D + 1)];
99 }
100
101 // std::bitset<2 * D> flags;
102 // flags.set();
103 //
104 // // if triangle at border skip
105 // for (int k = 0; k < D; k++) {
106 // for (int l = 0; l < D; l++) {
107 // if (mesh->nodes[currentSurfaceElement[k]][l] < Geometry.Max[l] -
108 // eps) {
109 // flags.reset(l + D);
110 // }
111 // if (mesh->nodes[currentSurfaceElement[k]][l] > Geometry.Min[l] +
112 // eps) {
113 // flags.reset(l);
114 // }
115 // }
116 // }
117 //
118 // flags &= remove_flags;
119
120 // if (is_open_boundary_negative) flags.reset(open_boundary_direction);
121 // else flags.reset(open_boundary_direction+D);
122 //
123 // if (flags.any())
124 // continue;
125
126 // currentSurfaceElement.sort();
127 std::sort(currentSurfaceElement.begin(), currentSurfaceElement.end());
128
129 Vec3D<T> currentElementPoints[D + 1];
130 for (int k = 0; k < D; k++) {
131 currentElementPoints[k] = mesh->nodes[currentSurfaceElement[k]];
132 }
133
134 // get the other point of the element as well
135 currentElementPoints[D] =
136 mesh->nodes[mesh->template getElements<D + 1>()[i]
137 [(j + D) % (D + 1)]];
138
139 typename triangleMapType::iterator it =
140 surfaceElements.lower_bound(currentSurfaceElement);
141 if ((it != surfaceElements.end()) &&
142 (it->first == currentSurfaceElement)) {
143 if (Orientation(currentElementPoints)) {
144 if (it->second.second != materialInts.back() + 1) {
145 Logger::getInstance()
146 .addWarning(
147 "Coinciding surface elements with same orientation in "
148 "Element: " +
149 std::to_string(i))
150 .print();
151 }
152 it->second.second =
153 (materialData == nullptr) ? 0 : (*materialData)[i];
154 } else {
155 if (it->second.first != materialInts.back() + 1) {
156 Logger::getInstance()
157 .addWarning(
158 "Coinciding surface elements with same orientation in "
159 "Element: " +
160 std::to_string(i))
161 .print();
162 }
163 it->second.first =
164 (materialData == nullptr) ? 0 : (*materialData)[i];
165 }
166
167 if (it->second.first == it->second.second)
168 surfaceElements.erase(it);
169
170 } else {
171 if (Orientation(currentElementPoints)) {
172 surfaceElements.insert(
173 it, std::make_pair(currentSurfaceElement,
174 std::make_pair(materialInts.back() + 1,
175 (materialData == nullptr)
176 ? 0
177 : (*materialData)[i])));
178 } else {
179 surfaceElements.insert(
180 it, std::make_pair(currentSurfaceElement,
181 std::make_pair((materialData == nullptr)
182 ? 0
183 : (*materialData)[i],
184 materialInts.back() + 1)));
185 }
186 }
187 }
188 }
189
190 // for all materials/for each surface
191 // resize to empty levelsets, but they need grid information
192 {
193 levelSets.clear();
194 for (unsigned i = 0; i < materialInts.size(); ++i) {
195 auto ls = LevelSetType::New(grid);
196 levelSets.push_back(ls);
197 }
198 }
199
200 auto levelSetIterator = levelSets.begin();
201 for (int &materialInt : materialInts) {
202 auto currentSurface = SmartPointer<Mesh<T>>::New();
203 auto &meshElements = currentSurface->template getElements<D>();
204 for (auto it = surfaceElements.begin(); it != surfaceElements.end();
205 ++it) {
206 if ((materialInt >= it->second.first) &&
207 (materialInt < it->second.second)) {
208 std::array<unsigned, D> element{it->first[0], it->first[1]};
209 if constexpr (D == 3)
210 element[2] = it->first[2];
211 meshElements.push_back(element);
212 } else if ((materialInt >= it->second.second) &&
213 (materialInt < it->second.first)) {
214 // swap first two elements since triangle has different orientation
215 std::array<unsigned, D> element{it->first[1], it->first[0]};
216 if constexpr (D == 3)
217 element[2] = it->first[2];
218 meshElements.push_back(element);
219 }
220 }
221
222 // replace Nodes of Geometry by Nodes of individual surface
223 constexpr unsigned int undefined_node =
224 std::numeric_limits<unsigned int>::max();
225 std::vector<unsigned int> nodeReplacements(mesh->nodes.size(),
226 undefined_node);
227 unsigned int NodeCounter = 0;
228
229 for (unsigned int k = 0; k < meshElements.size(); ++k) {
230 for (int h = 0; h < D; h++) {
231 unsigned int origin_node = meshElements[k][h];
232 if (nodeReplacements[origin_node] == undefined_node) {
233 nodeReplacements[origin_node] = NodeCounter++;
234 currentSurface->nodes.push_back(mesh->nodes[origin_node]);
235 }
236 meshElements[k][h] = nodeReplacements[origin_node];
237 }
238 }
239
240 // create level set from surface
241 FromSurfaceMesh<T, D>(*levelSetIterator, currentSurface,
242 removeBoundaryTriangles)
243 .apply();
244
245 ++levelSetIterator;
246 }
247 }
248};
249
250// add all template specialisations for this class
251PRECOMPILE_PRECISION_DIMENSION(FromVolumeMesh)
252
253} // namespace viennals
viennahrle::Grid< D > GridType
Definition lsDomain.hpp:31
Construct a level set from an explicit mesh.
Definition lsFromSurfaceMesh.hpp:15
void apply()
Definition lsFromSurfaceMesh.hpp:243
std::vector< LevelSetType > LevelSetsType
Definition lsFromVolumeMesh.hpp:25
typename Domain< T, D >::GridType GridType
Definition lsFromVolumeMesh.hpp:26
void apply()
Definition lsFromVolumeMesh.hpp:56
std::vector< LevelSetType > getLevelSets() const
Definition lsFromVolumeMesh.hpp:54
FromVolumeMesh(const GridType &passedGrid, SmartPointer< Mesh< T > > passedMesh, bool passedRemoveBoundaryTriangles=true)
Definition lsFromVolumeMesh.hpp:38
void setMesh(SmartPointer< Mesh< T > > passedMesh)
Definition lsFromVolumeMesh.hpp:48
void setGrid(const GridType &passedGrid)
Definition lsFromVolumeMesh.hpp:43
void setRemoveBoundaryTriangles(bool passedRemoveBoundaryTriangles)
Definition lsFromVolumeMesh.hpp:50
SmartPointer< Domain< T, D > > LevelSetType
Definition lsFromVolumeMesh.hpp:24
This class holds an explicit mesh, which is always given in 3 dimensions. If it describes a 2D mesh,...
Definition lsMesh.hpp:21
std::vector< T > ScalarDataType
Definition lsPointData.hpp:22
#define PRECOMPILE_PRECISION_DIMENSION(className)
Definition lsPreCompileMacros.hpp:24
Definition lsAdvect.hpp:36
constexpr int D
Definition pyWrap.cpp:70