preCICE v3.3.0
Loading...
Searching...
No Matches
PartitionOfUnityMapping.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <Eigen/Core>
4#include <numeric>
5
7#include "io/ExportVTU.hpp"
11#include "mesh/Filter.hpp"
13#include "profiling/Event.hpp"
14#include "query/Index.hpp"
15#include "utils/IntraComm.hpp"
16
17namespace precice {
18extern bool syncMode;
19
20namespace mapping {
21
29template <typename RADIAL_BASIS_FUNCTION_T>
31public:
48 Mapping::Constraint constraint,
49 int dimension,
50 RADIAL_BASIS_FUNCTION_T function,
51 Polynomial polynomial,
52 unsigned int verticesPerCluster,
53 double relativeOverlap,
54 bool projectToInput);
55
65 void computeMapping() final override;
66
68 void clear() final override;
69
71 void tagMeshFirstRound() final override;
72
74 void tagMeshSecondRound() final override;
75
77 std::string getName() const final override;
78
79 void mapConsistentAt(const Eigen::Ref<const Eigen::MatrixXd> &coordinates, const impl::MappingDataCache &cache, Eigen::Ref<Eigen::MatrixXd> values) final override;
80
82 void mapConservativeAt(const Eigen::Ref<const Eigen::MatrixXd> &coordinates, const Eigen::Ref<const Eigen::MatrixXd> &source, impl::MappingDataCache &cache, Eigen::Ref<Eigen::MatrixXd> target) final override;
83
84 void updateMappingDataCache(impl::MappingDataCache &cache, const Eigen::Ref<const Eigen::VectorXd> &in) final override;
85
86 void completeJustInTimeMapping(impl::MappingDataCache &cache, Eigen::Ref<Eigen::MatrixXd> buffer) final override;
87
88 void initializeMappingDataCache(impl::MappingDataCache &cache) final override;
89
90private:
92 precice::logging::Logger _log{"mapping::PartitionOfUnityMapping"};
93
96
98 RADIAL_BASIS_FUNCTION_T _basisFunction;
99
101
103 const unsigned int _verticesPerCluster;
104
106 const double _relativeOverlap;
107
109 const bool _projectToInput;
110
112 double _clusterRadius = 0;
113
116
118
120 void mapConservative(const time::Sample &inData, Eigen::VectorXd &outData) override;
121
123 void mapConsistent(const time::Sample &inData, Eigen::VectorXd &outData) override;
124
129
133};
134
135template <typename RADIAL_BASIS_FUNCTION_T>
137 Mapping::Constraint constraint,
138 int dimension,
139 RADIAL_BASIS_FUNCTION_T function,
140 Polynomial polynomial,
141 unsigned int verticesPerCluster,
142 double relativeOverlap,
143 bool projectToInput)
144 : Mapping(constraint, dimension, false, Mapping::InitialGuessRequirement::None),
145 _basisFunction(function), _verticesPerCluster(verticesPerCluster), _relativeOverlap(relativeOverlap), _projectToInput(projectToInput), _polynomial(polynomial)
146{
147 PRECICE_ASSERT(this->getDimensions() <= 3);
148 PRECICE_ASSERT(_polynomial != Polynomial::ON, "Integrated polynomial is not supported for partition of unity data mappings.");
149 PRECICE_ASSERT(_relativeOverlap < 1, "The relative overlap has to be smaller than one.");
150 PRECICE_ASSERT(_verticesPerCluster > 0, "The number of vertices per cluster has to be greater zero.");
151
152 if (isScaledConsistent()) {
155 } else {
158 }
159}
160
161template <typename RADIAL_BASIS_FUNCTION_T>
163{
165
166 precice::profiling::Event e("map.pou.computeMapping.From" + this->input()->getName() + "To" + this->output()->getName(), profiling::Synchronize);
167
168 // Recompute the whole clustering
169 PRECICE_ASSERT(!this->_hasComputedMapping, "Please clear the mapping before recomputing.");
170
171 mesh::PtrMesh inMesh;
172 mesh::PtrMesh outMesh;
174 inMesh = this->output();
175 outMesh = this->input();
176 } else { // Consistent or scaled consistent
177 inMesh = this->input();
178 outMesh = this->output();
179 }
180
181 precice::profiling::Event eClusters("map.pou.computeMapping.createClustering.From" + this->input()->getName() + "To" + this->output()->getName());
182 // Step 1: get a tentative clustering consisting of centers and a radius from one of the available algorithms
183 auto [clusterRadius, centerCandidates] = impl::createClustering(inMesh, outMesh, _relativeOverlap, _verticesPerCluster, _projectToInput);
184 eClusters.stop();
185
186 _clusterRadius = clusterRadius;
187 PRECICE_ASSERT(_clusterRadius > 0 || inMesh->nVertices() == 0 || outMesh->nVertices() == 0);
188
189 // Step 2: check, which of the resulting clusters are non-empty and register the cluster centers in a mesh
190 // Here, the VertexCluster computes the matrix decompositions directly in case the cluster is non-empty
191 _centerMesh = std::make_unique<mesh::Mesh>("pou-centers-" + inMesh->getName(), this->getDimensions(), mesh::Mesh::MESH_ID_UNDEFINED);
192 auto &meshVertices = _centerMesh->vertices();
193
194 meshVertices.clear();
195 _clusters.clear();
196 _clusters.reserve(centerCandidates.size());
197 for (const auto &c : centerCandidates) {
198 // We cannot simply copy the vertex from the container in order to fill the vertices of the centerMesh, as the vertexID of each center needs to match the index
199 // of the cluster within the _clusters vector. That's required for the indexing further down and asserted below
200 const VertexID vertexID = meshVertices.size();
201 mesh::Vertex center(c.getCoords(), vertexID);
203
204 // Consider only non-empty clusters (more of a safeguard here)
205 if (!cluster.empty()) {
206 PRECICE_ASSERT(center.getID() == static_cast<int>(_clusters.size()), center.getID(), _clusters.size());
207 meshVertices.emplace_back(std::move(center));
208 _clusters.emplace_back(std::move(cluster));
209 }
210 }
211
212 e.addData("n clusters", _clusters.size());
213 // Log the average number of resulting clusters
214 PRECICE_DEBUG("Partition of unity data mapping between mesh \"{}\" and mesh \"{}\": mesh \"{}\" on rank {} was decomposed into {} clusters.", this->input()->getName(), this->output()->getName(), inMesh->getName(), utils::IntraComm::getRank(), _clusters.size());
215
216 if (_clusters.size() > 0) {
217 PRECICE_DEBUG("Average number of vertices per cluster {}", std::accumulate(_clusters.begin(), _clusters.end(), static_cast<unsigned int>(0), [](auto &acc, auto &val) { return acc += val.getNumberOfInputVertices(); }) / _clusters.size());
218 PRECICE_DEBUG("Maximum number of vertices per cluster {}", std::max_element(_clusters.begin(), _clusters.end(), [](auto &v1, auto &v2) { return v1.getNumberOfInputVertices() < v2.getNumberOfInputVertices(); })->getNumberOfInputVertices());
219 PRECICE_DEBUG("Minimum number of vertices per cluster {}", std::min_element(_clusters.begin(), _clusters.end(), [](auto &v1, auto &v2) { return v1.getNumberOfInputVertices() < v2.getNumberOfInputVertices(); })->getNumberOfInputVertices());
220 }
221
222 precice::profiling::Event eWeights("map.pou.computeMapping.computeWeights");
223 // Log a bounding box of the center mesh
224 _centerMesh->computeBoundingBox();
225 PRECICE_DEBUG("Bounding Box of the cluster centers {}", _centerMesh->getBoundingBox());
226
227 // Step 3: Determine PU weights
228 PRECICE_DEBUG("Computing cluster-vertex association");
229 for (const auto &vertex : outMesh->vertices()) {
230 // we use a helper function, as we need the same functionality for just-in-time mapping
231 auto [clusterIDs, normalizedWeights] = computeNormalizedWeight(vertex, outMesh->getName());
232 // Step 4: store the normalized weight in all associated clusters
233 for (unsigned int i = 0; i < clusterIDs.size(); ++i) {
234 PRECICE_ASSERT(clusterIDs[i] < static_cast<int>(_clusters.size()));
235 _clusters[clusterIDs[i]].setNormalizedWeight(normalizedWeights[i], vertex.getID());
236 }
237 }
238 eWeights.stop();
239
240 // Uncomment to add a VTK export of the cluster center distribution for visualization purposes
241 // exportClusterCentersAsVTU(*_centerMesh);
242
243 // we need the center mesh index data structure
244 if (!outMesh->isJustInTime()) {
245 _centerMesh.reset();
246 }
247
248 this->_hasComputedMapping = true;
249}
250
251template <typename RADIAL_BASIS_FUNCTION_T>
253{
254
255 // Step 1: index the clusters / the center mesh in order to define the output vertex -> cluster ownership
256 // the ownership is required to compute the normalized partition of unity weights (Step 2)
257 // query::Index clusterIndex(*_centerMesh.get());
259 query::Index &clusterIndex = _centerMesh->index();
260
261 // Step 2: find all clusters the output vertex lies in, i.e., find all cluster centers which have the distance of a cluster radius from the given output vertex
262 // Here, we do this using the RTree on the centerMesh: VertexID (queried from the centersMesh) == clusterID, by construction above. The loop uses
263 // the vertices to compute the weights required for the partition of unity data mapping.
264 // Note: this could also be done on-the-fly in the map data phase for dynamic queries, which would require to make the mesh as well as the indexTree member variables.
265
266 // Step 2a: get the relevant clusters for the output vertex
267 auto clusterIDs = clusterIndex.getVerticesInsideBox(vertex, _clusterRadius);
268 const auto localNumberOfClusters = clusterIDs.size();
269
270 // Consider the case where we didn't find any cluster (meshes don't match very well)
271 //
272 // In principle, we could assign the vertex to the closest cluster using clusterIDs.emplace_back(clusterIndex.getClosestVertex(vertex.getCoords()).index);
273 // However, this leads to a conflict with weights already set in the corresponding cluster, since we insert the ID and, later on, map the ID to a local weight index
274 // Of course, we could rearrange the weights, but we want to avoid the case here anyway, i.e., prefer to abort.
275 PRECICE_CHECK(localNumberOfClusters > 0,
276 "Output vertex {} of mesh \"{}\" could not be assigned to any cluster in the rbf-pum mapping. This probably means that the meshes do not match well geometry-wise: Visualize the exported preCICE meshes to confirm. "
277 "If the meshes are fine geometry-wise, you can try to increase the number of \"vertices-per-cluster\" (default is 50), the \"relative-overlap\" (default is 0.15), or disable the option \"project-to-input\". "
278 "These options are only valid for the <mapping:rbf-pum-direct/> tag.",
279 vertex.getCoords(), mesh);
280
281 // Next we compute the normalized weights of each output vertex for each partition
282 PRECICE_ASSERT(localNumberOfClusters > 0, "No cluster found for vertex {}", vertex.getCoords());
283
284 // Step 2b: compute the weight in each partition individually and store them in 'weights'
285 std::vector<double> weights(localNumberOfClusters);
286 std::transform(clusterIDs.cbegin(), clusterIDs.cend(), weights.begin(), [&](const auto &ids) { return _clusters[ids].computeWeight(vertex); });
287 double weightSum = std::accumulate(weights.begin(), weights.end(), static_cast<double>(0.));
288 // TODO: This covers the edge case of vertices being at the edge of (several) clusters
289 // In case the sum is equal to zero, we assign equal weights for all clusters
290 if (weightSum <= 0) {
291 PRECICE_ASSERT(weights.size() > 0);
292 std::for_each(weights.begin(), weights.end(), [&weights](auto &w) { w = 1. / weights.size(); });
293 weightSum = 1;
294 }
295 PRECICE_ASSERT(weightSum > 0);
296
297 // Step 2c: Normalize weights
298 std::transform(weights.begin(), weights.end(), weights.begin(), [weightSum](double w) { return w / weightSum; });
299
300 // Return both the cluster IDs and the normalized weights
301 return {clusterIDs, weights};
302}
303
304template <typename RADIAL_BASIS_FUNCTION_T>
306{
308
309 precice::profiling::Event e("map.pou.mapData.From" + input()->getName() + "To" + output()->getName(), profiling::Synchronize);
310
311 // Execute the actual mapping evaluation in all clusters
312 // 1. Assert that all output data values were reset, as we accumulate data in all clusters independently
313 PRECICE_ASSERT(outData.isZero());
314
315 // 2. Iterate over all clusters and accumulate the result in the output data
316 std::for_each(_clusters.begin(), _clusters.end(), [&](auto &cluster) { cluster.mapConservative(inData, outData); });
317}
318
319template <typename RADIAL_BASIS_FUNCTION_T>
321{
323
324 precice::profiling::Event e("map.pou.mapData.From" + input()->getName() + "To" + output()->getName(), profiling::Synchronize);
325
326 // Execute the actual mapping evaluation in all clusters
327 // 1. Assert that all output data values were reset, as we accumulate data in all clusters independently
328 PRECICE_ASSERT(outData.isZero());
329
330 // 2. Execute the actual mapping evaluation in all vertex clusters and accumulate the data
331 std::for_each(_clusters.begin(), _clusters.end(), [&](auto &clusters) { clusters.mapConsistent(inData, outData); });
332}
333
334template <typename RADIAL_BASIS_FUNCTION_T>
335void PartitionOfUnityMapping<RADIAL_BASIS_FUNCTION_T>::mapConservativeAt(const Eigen::Ref<const Eigen::MatrixXd> &coordinates, const Eigen::Ref<const Eigen::MatrixXd> &source,
336 impl::MappingDataCache &cache, Eigen::Ref<Eigen::MatrixXd>)
337{
338 precice::profiling::Event e("map.pou.mapConservativeAt.From" + input()->getName());
339 // @todo: it would most probably be more efficient to first group the vertices we receive here according to the clusters and then compute the solution
340
343 PRECICE_ASSERT(cache.p.size() == _clusters.size());
345
346 mesh::Vertex vertex(coordinates.col(0), -1);
347 for (Eigen::Index v = 0; v < coordinates.cols(); ++v) {
348 vertex.setCoords(coordinates.col(v));
349 auto [clusterIDs, normalizedWeights] = computeNormalizedWeight(vertex, this->input()->getName());
350 // Use the weight to interpolate the solution
351 for (std::size_t i = 0; i < clusterIDs.size(); ++i) {
352 PRECICE_ASSERT(clusterIDs[i] < static_cast<int>(_clusters.size()));
353 auto id = clusterIDs[i];
354 // the input mesh refers here to a consistent constraint
355 Eigen::VectorXd res = normalizedWeights[i] * source.col(v);
356 _clusters[id].addWriteDataToCache(vertex, res, cache.polynomialContributions[id], cache.p[id], *this->output().get());
357 }
358 }
359}
360
361template <typename RADIAL_BASIS_FUNCTION_T>
363{
365 PRECICE_ASSERT(!cache.p.empty());
367 precice::profiling::Event e("map.pou.completeJustInTimeMapping.From" + input()->getName());
368
369 for (std::size_t c = 0; c < _clusters.size(); ++c) {
370 // If there is no contribution, we don't have to evaluate
371 if (cache.p[c].squaredNorm() > 0) {
372 _clusters[c].evaluateConservativeCache(cache.polynomialContributions[c], cache.p[c], buffer);
373 }
374 }
375}
376
377template <typename RADIAL_BASIS_FUNCTION_T>
379{
382 cache.p.resize(_clusters.size());
384 for (std::size_t c = 0; c < _clusters.size(); ++c) {
385 _clusters[c].initializeCacheData(cache.polynomialContributions[c], cache.p[c], cache.getDataDimensions());
386 }
387}
388
389template <typename RADIAL_BASIS_FUNCTION_T>
391{
392 // We cannot synchronize this event, as the call to this function is rank-local only
393 precice::profiling::Event e("map.pou.updateMappingDataCache.From" + input()->getName());
394 PRECICE_ASSERT(cache.p.size() == _clusters.size());
396 Eigen::Map<const Eigen::MatrixXd> inMatrix(in.data(), cache.getDataDimensions(), in.size() / cache.getDataDimensions());
397 for (std::size_t c = 0; c < _clusters.size(); ++c) {
398 _clusters[c].computeCacheData(inMatrix, cache.polynomialContributions[c], cache.p[c]);
399 }
400}
401
402template <typename RADIAL_BASIS_FUNCTION_T>
403void PartitionOfUnityMapping<RADIAL_BASIS_FUNCTION_T>::mapConsistentAt(const Eigen::Ref<const Eigen::MatrixXd> &coordinates, const impl::MappingDataCache &cache, Eigen::Ref<Eigen::MatrixXd> values)
404{
405 precice::profiling::Event e("map.pou.mapConsistentAt.From" + input()->getName());
406 // @todo: it would most probably be more efficient to first group the vertices we receive here according to the clusters and then compute the solution
409
410 // First, make sure that everything is reset before we start
411 values.setZero();
412
413 mesh::Vertex vertex(coordinates.col(0), -1);
414 for (Eigen::Index v = 0; v < values.cols(); ++v) {
415 vertex.setCoords(coordinates.col(v));
416 auto [clusterIDs, normalizedWeights] = computeNormalizedWeight(vertex, this->output()->getName());
417 // Use the weight to interpolate the solution
418 for (std::size_t i = 0; i < clusterIDs.size(); ++i) {
419 PRECICE_ASSERT(clusterIDs[i] < static_cast<int>(_clusters.size()));
420 auto id = clusterIDs[i];
421 // the input mesh refers here to a consistent constraint
422 Eigen::VectorXd localRes = normalizedWeights[i] * _clusters[id].interpolateAt(vertex, cache.polynomialContributions[id], cache.p[id], *this->input().get());
423 values.col(v) += localRes;
424 }
425 }
426}
427
428template <typename RADIAL_BASIS_FUNCTION_T>
430{
432 mesh::PtrMesh filterMesh, outMesh;
434 filterMesh = this->output(); // remote
435 outMesh = this->input(); // local
436 } else {
437 filterMesh = this->input(); // remote
438 outMesh = this->output(); // local
439 }
440
441 if (outMesh->empty())
442 return; // Ranks not at the interface should never hold interface vertices
443
444 // The geometric filter of the repartitioning is always disabled for the PU-RBF.
445 // The main rationale: if we use only a fraction of the mesh then we might end up
446 // with too few vertices per rank and we cannot prevent too few vertices from being
447 // tagged, if we have filtered too much vertices beforehand. When using the filtering,
448 // the user could increase the safety-factor or disable the filtering, but that's
449 // a bit hard to understand for users. When no geometric filter is applid,
450 // vertices().size() is here the same as getGlobalNumberOfVertices. Hence, it is much
451 // safer to make use of the unfiltered mesh for the parallel tagging.
452 //
453 // Drawback: the "estimateClusterRadius" below makes use of the mesh R* index tree, and
454 // constructing the tree on the (unfiltered) global mesh is computationally expensive (O( N logN)).
455 // We could pre-filter the global mesh to a local fraction (using our own geometric filtering,
456 // maybe with an increased safety margin or even an iterative increase of the safety margin),
457 // but then there is again the question on how to do this in a safe way, without risking
458 // failures depending on the partitioning. So we stick here to the computationally more
459 // demanding, but safer version.
460 // See also https://github.com/precice/precice/pull/1912#issuecomment-2551143620
461
462 // Get the local bounding boxes
463 auto localBB = outMesh->getBoundingBox();
464 // we cannot check for empty'ness here, as a single output mesh vertex
465 // would lead to a 0D box with zero volume (considered empty). Thus, we
466 // simply check here for default'ness, which is equivalent to outMesh->empty()
467 // further above
468 PRECICE_ASSERT(!localBB.isDefault());
469
470 if (_clusterRadius == 0)
472
473 PRECICE_DEBUG("Cluster radius estimate: {}", _clusterRadius);
475
476 // Now we extend the bounding box by the radius
477 localBB.expandBy(2 * _clusterRadius);
478
479 // ... and tag all affected vertices
480 auto verticesNew = filterMesh->index().getVerticesInsideBox(localBB);
481
482 std::for_each(verticesNew.begin(), verticesNew.end(), [&filterMesh](VertexID v) { filterMesh->vertex(v).tag(); });
483}
484
485template <typename RADIAL_BASIS_FUNCTION_T>
487{
488 // Nothing to be done here. There is no global ownership for matrix entries required and we tag all potentially locally relevant vertices already in the first round.
489}
490
491template <typename RADIAL_BASIS_FUNCTION_T>
493{
495
496 auto dataRadius = centerMesh.createData("radius", 1, -1);
497 auto dataCardinality = centerMesh.createData("number-of-vertices", 1, -1);
498 centerMesh.allocateDataValues();
499 dataRadius->values().fill(_clusterRadius);
500 for (unsigned int i = 0; i < _clusters.size(); ++i) {
501 dataCardinality->values()[i] = static_cast<double>(_clusters[i].getNumberOfInputVertices());
502 }
503
504 // We have to create the global offsets in order to export things in parallel
506 // send number of vertices
507 PRECICE_DEBUG("Send number of vertices: {}", centerMesh.nVertices());
508 int numberOfVertices = centerMesh.nVertices();
509 utils::IntraComm::getCommunication()->send(numberOfVertices, 0);
510
511 // receive vertex offsets
512 mesh::Mesh::VertexOffsets vertexOffsets;
513 utils::IntraComm::getCommunication()->broadcast(vertexOffsets, 0);
514 PRECICE_DEBUG("Vertex offsets: {}", vertexOffsets);
515 PRECICE_ASSERT(centerMesh.getVertexOffsets().empty());
516 centerMesh.setVertexOffsets(std::move(vertexOffsets));
517 } else if (utils::IntraComm::isPrimary()) {
518
520 vertexOffsets[0] = centerMesh.nVertices();
521
522 // receive number of secondary vertices and fill vertex offsets
523 for (int secondaryRank : utils::IntraComm::allSecondaryRanks()) {
524 int numberOfSecondaryRankVertices = -1;
525 utils::IntraComm::getCommunication()->receive(numberOfSecondaryRankVertices, secondaryRank);
526 PRECICE_ASSERT(numberOfSecondaryRankVertices >= 0);
527 vertexOffsets[secondaryRank] = numberOfSecondaryRankVertices + vertexOffsets[secondaryRank - 1];
528 }
529
530 // broadcast vertex offsets
531 PRECICE_DEBUG("Vertex offsets: {}", centerMesh.getVertexOffsets());
532 utils::IntraComm::getCommunication()->broadcast(vertexOffsets);
533 centerMesh.setVertexOffsets(std::move(vertexOffsets));
534 }
535
536 dataRadius->setSampleAtTime(0, time::Sample{1, dataRadius->values()});
537 dataCardinality->setSampleAtTime(0, time::Sample{1, dataCardinality->values()});
539 exporter.doExport(0, 0.0);
540}
541
542template <typename RADIAL_BASIS_FUNCTION_T>
544{
546 _clusters.clear();
547 // TODO: Don't reset this here
548 _clusterRadius = 0;
549 this->_hasComputedMapping = false;
550}
551
552template <typename RADIAL_BASIS_FUNCTION_T>
554{
555 return "partition-of-unity RBF";
556}
557} // namespace mapping
558} // namespace precice
#define PRECICE_DEBUG(...)
Definition LogMacros.hpp:61
#define PRECICE_TRACE(...)
Definition LogMacros.hpp:92
#define PRECICE_CHECK(check,...)
Definition LogMacros.hpp:32
T accumulate(T... args)
#define PRECICE_ASSERT(...)
Definition assertion.hpp:85
T begin(T... args)
VertexContainer & vertices()
Returns modifieable container holding all vertices.
Definition Mesh.cpp:55
const std::string & getName() const
Returns the name of the mesh, as set in the config file.
Definition Mesh.cpp:220
std::size_t nVertices() const
Returns the number of vertices.
Definition Mesh.cpp:65
bool isJustInTime() const
Definition Mesh.hpp:332
bool empty() const
Does the mesh contain any vertices?
Definition Mesh.hpp:88
const BoundingBox & getBoundingBox() const
Returns the bounding box of the mesh.
Definition Mesh.cpp:388
void doExport(int index, double time) final override
Export the mesh and writes files.
Definition ExportXML.cpp:33
mesh::PtrMesh output() const
Returns pointer to output mesh.
Definition Mapping.cpp:92
Constraint
Specifies additional constraints for a mapping.
Definition Mapping.hpp:30
Mapping(Constraint constraint, int dimensions, bool requiresGradientData, InitialGuessRequirement initialGuessRequirement)
Constructor, takes mapping constraint.
Definition Mapping.cpp:12
mesh::PtrMesh input() const
Returns pointer to input mesh.
Definition Mapping.cpp:87
bool _hasComputedMapping
Flag to indicate whether computeMapping() has been called.
Definition Mapping.hpp:307
bool isScaledConsistent() const
Returns true if mapping is a form of scaled consistent mapping.
Definition Mapping.cpp:258
void setInputRequirement(MeshRequirement requirement)
Sets the mesh requirement for the input mesh.
Definition Mapping.cpp:97
void setOutputRequirement(MeshRequirement requirement)
Sets the mesh requirement for the output mesh.
Definition Mapping.cpp:103
virtual bool hasConstraint(const Constraint &constraint) const
Checks whether the mapping has the given constraint or not.
Definition Mapping.cpp:248
InitialGuessRequirement
Specifies whether the mapping requires an initial guess.
Definition Mapping.hpp:64
std::pair< std::vector< int >, std::vector< double > > computeNormalizedWeight(const mesh::Vertex &v, std::string_view mesh)
void initializeMappingDataCache(impl::MappingDataCache &cache) final override
void mapConservativeAt(const Eigen::Ref< const Eigen::MatrixXd > &coordinates, const Eigen::Ref< const Eigen::MatrixXd > &source, impl::MappingDataCache &cache, Eigen::Ref< Eigen::MatrixXd > target) final override
std::vector< SphericalVertexCluster< RBF > > _clusters
std::string getName() const final override
void mapConsistent(const time::Sample &inData, Eigen::VectorXd &outData) override
Maps data using a consistent constraint.
PartitionOfUnityMapping(Mapping::Constraint constraint, int dimension, RADIAL_BASIS_FUNCTION_T function, Polynomial polynomial, unsigned int verticesPerCluster, double relativeOverlap, bool projectToInput)
void mapConsistentAt(const Eigen::Ref< const Eigen::MatrixXd > &coordinates, const impl::MappingDataCache &cache, Eigen::Ref< Eigen::MatrixXd > values) final override
void mapConservative(const time::Sample &inData, Eigen::VectorXd &outData) override
Maps data using a conservative constraint.
void updateMappingDataCache(impl::MappingDataCache &cache, const Eigen::Ref< const Eigen::VectorXd > &in) final override
void completeJustInTimeMapping(impl::MappingDataCache &cache, Eigen::Ref< Eigen::MatrixXd > buffer) final override
Container and creator for meshes.
Definition Mesh.hpp:38
static constexpr MeshID MESH_ID_UNDEFINED
Use if the id of the mesh is not necessary.
Definition Mesh.hpp:57
std::size_t nVertices() const
Returns the number of vertices.
Definition Mesh.cpp:65
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
const VertexOffsets & getVertexOffsets() const
Definition Mesh.hpp:251
std::vector< int > VertexOffsets
Definition Mesh.hpp:54
void setVertexOffsets(VertexOffsets vertexOffsets)
Only used for tests.
Definition Mesh.hpp:260
void allocateDataValues()
Allocates memory for the vertex data values and corresponding gradient values.
Definition Mesh.cpp:235
Vertex of a mesh.
Definition Vertex.hpp:16
VertexID getID() const
Returns the unique (among vertices of one mesh on one processor) ID of the vertex.
Definition Vertex.hpp:109
void setCoords(const VECTOR_T &coordinates)
Sets the coordinates of the vertex.
Definition Vertex.hpp:101
Eigen::VectorXd getCoords() const
Returns the coordinates of the vertex.
Definition Vertex.hpp:114
void stop()
Stops a running event.
Definition Event.cpp:51
void addData(std::string_view key, int value)
Adds named integer data, associated to an event.
Definition Event.cpp:63
Class to query the index trees of the mesh.
Definition Index.hpp:64
std::vector< VertexID > getVerticesInsideBox(const mesh::Vertex &centerVertex, double radius)
Return all the vertices inside the box formed by vertex and radius (boundary exclusive)
Definition Index.cpp:223
static int getSize()
Number of ranks. This includes ranks from both participants, e.g. minimal size is 2.
Definition IntraComm.cpp:47
static Rank getRank()
Current rank.
Definition IntraComm.cpp:42
static bool isPrimary()
True if this process is running the primary rank.
Definition IntraComm.cpp:52
static auto allSecondaryRanks()
Returns an iterable range over salve ranks [1, _size)
Definition IntraComm.hpp:37
static bool isSecondary()
True if this process is running a secondary rank.
Definition IntraComm.cpp:57
static com::PtrCommunication & getCommunication()
Intra-participant communication.
Definition IntraComm.hpp:31
T empty(T... args)
T end(T... args)
T for_each(T... args)
T make_unique(T... args)
T max_element(T... args)
T min_element(T... args)
contains the logging framework.
std::tuple< double, Vertices > createClustering(mesh::PtrMesh inMesh, mesh::PtrMesh outMesh, double relativeOverlap, unsigned int verticesPerCluster, bool projectClustersToInput)
Creates a clustering as a collection of Vertices (representing the cluster centers) and a cluster rad...
double estimateClusterRadius(unsigned int verticesPerCluster, mesh::PtrMesh inMesh, const mesh::BoundingBox &bb)
Computes an estimate for the cluster radius, which results in approximately verticesPerCluster vertic...
contains data mapping from points to meshes.
Polynomial
How to handle the polynomial?
provides Mesh, Data and primitives.
std::shared_ptr< Mesh > PtrMesh
static constexpr SynchronizeTag Synchronize
Convenience instance of the SynchronizeTag.
Definition Event.hpp:28
Main namespace of the precice library.
int VertexID
Definition Types.hpp:13
bool syncMode
Enabled further inter- and intra-solver synchronisation.
STL namespace.
T resize(T... args)
T size(T... args)
std::vector< Eigen::MatrixXd > polynomialContributions
int getDataDimensions() const
Returns the number of data components.
T transform(T... args)