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:
37
38 FromVolumeMesh(const GridType &passedGrid, SmartPointer<Mesh<T>> passedMesh,
39 bool passedRemoveBoundaryTriangles = true)
40 : grid(passedGrid), mesh(passedMesh),
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<hrleVectorType<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 hrleVectorType<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
128 hrleVectorType<double, D> currentElementPoints[D + 1];
129 for (int k = 0; k < D; k++) {
130 currentElementPoints[k] = mesh->nodes[currentSurfaceElement[k]];
131 }
132
133 // get the other point of the element as well
134 currentElementPoints[D] =
135 mesh->nodes[mesh->template getElements<D + 1>()[i]
136 [(j + D) % (D + 1)]];
137
138 typename triangleMapType::iterator it =
139 surfaceElements.lower_bound(currentSurfaceElement);
140 if ((it != surfaceElements.end()) &&
141 (it->first == currentSurfaceElement)) {
142 if (Orientation(currentElementPoints)) {
143 if (it->second.second != materialInts.back() + 1) {
144 Logger::getInstance()
145 .addWarning(
146 "Coinciding surface elements with same orientation in "
147 "Element: " +
148 std::to_string(i))
149 .print();
150 }
151 it->second.second =
152 (materialData == nullptr) ? 0 : (*materialData)[i];
153 } else {
154 if (it->second.first != materialInts.back() + 1) {
155 Logger::getInstance()
156 .addWarning(
157 "Coinciding surface elements with same orientation in "
158 "Element: " +
159 std::to_string(i))
160 .print();
161 }
162 it->second.first =
163 (materialData == nullptr) ? 0 : (*materialData)[i];
164 }
165
166 if (it->second.first == it->second.second)
167 surfaceElements.erase(it);
168
169 } else {
170 if (Orientation(currentElementPoints)) {
171 surfaceElements.insert(
172 it, std::make_pair(currentSurfaceElement,
173 std::make_pair(materialInts.back() + 1,
174 (materialData == nullptr)
175 ? 0
176 : (*materialData)[i])));
177 } else {
178 surfaceElements.insert(
179 it, std::make_pair(currentSurfaceElement,
180 std::make_pair((materialData == nullptr)
181 ? 0
182 : (*materialData)[i],
183 materialInts.back() + 1)));
184 }
185 }
186 }
187 }
188
189 // for all materials/for each surface
190 // resize to empty levelsets, but they need grid information
191 {
192 levelSets.clear();
193 for (unsigned i = 0; i < materialInts.size(); ++i) {
194 auto ls = LevelSetType::New(grid);
195 levelSets.push_back(ls);
196 }
197 }
198
199 auto levelSetIterator = levelSets.begin();
200 for (auto matIt = materialInts.begin(); matIt != materialInts.end();
201 ++matIt) {
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 (((*matIt) >= it->second.first) && ((*matIt) < it->second.second)) {
207 std::array<unsigned, D> element{it->first[0], it->first[1]};
208 if constexpr (D == 3)
209 element[2] = it->first[2];
210 meshElements.push_back(element);
211 } else if (((*matIt) >= it->second.second) &&
212 ((*matIt) < it->second.first)) {
213 // swap first two elements since triangle has different orientation
214 std::array<unsigned, D> element{it->first[1], it->first[0]};
215 if constexpr (D == 3)
216 element[2] = it->first[2];
217 meshElements.push_back(element);
218 }
219 }
220
221 // replace Nodes of Geometry by Nodes of individual surface
222 const unsigned int undefined_node =
223 std::numeric_limits<unsigned int>::max();
224 std::vector<unsigned int> nodeReplacements(mesh->nodes.size(),
225 undefined_node);
226 unsigned int NodeCounter = 0;
227
228 for (unsigned int k = 0; k < meshElements.size(); ++k) {
229 for (int h = 0; h < D; h++) {
230 unsigned int origin_node = meshElements[k][h];
231 if (nodeReplacements[origin_node] == undefined_node) {
232 nodeReplacements[origin_node] = NodeCounter++;
233 currentSurface->nodes.push_back(mesh->nodes[origin_node]);
234 }
235 meshElements[k][h] = nodeReplacements[origin_node];
236 }
237 }
238
239 // create level set from surface
240 FromSurfaceMesh<T, D>(*levelSetIterator, currentSurface,
241 removeBoundaryTriangles)
242 .apply();
243
244 ++levelSetIterator;
245 }
246 }
247};
248
249// add all template specialisations for this class
250PRECOMPILE_PRECISION_DIMENSION(FromVolumeMesh)
251
252} // namespace viennals
hrleGrid< D > GridType
Definition lsDomain.hpp:32
Construct a level set from an explicit mesh.
Definition lsFromSurfaceMesh.hpp:15
void apply()
Definition lsFromSurfaceMesh.hpp:250
This class creates a level set from a tetrahedral mesh. If the mesh contains a scalar data array call...
Definition lsFromVolumeMesh.hpp:22
std::vector< LevelSetType > LevelSetsType
Definition lsFromVolumeMesh.hpp:25
typename Domain< T, D >::GridType GridType
Definition lsFromVolumeMesh.hpp:26
FromVolumeMesh()
Definition lsFromVolumeMesh.hpp:36
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:46
constexpr int D
Definition pyWrap.cpp:65