preCICE
Loading...
Searching...
No Matches
Mesh.cpp
Go to the documentation of this file.
1#include <Eigen/Core>
2#include <algorithm>
3#include <array>
4#include <boost/container/flat_map.hpp>
5#include <functional>
6#include <memory>
7#include <ostream>
8#include <type_traits>
9#include <utility>
10#include <vector>
11
12#include "Edge.hpp"
13#include "Mesh.hpp"
14#include "Tetrahedron.hpp"
15#include "Triangle.hpp"
16#include "logging/LogMacros.hpp"
17#include "math/geometry.hpp"
18#include "mesh/Data.hpp"
19#include "mesh/Filter.hpp"
20#include "mesh/Vertex.hpp"
22#include "query/Index.hpp"
23#include "utils/assertion.hpp"
24
25namespace precice::mesh {
26
28 std::string name,
29 int dimensions,
30 MeshID id,
31 bool isJustInTime)
32 : _name(std::move(name)),
33 _dimensions(dimensions),
34 _id(id),
36 _boundingBox(dimensions),
37 _index(*this)
38{
40 PRECICE_ASSERT(_name != std::string(""));
41}
42
44{
46 return _vertices.at(id);
47}
48
50{
52 return _vertices.at(id);
53}
54
59
61{
62 return _vertices;
63}
64
65std::size_t Mesh::nVertices() const
66{
67 return _vertices.size();
68}
69
74
76{
77 return _edges;
78}
79
84
86{
87 return _triangles;
88}
89
91{
92 return _tetrahedra;
93}
94
99
101{
102 return _dimensions;
103}
104
105Vertex &Mesh::createVertex(const Eigen::Ref<const Eigen::VectorXd> &coords)
106{
107 PRECICE_ASSERT(coords.size() == _dimensions, coords.size(), _dimensions);
108 auto nextID = _vertices.size();
109 _vertices.emplace_back(coords, nextID);
110 return _vertices.back();
111}
112
114 Vertex &vertexOne,
115 Vertex &vertexTwo)
116{
117 _edges.emplace_back(vertexOne, vertexTwo);
118 return _edges.back();
119}
120
122 Edge &edgeOne,
123 Edge &edgeTwo,
124 Edge &edgeThree)
125{
127 edgeOne.connectedTo(edgeTwo) &&
128 edgeTwo.connectedTo(edgeThree) &&
129 edgeThree.connectedTo(edgeOne));
130 _triangles.emplace_back(edgeOne, edgeTwo, edgeThree);
131 return _triangles.back();
132}
133
135 Vertex &vertexOne,
136 Vertex &vertexTwo,
137 Vertex &vertexThree)
138{
139 _triangles.emplace_back(vertexOne, vertexTwo, vertexThree);
140 return _triangles.back();
141}
142
144 Vertex &vertexOne,
145 Vertex &vertexTwo,
146 Vertex &vertexThree,
147 Vertex &vertexFour)
148{
149 _tetrahedra.emplace_back(vertexOne, vertexTwo, vertexThree, vertexFour);
150 return _tetrahedra.back();
151}
152
154 const std::string &name,
155 int dimension,
156 DataID id,
157 int waveformDegree)
158{
159 PRECICE_TRACE(name, dimension);
160 for (const PtrData &data : _data) {
161 PRECICE_CHECK(data->getName() != name,
162 "Data \"{}\" cannot be created twice for mesh \"{}\". "
163 "Please rename or remove one of the use-data tags with name \"{}\".",
164 name, _name, name);
165 }
166 // #rows = dimensions of current mesh #columns = dimensions of corresponding data set
167 std::vector<std::optional<double>> lowerBound = std::vector<std::optional<double>>(dimension);
168 std::vector<std::optional<double>> upperBound = std::vector<std::optional<double>>(dimension);
169 PtrData data(new Data(name, id, dimension, _dimensions, waveformDegree, lowerBound, upperBound));
170 _data.push_back(data);
171 return _data.back();
172}
173
175 const std::string &name,
176 int dimension,
177 DataID id,
178 int waveformDegree,
179 std::vector<std::optional<double>> lowerBound,
180 std::vector<std::optional<double>> upperBound)
181{
182 PRECICE_TRACE(name, dimension);
183 for (const PtrData &data : _data) {
184 PRECICE_CHECK(data->getName() != name,
185 "Data \"{}\" cannot be created twice for mesh \"{}\". "
186 "Please rename or remove one of the use-data tags with name \"{}\".",
187 name, _name, name);
188 }
189 // #rows = dimensions of current mesh #columns = dimensions of corresponding data set
190 PtrData data(new Data(name, id, dimension, _dimensions, waveformDegree, lowerBound, upperBound));
191 _data.push_back(data);
192 return _data.back();
193}
194
196{
197 return _data;
198}
199
200bool Mesh::hasDataID(DataID dataID) const
201{
202 auto iter = std::find_if(_data.begin(), _data.end(), [dataID](const auto &dptr) {
203 return dptr->getID() == dataID;
204 });
205 return iter != _data.end(); // if id was not found in mesh, iter == _data.end()
206}
207
208const PtrData &Mesh::data(DataID dataID) const
209{
210 auto iter = std::find_if(_data.begin(), _data.end(), [dataID](const auto &dptr) {
211 return dptr->getID() == dataID;
212 });
213 PRECICE_ASSERT(iter != _data.end(), "Data with id not found in mesh.", dataID, _name);
214 return *iter;
215}
216
217bool Mesh::hasDataName(std::string_view dataName) const
218{
219 auto iter = std::find_if(_data.begin(), _data.end(), [&dataName](const auto &dptr) {
220 return dptr->getName() == dataName;
221 });
222 return iter != _data.end(); // if name was not found in mesh, iter == _data.end()
223}
224
225std::vector<std::string> Mesh::availableData() const
226{
227 std::vector<std::string> names;
228 for (const auto &data : _data) {
229 names.push_back(data->getName());
230 }
231 return names;
232}
233
234const PtrData &Mesh::data(std::string_view dataName) const
235{
236 auto iter = std::find_if(_data.begin(), _data.end(), [&dataName](const auto &dptr) {
237 return dptr->getName() == dataName;
238 });
239 PRECICE_ASSERT(iter != _data.end(), "Data not found in mesh", dataName, _name);
240 return *iter;
241}
242
243const std::string &Mesh::getName() const
244{
245 return _name;
246}
247
249{
250 return _id;
251}
252
253bool Mesh::isValidVertexID(VertexID vertexID) const
254{
255 return (0 <= vertexID) && (static_cast<size_t>(vertexID) < nVertices());
256}
257
259{
260 PRECICE_TRACE(_vertices.size());
261 const auto expectedCount = _vertices.size();
262 for (PtrData &data : _data) {
263 data->allocateValues(expectedCount);
264 }
265}
266
268{
270
271 // Keep the bounding box if set via the API function.
273
274 for (const Vertex &vertex : _vertices) {
275 bb.expandBy(vertex);
276 }
277 _boundingBox = std::move(bb);
278 PRECICE_DEBUG("Bounding Box, {}", _boundingBox);
279}
280
282{
283 _triangles.clear();
284 _edges.clear();
285 _vertices.clear();
286 _tetrahedra.clear();
287 _index.clear();
288
290 for (mesh::PtrData &data : _data) {
291 data->values().resize(0);
292 }
293}
294
297{
298 _connectedRanks.clear();
299 _communicationMap.clear();
300 _vertexDistribution.clear();
301 _vertexOffsets.clear();
303}
304
306{
307 for (mesh::PtrData &data : _data) {
308 data->waveform().clear();
309 }
310}
311
313{
314 // Without offset data, we assume non-empty partitions
315 if (_vertexOffsets.empty()) {
316 return false;
317 }
318 PRECICE_ASSERT(_vertexOffsets.size() >= static_cast<std::size_t>(rank));
319 if (rank == 0) {
320 return _vertexOffsets[0] == 0;
321 }
322 return _vertexOffsets[rank] - _vertexOffsets[rank - 1] == 0;
323}
324
325Eigen::VectorXd Mesh::getOwnedVertexData(const Eigen::VectorXd &values)
326{
327 std::vector<double> ownedDataVector;
328 PRECICE_ASSERT(static_cast<std::size_t>(values.size()) >= nVertices());
329 if (empty()) {
330 return {};
331 }
332 int valueDim = values.size() / nVertices();
333 int index = 0;
334
335 for (const auto &vertex : vertices()) {
336 if (vertex.isOwner()) {
337 for (int dim = 0; dim < valueDim; ++dim) {
338 ownedDataVector.push_back(values[index * valueDim + dim]);
339 }
340 }
341 ++index;
342 }
343 Eigen::Map<Eigen::VectorXd> ownedData(ownedDataVector.data(), ownedDataVector.size());
344
345 return ownedData;
346}
347
349{
350 for (auto &vertex : _vertices) {
351 vertex.tag();
352 }
353}
354
356 const Mesh &deltaMesh)
357{
360
361 // Filter by selecting all vertices in the delta mesh
362 filterMesh(*this, deltaMesh, [](const Vertex &) { return true; });
363
364 _index.clear();
365}
366
368{
369 return _boundingBox;
370}
371
372void Mesh::expandBoundingBox(const BoundingBox &boundingBox)
373{
374 _boundingBox.expandBy(boundingBox);
375}
376
382
384{
385 // Remove duplicate tetrahedra
386 auto tetrahedraCnt = _tetrahedra.size();
387 std::sort(_tetrahedra.begin(), _tetrahedra.end());
388 auto lastTetrahedron = std::unique(_tetrahedra.begin(), _tetrahedra.end());
389 _tetrahedra = TetraContainer{_tetrahedra.begin(), lastTetrahedron};
390
391 // Remove duplicate triangles
392 auto triangleCnt = _triangles.size();
393 std::sort(_triangles.begin(), _triangles.end());
394 auto lastTriangle = std::unique(_triangles.begin(), _triangles.end());
395 _triangles = TriangleContainer{_triangles.begin(), lastTriangle};
396
397 // Remove duplicate edges
398 auto edgeCnt = _edges.size();
399 std::sort(_edges.begin(), _edges.end());
400 auto lastEdge = std::unique(_edges.begin(), _edges.end());
401 _edges = EdgeContainer{_edges.begin(), lastEdge};
402
403 PRECICE_DEBUG("Compression removed {} tetrahedra ({} to {}), {} triangles ({} to {}), and {} edges ({} to {})",
404 tetrahedraCnt - _tetrahedra.size(), tetrahedraCnt, _tetrahedra.size(),
405 triangleCnt - _triangles.size(), triangleCnt, _triangles.size(),
406 edgeCnt - _edges.size(), edgeCnt, _edges.size());
407}
408
409namespace {
410
411template <class Primitive, int... Indices>
412auto sortedVertexPtrsForImpl(Primitive &p, std::integer_sequence<int, Indices...>)
413{
414 std::array<Vertex *, Primitive::vertexCount> vs{&p.vertex(Indices)...};
415 std::sort(vs.begin(), vs.end());
416 return std::tuple_cat(vs);
417}
418
427template <class Primitive>
428auto sortedVertexPtrsFor(Primitive &p)
429{
430 return sortedVertexPtrsForImpl(p, std::make_integer_sequence<int, Primitive::vertexCount>{});
431}
432} // namespace
433
435{
436 if (_triangles.empty() && _tetrahedra.empty()) {
437 PRECICE_DEBUG("No implicit primitives required");
438 return; // no implicit primitives
439 }
440
441 // count explicit primitives for debug
442 const auto explTriangles = _triangles.size();
443 const auto explEdges = _triangles.size();
444
445 // First handle all explicit tetrahedra
446
447 // Build a set of all explicit triangles
448 using ExisitingTriangle = std::tuple<Vertex *, Vertex *, Vertex *>;
449 std::set<ExisitingTriangle> triangles;
450 for (auto &t : _triangles) {
451 triangles.insert(sortedVertexPtrsFor(t));
452 }
453
454 // Generate all missing implicit triangles of explicit tetrahedra
455 // Update the triangles set used by the implicit edge generation
456 auto createTriangleIfMissing = [&](Vertex *a, Vertex *b, Vertex *c) {
457 if (triangles.count({a, b, c}) == 0) {
458 triangles.emplace(a, b, c);
459 createTriangle(*a, *b, *c);
460 };
461 };
462 for (auto &t : _tetrahedra) {
463 auto [a, b, c, d] = sortedVertexPtrsFor(t);
464 // Make sure these are in the same order as above
465 createTriangleIfMissing(a, b, c);
466 createTriangleIfMissing(a, b, d);
467 createTriangleIfMissing(a, c, d);
468 createTriangleIfMissing(b, c, d);
469 }
470
471 // Second handle all triangles, both explicit and implicit from the tetrahedron phase
472 // Build an set of all explicit triangles
473 using ExisitingEdge = std::tuple<Vertex *, Vertex *>;
474 std::set<ExisitingEdge> edges;
475 for (auto &e : _edges) {
476 edges.emplace(sortedVertexPtrsFor(e));
477 }
478
479 // generate all missing implicit edges of implicit and explicit triangles
480 auto createEdgeIfMissing = [&](Vertex *a, Vertex *b) {
481 if (edges.count({a, b}) == 0) {
482 edges.emplace(a, b);
483 createEdge(*a, *b);
484 };
485 };
486 for (auto &t : _triangles) {
487 auto [a, b, c] = sortedVertexPtrsFor(t);
488 // Make sure these are in the same order as above
489 createEdgeIfMissing(a, b);
490 createEdgeIfMissing(a, c);
491 createEdgeIfMissing(b, c);
492 }
493
494 PRECICE_DEBUG("Generated {} implicit triangles and {} implicit edges",
495 _triangles.size() - explTriangles,
496 _edges.size() - explEdges);
497}
498
499bool Mesh::operator==(const Mesh &other) const
500{
501 bool equal = true;
502 equal &= _vertices.size() == other._vertices.size() &&
503 std::is_permutation(_vertices.begin(), _vertices.end(), other._vertices.begin());
504 equal &= _edges.size() == other._edges.size() &&
505 std::is_permutation(_edges.begin(), _edges.end(), other._edges.begin());
506 equal &= _triangles.size() == other._triangles.size() &&
507 std::is_permutation(_triangles.begin(), _triangles.end(), other._triangles.begin());
508 return equal;
509}
510
511bool Mesh::operator!=(const Mesh &other) const
512{
513 return !(*this == other);
514}
515
516std::ostream &operator<<(std::ostream &os, const Mesh &m)
517{
518 os << "Mesh \"" << m.getName() << "\", dimensionality = " << m.getDimensions() << ":\n";
519 os << "GEOMETRYCOLLECTION(\n";
520 const auto token = ", ";
521 const auto *sep = "";
522 for (auto &vertex : m.vertices()) {
523 os << sep << vertex;
524 sep = token;
525 }
526 sep = ",\n";
527 for (auto &edge : m.edges()) {
528 os << sep << edge;
529 sep = token;
530 }
531 sep = ",\n";
532 for (auto &triangle : m.triangles()) {
533 os << sep << triangle;
534 sep = token;
535 }
536 os << "\n)";
537 return os;
538}
539
540} // namespace precice::mesh
#define PRECICE_DEBUG(...)
Definition LogMacros.hpp:61
#define PRECICE_TRACE(...)
Definition LogMacros.hpp:92
#define PRECICE_CHECK(check,...)
Definition LogMacros.hpp:32
#define PRECICE_ASSERT(...)
Definition assertion.hpp:85
An axis-aligned bounding box around a (partition of a) mesh.
void expandBy(const BoundingBox &otherBB)
Expand bounding box using another bounding box.
Describes a set of data values belonging to the vertices of a mesh.
Definition Data.hpp:26
Linear edge of a mesh, defined by two Vertex objects.
Definition Edge.hpp:15
bool connectedTo(const Edge &other) const
Checks whether both edges share a vertex.
Definition Edge.cpp:39
Container and creator for meshes.
Definition Mesh.hpp:38
void expandBoundingBox(const BoundingBox &bounding_box)
Definition Mesh.cpp:372
Triangle & createTriangle(Edge &edgeOne, Edge &edgeTwo, Edge &edgeThree)
Creates and initializes a Triangle object.
Definition Mesh.cpp:121
MeshID _id
The ID of this mesh.
Definition Mesh.hpp:365
MeshID getID() const
Returns the base ID of the mesh.
Definition Mesh.cpp:248
std::string _name
Name of the mesh.
Definition Mesh.hpp:359
BoundingBox _boundingBox
Definition Mesh.hpp:412
std::deque< Triangle > TriangleContainer
Definition Mesh.hpp:42
int _globalNumberOfVertices
Number of unique vertices for complete distributed mesh.
Definition Mesh.hpp:395
int getDimensions() const
Definition Mesh.cpp:100
VertexContainer & vertices()
Returns modifieable container holding all vertices.
Definition Mesh.cpp:55
void clearDataStamples()
Clears all data stamples.
Definition Mesh.cpp:305
std::vector< PtrData > DataContainer
Definition Mesh.hpp:44
bool hasDataID(DataID dataID) const
Returns whether Mesh has Data with the matchingID.
Definition Mesh.cpp:200
Eigen::VectorXd getOwnedVertexData(const Eigen::VectorXd &values)
Definition Mesh.cpp:325
void clear()
Removes all mesh elements and data values (does not remove data or the bounding boxes).
Definition Mesh.cpp:281
DataContainer _data
Data hold by the vertices of the mesh.
Definition Mesh.hpp:374
void addMesh(const Mesh &deltaMesh)
Definition Mesh.cpp:355
bool operator!=(const Mesh &other) const
Definition Mesh.cpp:511
std::vector< std::string > availableData() const
Returns the names of all available data.
Definition Mesh.cpp:225
const std::string & getName() const
Returns the name of the mesh, as set in the config file.
Definition Mesh.cpp:243
void removeDuplicates()
Removes all duplicate connectivity.
Definition Mesh.cpp:383
std::size_t nVertices() const
Returns the number of vertices.
Definition Mesh.cpp:65
VertexDistribution _vertexDistribution
Vertex distribution for the primary rank, holding for each secondary rank all vertex IDs it owns.
Definition Mesh.hpp:381
TetraContainer & tetrahedra()
Returns modifiable container holding all tetrahedra.
Definition Mesh.cpp:95
std::deque< Tetrahedron > TetraContainer
Definition Mesh.hpp:43
bool operator==(const Mesh &other) const
Definition Mesh.cpp:499
std::vector< Rank > _connectedRanks
each rank stores list of connected remote ranks. In the m2n package, this is used to create the initi...
Definition Mesh.hpp:401
bool _isJustInTime
for just-in-time mapping, we need an artificial mesh, which we can use
Definition Mesh.hpp:410
TetraContainer _tetrahedra
Definition Mesh.hpp:371
Vertex & vertex(VertexID id)
Mutable access to a vertex by VertexID.
Definition Mesh.cpp:43
bool isJustInTime() const
Definition Mesh.hpp:340
Mesh(std::string name, int dimensions, MeshID id, bool isJustInTime=false)
Constructor.
Definition Mesh.cpp:27
const query::Index & index() const
Call preprocess() before index() to ensure correct projection handling.
Definition Mesh.hpp:329
query::Index _index
Definition Mesh.hpp:414
VertexContainer _vertices
Holds vertices, edges, triangles and tetrahedra.
Definition Mesh.hpp:368
bool hasDataName(std::string_view dataName) const
Returns whether Mesh has Data with the dataName.
Definition Mesh.cpp:217
std::deque< Edge > EdgeContainer
Definition Mesh.hpp:41
PtrData & createData(const std::string &name, int dimension, DataID id, int waveformDegree=time::Time::DEFAULT_WAVEFORM_DEGREE)
Create only data for vertex.
Definition Mesh.cpp:153
CommunicationMap _communicationMap
each rank stores list of connected ranks and corresponding vertex IDs here. In the m2n package,...
Definition Mesh.hpp:407
bool empty() const
Does the mesh contain any vertices?
Definition Mesh.hpp:88
void generateImplictPrimitives()
Definition Mesh.cpp:434
void clearPartitioning()
Clears the partitioning information.
Definition Mesh.cpp:296
void computeBoundingBox()
Computes the boundingBox for the vertices.
Definition Mesh.cpp:267
TriangleContainer _triangles
Definition Mesh.hpp:370
bool isPartitionEmpty(Rank rank) const
checks if the given ranks partition is empty
Definition Mesh.cpp:312
Tetrahedron & createTetrahedron(Vertex &vertexOne, Vertex &vertexTwo, Vertex &vertexThree, Vertex &vertexFour)
Creates and initializes a Tetrahedron object.
Definition Mesh.cpp:143
VertexOffsets _vertexOffsets
Holds the index of the last vertex for each rank.
Definition Mesh.hpp:388
bool isValidVertexID(VertexID vertexID) const
Returns true if the given vertexID is valid.
Definition Mesh.cpp:253
EdgeContainer _edges
Definition Mesh.hpp:369
const DataContainer & data() const
Allows access to all data.
Definition Mesh.cpp:195
TriangleContainer & triangles()
Returns modifiable container holding all triangles.
Definition Mesh.cpp:80
const BoundingBox & getBoundingBox() const
Returns the bounding box of the mesh.
Definition Mesh.cpp:367
std::deque< Vertex > VertexContainer
Definition Mesh.hpp:40
Edge & createEdge(Vertex &vertexOne, Vertex &vertexTwo)
Creates and initializes an Edge object.
Definition Mesh.cpp:113
Vertex & createVertex(const Eigen::Ref< const Eigen::VectorXd > &coords)
Creates and initializes a Vertex object.
Definition Mesh.cpp:105
EdgeContainer & edges()
Returns modifiable container holding all edges.
Definition Mesh.cpp:70
void allocateDataValues()
Allocates memory for the vertex data values and corresponding gradient values.
Definition Mesh.cpp:258
int _dimensions
Dimension of mesh.
Definition Mesh.hpp:362
Tetrahedron of a mesh, defined by 4 vertices.
Triangle of a mesh, defined by three vertices.
Definition Triangle.hpp:24
Vertex of a mesh.
Definition Vertex.hpp:16
provides Mesh, Data and primitives.
void filterMesh(Mesh &destination, const Mesh &source, UnaryPredicate &&p)
Definition Filter.hpp:16
std::shared_ptr< Data > PtrData
std::ostream & operator<<(std::ostream &os, const BoundingBox &bb)
int MeshID
Definition Types.hpp:30
int VertexID
Definition Types.hpp:13
int Rank
Definition Types.hpp:37
int DataID
Definition Types.hpp:25
STL namespace.