ViennaLS
Loading...
Searching...
No Matches
lsMesh.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <array>
6#include <iostream>
7#include <vector>
8
9#include <vcPointData.hpp>
10#include <vcSmartPointer.hpp>
11#include <vcVectorType.hpp>
12
13namespace viennals {
14
15using namespace viennacore;
16
21template <class T = double> class Mesh {
22public:
23 std::vector<Vec3D<T>> nodes;
24 std::vector<std::array<unsigned, 1>> vertices;
25 std::vector<std::array<unsigned, 2>> lines;
26 std::vector<std::array<unsigned, 3>> triangles;
27 std::vector<std::array<unsigned, 4>> tetras;
28 std::vector<std::array<unsigned, 8>> hexas;
29 PointData<T> pointData;
30 PointData<T> cellData;
31 Vec3D<T> minimumExtent{};
32 Vec3D<T> maximumExtent{};
33
34 constexpr static const char *materialIdsLabel = "MaterialIds";
35 constexpr static const char *normalsLabel = "Normals";
36
37private:
38 // iterator typedef
39 using VectorIt = typename PointData<T>::VectorDataType::iterator;
40 // find function to avoid including the whole algorithm header
41 static VectorIt find(VectorIt first, VectorIt last, const Vec3D<T> &value) {
42 for (; first != last; ++first) {
43 if (*first == value) {
44 return first;
45 }
46 }
47 return last;
48 }
49
50 // helper function for duplicate removal
51 template <class ElementType>
52 static void replaceNode(ElementType &elements,
53 std::pair<unsigned, unsigned> node) {
54 for (unsigned i = 0; i < elements.size(); ++i) {
55 for (unsigned j = 0; j < elements[i].size(); ++j) {
56 if (elements[i][j] == node.first) {
57 elements[i][j] = node.second;
58 }
59 }
60 }
61 };
62
63public:
64 // Convenience function to create a new mesh smart pointer.
65 static auto New() { return SmartPointer<Mesh>::New(); }
66
67 const std::vector<Vec3D<T>> &getNodes() const { return nodes; }
68
69 std::vector<Vec3D<T>> &getNodes() { return nodes; }
70
71 template <int D, std::enable_if_t<D == 1, int> = 0>
72 std::vector<std::array<unsigned, D>> &getElements() {
73 return vertices;
74 }
75
76 template <int D, std::enable_if_t<D == 2, int> = 0>
77 std::vector<std::array<unsigned, D>> &getElements() {
78 return lines;
79 }
80
81 template <int D, std::enable_if_t<D == 3, int> = 0>
82 std::vector<std::array<unsigned, D>> &getElements() {
83 return triangles;
84 }
85
86 template <int D, std::enable_if_t<D == 4, int> = 0>
87 std::vector<std::array<unsigned, D>> &getElements() {
88 return tetras;
89 }
90
91 template <int D, std::enable_if_t<D == 8, int> = 0>
92 std::vector<std::array<unsigned, D>> &getElements() {
93 return hexas;
94 }
95
96 PointData<T> &getPointData() { return pointData; }
97
98 const PointData<T> &getPointData() const { return pointData; }
99
100 PointData<T> &getCellData() { return cellData; }
101
102 const PointData<T> &getCellData() const { return cellData; }
103
104 // helper function to get normals
105 std::vector<Vec3D<T>> *getNormals(const char *label = normalsLabel) {
106 return cellData.getVectorData(label);
107 }
108
109 // helper function to get material ids
110 std::vector<T> *getMaterialIds(const char *label = materialIdsLabel) {
111 return cellData.getScalarData(label);
112 }
113
114 unsigned insertNextNode(const Vec3D<T> &node) {
115 nodes.push_back(node);
116 return nodes.size() - 1;
117 }
118
119 unsigned insertNextVertex(const std::array<unsigned, 1> &vertex) {
120 vertices.push_back(vertex);
121 return vertices.size() - 1;
122 }
123
124 unsigned insertNextLine(const std::array<unsigned, 2> &line) {
125 lines.push_back(line);
126 return lines.size() - 1;
127 }
128
129 unsigned insertNextTriangle(const std::array<unsigned, 3> &triangle) {
130 triangles.push_back(triangle);
131 return triangles.size() - 1;
132 }
133
134 unsigned insertNextTetra(const std::array<unsigned, 4> &tetra) {
135 tetras.push_back(tetra);
136 return tetras.size() - 1;
137 }
138
139 unsigned insertNextHexa(const std::array<unsigned, 8> &hexa) {
140 hexas.push_back(hexa);
141 return hexas.size() - 1;
142 }
143
144 unsigned insertNextElement(const std::array<unsigned, 1> &vertex) {
145 vertices.push_back(vertex);
146 return vertices.size() - 1;
147 }
148
149 unsigned insertNextElement(const std::array<unsigned, 2> &line) {
150 lines.push_back(line);
151 return lines.size() - 1;
152 }
153
154 unsigned insertNextElement(const std::array<unsigned, 3> &triangle) {
155 triangles.push_back(triangle);
156 return triangles.size() - 1;
157 }
158
159 unsigned insertNextElement(const std::array<unsigned, 4> &tetra) {
160 tetras.push_back(tetra);
161 return tetras.size() - 1;
162 }
163
164 unsigned insertNextElement(const std::array<unsigned, 8> &hexa) {
165 hexas.push_back(hexa);
166 return hexas.size() - 1;
167 }
168
170 std::vector<Vec3D<T>> newNodes;
171 // can just push first point since it cannot be duplicate
172 newNodes.push_back(nodes[0]);
173 // now check for duplicates
174 // pair of oldId <-> newId
175 std::vector<std::pair<unsigned, unsigned>> duplicates;
176 bool adjusted = false;
177 for (unsigned i = 1; i < nodes.size(); ++i) {
178 auto it = find(newNodes.begin(), newNodes.end(), nodes[i]);
179 if (it != newNodes.end()) {
180 adjusted = true;
181 // if duplicate point, save it to be replaced
182 unsigned nodeId =
183 static_cast<unsigned>(std::distance(newNodes.begin(), it));
184 duplicates.emplace_back(i, nodeId);
185 } else {
186 if (adjusted)
187 duplicates.emplace_back(i, static_cast<unsigned>(newNodes.size()));
188 newNodes.push_back(nodes[i]);
189 }
190 }
191 nodes = newNodes;
192
193 // now replace in vertices
194 // TODO also need to shift down all other nodes
195 for (auto &duplicate : duplicates) {
196 replaceNode(vertices, duplicate);
197 replaceNode(lines, duplicate);
198 replaceNode(triangles, duplicate);
199 replaceNode(tetras, duplicate);
200 replaceNode(hexas, duplicate);
201 }
202 }
203
204 void append(const Mesh<T> &passedMesh) {
205 const unsigned numberOfOldNodes = nodes.size();
206
207 // append new nodes
208 nodes.insert(nodes.end(), passedMesh.nodes.begin(), passedMesh.nodes.end());
209
210 // go through all elements and increase node IDs to match new IDS
211 const unsigned numberOfVertices = vertices.size();
212 vertices.insert(vertices.end(), passedMesh.vertices.begin(),
213 passedMesh.vertices.end());
214 for (unsigned i = numberOfVertices;
215 i < passedMesh.vertices.size() + numberOfVertices; ++i) {
216 vertices[i][0] += numberOfOldNodes;
217 }
218
219 const unsigned numberOfLines = lines.size();
220 lines.insert(lines.end(), passedMesh.lines.begin(), passedMesh.lines.end());
221 for (unsigned i = numberOfLines;
222 i < passedMesh.lines.size() + numberOfLines; ++i) {
223 for (unsigned d = 0; d < 2; ++d) {
224 lines[i][d] += numberOfOldNodes;
225 }
226 }
227
228 const unsigned numberOfTriangles = triangles.size();
229 triangles.insert(triangles.end(), passedMesh.triangles.begin(),
230 passedMesh.triangles.end());
231 for (unsigned i = numberOfTriangles;
232 i < passedMesh.triangles.size() + numberOfTriangles; ++i) {
233 for (unsigned d = 0; d < 3; ++d) {
234 triangles[i][d] += numberOfOldNodes;
235 }
236 }
237
238 const unsigned numberOfTetras = tetras.size();
239 tetras.insert(tetras.end(), passedMesh.tetras.begin(),
240 passedMesh.tetras.end());
241 for (unsigned i = numberOfTetras;
242 i < passedMesh.tetras.size() + numberOfTetras; ++i) {
243 for (unsigned d = 0; d < 4; ++d) {
244 tetras[i][d] += numberOfOldNodes;
245 }
246 }
247
248 const unsigned numberOfHexas = hexas.size();
249 hexas.insert(hexas.end(), passedMesh.hexas.begin(), passedMesh.hexas.end());
250 for (unsigned i = numberOfHexas;
251 i < passedMesh.hexas.size() + numberOfHexas; ++i) {
252 for (unsigned d = 0; d < 8; ++d) {
253 hexas[i][d] += numberOfOldNodes;
254 }
255 }
256
257 // Append data
258 // TODO need to adjust lsVTKWriter to deal with different data correctly
259 // currently this only works for vertex only meshes
260 pointData.append(passedMesh.pointData);
261 cellData.append(passedMesh.cellData);
262
263 // if(lsPointData<T>::scalarData.size() < nodes.size())
264 for (unsigned i = 0; i < pointData.getScalarDataSize(); ++i) {
265 pointData.getScalarData(i)->resize(vertices.size());
266 }
267 for (unsigned i = 0; i < pointData.getVectorDataSize(); ++i) {
268 pointData.getVectorData(i)->resize(vertices.size());
269 }
270
271 for (unsigned i = 0; i < cellData.getScalarDataSize(); ++i) {
272 cellData.getScalarData(i)->resize(vertices.size());
273 }
274 for (unsigned i = 0; i < cellData.getVectorDataSize(); ++i) {
275 cellData.getVectorData(i)->resize(vertices.size());
276 }
277 }
278
279 void clear() {
280 nodes.clear();
281 vertices.clear();
282 lines.clear();
283 triangles.clear();
284 tetras.clear();
285 hexas.clear();
286 pointData.clear();
287 cellData.clear();
288 minimumExtent = Vec3D<T>{};
289 maximumExtent = Vec3D<T>{};
290 }
291
292 void print() {
293 std::cout << "Mesh:" << std::endl;
294 std::cout << "Number of Nodes: " << nodes.size() << std::endl;
295 if (!vertices.empty())
296 std::cout << "Number of Vertices: " << vertices.size() << std::endl;
297 if (!lines.empty())
298 std::cout << "Number of Lines: " << lines.size() << std::endl;
299 if (!triangles.empty())
300 std::cout << "Number of Triangles: " << triangles.size() << std::endl;
301 if (!tetras.empty())
302 std::cout << "Number of Tetrahedrons: " << tetras.size() << std::endl;
303 if (!hexas.empty())
304 std::cout << "Number of Hexas: " << hexas.size() << std::endl;
305 // pointData
306 if (pointData.getScalarDataSize() > 0) {
307 std::cout << "Scalar data:" << std::endl;
308 for (unsigned i = 0; i < pointData.getScalarDataSize(); ++i) {
309 std::cout << " \"" << pointData.getScalarDataLabel(i) << "\" of size "
310 << pointData.getScalarData(i)->size() << std::endl;
311 }
312 }
313 if (pointData.getVectorDataSize() > 0) {
314 std::cout << "Vector data:" << std::endl;
315 for (unsigned i = 0; i < pointData.getVectorDataSize(); ++i) {
316 std::cout << " \"" << pointData.getVectorDataLabel(i) << "\" of size "
317 << pointData.getVectorData(i)->size() << std::endl;
318 }
319 }
320
321 // cellData
322 if (cellData.getScalarDataSize() > 0) {
323 std::cout << "Scalar data:" << std::endl;
324 for (unsigned i = 0; i < cellData.getScalarDataSize(); ++i) {
325 std::cout << " \"" << cellData.getScalarDataLabel(i) << "\" of size "
326 << cellData.getScalarData(i)->size() << std::endl;
327 }
328 }
329 if (cellData.getVectorDataSize() > 0) {
330 std::cout << "Vector data:" << std::endl;
331 for (unsigned i = 0; i < cellData.getVectorDataSize(); ++i) {
332 std::cout << " \"" << cellData.getVectorDataLabel(i) << "\" of size "
333 << cellData.getVectorData(i)->size() << std::endl;
334 }
335 }
336 }
337};
338
339// add all template specialisations for this class
341
342} // namespace viennals
This class holds an explicit mesh, which is always given in 3 dimensions. If it describes a 2D mesh,...
Definition lsMesh.hpp:21
PointData< T > pointData
Definition lsMesh.hpp:29
unsigned insertNextElement(const std::array< unsigned, 3 > &triangle)
Definition lsMesh.hpp:154
unsigned insertNextElement(const std::array< unsigned, 4 > &tetra)
Definition lsMesh.hpp:159
const PointData< T > & getPointData() const
Definition lsMesh.hpp:98
static constexpr const char * normalsLabel
Definition lsMesh.hpp:35
std::vector< std::array< unsigned, 8 > > hexas
Definition lsMesh.hpp:28
unsigned insertNextNode(const Vec3D< T > &node)
Definition lsMesh.hpp:114
void removeDuplicateNodes()
Definition lsMesh.hpp:169
Vec3D< T > minimumExtent
Definition lsMesh.hpp:31
PointData< T > cellData
Definition lsMesh.hpp:30
std::vector< Vec3D< T > > & getNodes()
Definition lsMesh.hpp:69
std::vector< std::array< unsigned, 1 > > vertices
Definition lsMesh.hpp:24
static auto New()
Definition lsMesh.hpp:65
std::vector< std::array< unsigned, 2 > > lines
Definition lsMesh.hpp:25
unsigned insertNextTriangle(const std::array< unsigned, 3 > &triangle)
Definition lsMesh.hpp:129
std::vector< T > * getMaterialIds(const char *label=materialIdsLabel)
Definition lsMesh.hpp:110
unsigned insertNextHexa(const std::array< unsigned, 8 > &hexa)
Definition lsMesh.hpp:139
void print()
Definition lsMesh.hpp:292
Vec3D< T > maximumExtent
Definition lsMesh.hpp:32
std::vector< std::array< unsigned, 4 > > tetras
Definition lsMesh.hpp:27
std::vector< Vec3D< T > > nodes
Definition lsMesh.hpp:23
unsigned insertNextTetra(const std::array< unsigned, 4 > &tetra)
Definition lsMesh.hpp:134
void clear()
Definition lsMesh.hpp:279
const PointData< T > & getCellData() const
Definition lsMesh.hpp:102
std::vector< Vec3D< T > > * getNormals(const char *label=normalsLabel)
Definition lsMesh.hpp:105
unsigned insertNextElement(const std::array< unsigned, 1 > &vertex)
Definition lsMesh.hpp:144
static constexpr const char * materialIdsLabel
Definition lsMesh.hpp:34
PointData< T > & getPointData()
Definition lsMesh.hpp:96
void append(const Mesh< T > &passedMesh)
Definition lsMesh.hpp:204
PointData< T > & getCellData()
Definition lsMesh.hpp:100
const std::vector< Vec3D< T > > & getNodes() const
Definition lsMesh.hpp:67
unsigned insertNextElement(const std::array< unsigned, 2 > &line)
Definition lsMesh.hpp:149
std::vector< std::array< unsigned, 3 > > triangles
Definition lsMesh.hpp:26
unsigned insertNextVertex(const std::array< unsigned, 1 > &vertex)
Definition lsMesh.hpp:119
unsigned insertNextElement(const std::array< unsigned, 8 > &hexa)
Definition lsMesh.hpp:164
unsigned insertNextLine(const std::array< unsigned, 2 > &line)
Definition lsMesh.hpp:124
std::vector< std::array< unsigned, D > > & getElements()
Definition lsMesh.hpp:72
#define PRECOMPILE_PRECISION(className)
Definition lsPreCompileMacros.hpp:30
Definition lsAdvect.hpp:41