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 = std::distance(newNodes.begin(), it);
183 duplicates.emplace_back(i, nodeId);
184 } else {
185 if (adjusted)
186 duplicates.push_back(std::make_pair(i, newNodes.size()));
187 newNodes.push_back(nodes[i]);
188 }
189 }
190 nodes = newNodes;
191
192 // now replace in vertices
193 // TODO also need to shift down all other nodes
194 for (auto &duplicate : duplicates) {
195 replaceNode(vertices, duplicate);
196 replaceNode(lines, duplicate);
197 replaceNode(triangles, duplicate);
198 replaceNode(tetras, duplicate);
199 replaceNode(hexas, duplicate);
200 }
201 }
202
203 void append(const Mesh<T> &passedMesh) {
204 const unsigned numberOfOldNodes = nodes.size();
205
206 // append new nodes
207 nodes.insert(nodes.end(), passedMesh.nodes.begin(), passedMesh.nodes.end());
208
209 // go through all elements and increase node IDs to match new IDS
210 const unsigned numberOfVertices = vertices.size();
211 vertices.insert(vertices.end(), passedMesh.vertices.begin(),
212 passedMesh.vertices.end());
213 for (unsigned i = numberOfVertices;
214 i < passedMesh.vertices.size() + numberOfVertices; ++i) {
215 vertices[i][0] += numberOfOldNodes;
216 }
217
218 const unsigned numberOfLines = lines.size();
219 lines.insert(lines.end(), passedMesh.lines.begin(), passedMesh.lines.end());
220 for (unsigned i = numberOfLines;
221 i < passedMesh.lines.size() + numberOfLines; ++i) {
222 for (unsigned d = 0; d < 2; ++d) {
223 lines[i][d] += numberOfOldNodes;
224 }
225 }
226
227 const unsigned numberOfTriangles = triangles.size();
228 triangles.insert(triangles.end(), passedMesh.triangles.begin(),
229 passedMesh.triangles.end());
230 for (unsigned i = numberOfTriangles;
231 i < passedMesh.triangles.size() + numberOfTriangles; ++i) {
232 for (unsigned d = 0; d < 3; ++d) {
233 triangles[i][d] += numberOfOldNodes;
234 }
235 }
236
237 const unsigned numberOfTetras = tetras.size();
238 tetras.insert(tetras.end(), passedMesh.tetras.begin(),
239 passedMesh.tetras.end());
240 for (unsigned i = numberOfTetras;
241 i < passedMesh.tetras.size() + numberOfTetras; ++i) {
242 for (unsigned d = 0; d < 4; ++d) {
243 tetras[i][d] += numberOfOldNodes;
244 }
245 }
246
247 const unsigned numberOfHexas = hexas.size();
248 hexas.insert(hexas.end(), passedMesh.hexas.begin(), passedMesh.hexas.end());
249 for (unsigned i = numberOfHexas;
250 i < passedMesh.hexas.size() + numberOfHexas; ++i) {
251 for (unsigned d = 0; d < 8; ++d) {
252 hexas[i][d] += numberOfOldNodes;
253 }
254 }
255
256 // Append data
257 // TODO need to adjust lsVTKWriter to deal with different data correctly
258 // currently this only works for vertex only meshes
259 pointData.append(passedMesh.pointData);
260 cellData.append(passedMesh.cellData);
261
262 // if(lsPointData<T>::scalarData.size() < nodes.size())
263 for (unsigned i = 0; i < pointData.getScalarDataSize(); ++i) {
264 pointData.getScalarData(i)->resize(vertices.size());
265 }
266 for (unsigned i = 0; i < pointData.getVectorDataSize(); ++i) {
267 pointData.getVectorData(i)->resize(vertices.size());
268 }
269
270 for (unsigned i = 0; i < cellData.getScalarDataSize(); ++i) {
271 cellData.getScalarData(i)->resize(vertices.size());
272 }
273 for (unsigned i = 0; i < cellData.getVectorDataSize(); ++i) {
274 cellData.getVectorData(i)->resize(vertices.size());
275 }
276 }
277
278 void clear() {
279 nodes.clear();
280 vertices.clear();
281 lines.clear();
282 triangles.clear();
283 tetras.clear();
284 hexas.clear();
285 pointData.clear();
286 cellData.clear();
287 minimumExtent = Vec3D<T>{};
288 maximumExtent = Vec3D<T>{};
289 }
290
291 void print() {
292 std::cout << "Mesh:" << std::endl;
293 std::cout << "Number of Nodes: " << nodes.size() << std::endl;
294 if (!vertices.empty())
295 std::cout << "Number of Vertices: " << vertices.size() << std::endl;
296 if (!lines.empty())
297 std::cout << "Number of Lines: " << lines.size() << std::endl;
298 if (!triangles.empty())
299 std::cout << "Number of Triangles: " << triangles.size() << std::endl;
300 if (!tetras.empty())
301 std::cout << "Number of Tetrahedrons: " << tetras.size() << std::endl;
302 if (!hexas.empty())
303 std::cout << "Number of Hexas: " << hexas.size() << std::endl;
304 // pointData
305 if (pointData.getScalarDataSize() > 0) {
306 std::cout << "Scalar data:" << std::endl;
307 for (unsigned i = 0; i < pointData.getScalarDataSize(); ++i) {
308 std::cout << " \"" << pointData.getScalarDataLabel(i) << "\" of size "
309 << pointData.getScalarData(i)->size() << std::endl;
310 }
311 }
312 if (pointData.getVectorDataSize() > 0) {
313 std::cout << "Vector data:" << std::endl;
314 for (unsigned i = 0; i < pointData.getVectorDataSize(); ++i) {
315 std::cout << " \"" << pointData.getVectorDataLabel(i) << "\" of size "
316 << pointData.getVectorData(i)->size() << std::endl;
317 }
318 }
319
320 // cellData
321 if (cellData.getScalarDataSize() > 0) {
322 std::cout << "Scalar data:" << std::endl;
323 for (unsigned i = 0; i < cellData.getScalarDataSize(); ++i) {
324 std::cout << " \"" << cellData.getScalarDataLabel(i) << "\" of size "
325 << cellData.getScalarData(i)->size() << std::endl;
326 }
327 }
328 if (cellData.getVectorDataSize() > 0) {
329 std::cout << "Vector data:" << std::endl;
330 for (unsigned i = 0; i < cellData.getVectorDataSize(); ++i) {
331 std::cout << " \"" << cellData.getVectorDataLabel(i) << "\" of size "
332 << cellData.getVectorData(i)->size() << std::endl;
333 }
334 }
335 }
336};
337
338// add all template specialisations for this class
340
341} // 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:291
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:278
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:203
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