preCICE v3.3.1
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::transform_reduce(
218 _clusters.begin(), _clusters.end(), size_t{0}, std::plus<>(),
219 [](const auto &c) { return c.getNumberOfInputVertices(); }) /
220 _clusters.size());
221 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());
222 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());
223 }
224
225 precice::profiling::Event eWeights("map.pou.computeMapping.computeWeights");
226 // Log a bounding box of the center mesh
227 _centerMesh->computeBoundingBox();
228 PRECICE_DEBUG("Bounding Box of the cluster centers {}", _centerMesh->getBoundingBox());
229
230 // Step 3: Determine PU weights
231 PRECICE_DEBUG("Computing cluster-vertex association");
232 for (const auto &vertex : outMesh->vertices()) {
233 // we use a helper function, as we need the same functionality for just-in-time mapping
234 auto [clusterIDs, normalizedWeights] = computeNormalizedWeight(vertex, outMesh->getName());
235 // Step 4: store the normalized weight in all associated clusters
236 for (unsigned int i = 0; i < clusterIDs.size(); ++i) {
237 PRECICE_ASSERT(clusterIDs[i] < static_cast<int>(_clusters.size()));
238 _clusters[clusterIDs[i]].setNormalizedWeight(normalizedWeights[i], vertex.getID());
239 }
240 }
241 eWeights.stop();
242
243 // Uncomment to add a VTK export of the cluster center distribution for visualization purposes
244 // exportClusterCentersAsVTU(*_centerMesh);
245
246 // we need the center mesh index data structure
247 if (!outMesh->isJustInTime()) {
248 _centerMesh.reset();
249 }
250
251 this->_hasComputedMapping = true;
252}
253
254template <typename RADIAL_BASIS_FUNCTION_T>
256{
257
258 // Step 1: index the clusters / the center mesh in order to define the output vertex -> cluster ownership
259 // the ownership is required to compute the normalized partition of unity weights (Step 2)
260 // query::Index clusterIndex(*_centerMesh.get());
262 query::Index &clusterIndex = _centerMesh->index();
263
264 // 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
265 // Here, we do this using the RTree on the centerMesh: VertexID (queried from the centersMesh) == clusterID, by construction above. The loop uses
266 // the vertices to compute the weights required for the partition of unity data mapping.
267 // 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.
268
269 // Step 2a: get the relevant clusters for the output vertex
270 auto clusterIDs = clusterIndex.getVerticesInsideBox(vertex, _clusterRadius);
271 const auto localNumberOfClusters = clusterIDs.size();
272
273 // Consider the case where we didn't find any cluster (meshes don't match very well)
274 //
275 // In principle, we could assign the vertex to the closest cluster using clusterIDs.emplace_back(clusterIndex.getClosestVertex(vertex.getCoords()).index);
276 // 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
277 // Of course, we could rearrange the weights, but we want to avoid the case here anyway, i.e., prefer to abort.
278 PRECICE_CHECK(localNumberOfClusters > 0,
279 "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. "
280 "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\". "
281 "These options are only valid for the <mapping:rbf-pum-direct/> tag.",
282 vertex.getCoords(), mesh);
283
284 // Next we compute the normalized weights of each output vertex for each partition
285 PRECICE_ASSERT(localNumberOfClusters > 0, "No cluster found for vertex {}", vertex.getCoords());
286
287 // Step 2b: compute the weight in each partition individually and store them in 'weights'
288 std::vector<double> weights(localNumberOfClusters);
289 std::transform(clusterIDs.cbegin(), clusterIDs.cend(), weights.begin(), [&](const auto &ids) { return _clusters[ids].computeWeight(vertex); });
290 double weightSum = std::accumulate(weights.begin(), weights.end(), static_cast<double>(0.));
291 // TODO: This covers the edge case of vertices being at the edge of (several) clusters
292 // In case the sum is equal to zero, we assign equal weights for all clusters
293 if (weightSum <= 0) {
294 PRECICE_ASSERT(weights.size() > 0);
295 std::for_each(weights.begin(), weights.end(), [&weights](auto &w) { w = 1. / weights.size(); });
296 weightSum = 1;
297 }
298 PRECICE_ASSERT(weightSum > 0);
299
300 // Step 2c: Normalize weights
301 std::transform(weights.begin(), weights.end(), weights.begin(), [weightSum](double w) { return w / weightSum; });
302
303 // Return both the cluster IDs and the normalized weights
304 return {clusterIDs, weights};
305}
306
307template <typename RADIAL_BASIS_FUNCTION_T>
309{
311
312 precice::profiling::Event e("map.pou.mapData.From" + input()->getName() + "To" + output()->getName(), profiling::Synchronize);
313
314 // Execute the actual mapping evaluation in all clusters
315 // 1. Assert that all output data values were reset, as we accumulate data in all clusters independently
316 PRECICE_ASSERT(outData.isZero());
317
318 // 2. Iterate over all clusters and accumulate the result in the output data
319 std::for_each(_clusters.begin(), _clusters.end(), [&](auto &cluster) { cluster.mapConservative(inData, outData); });
320}
321
322template <typename RADIAL_BASIS_FUNCTION_T>
324{
326
327 precice::profiling::Event e("map.pou.mapData.From" + input()->getName() + "To" + output()->getName(), profiling::Synchronize);
328
329 // Execute the actual mapping evaluation in all clusters
330 // 1. Assert that all output data values were reset, as we accumulate data in all clusters independently
331 PRECICE_ASSERT(outData.isZero());
332
333 // 2. Execute the actual mapping evaluation in all vertex clusters and accumulate the data
334 std::for_each(_clusters.begin(), _clusters.end(), [&](auto &clusters) { clusters.mapConsistent(inData, outData); });
335}
336
337template <typename RADIAL_BASIS_FUNCTION_T>
338void PartitionOfUnityMapping<RADIAL_BASIS_FUNCTION_T>::mapConservativeAt(const Eigen::Ref<const Eigen::MatrixXd> &coordinates, const Eigen::Ref<const Eigen::MatrixXd> &source,
339 impl::MappingDataCache &cache, Eigen::Ref<Eigen::MatrixXd>)
340{
341 precice::profiling::Event e("map.pou.mapConservativeAt.From" + input()->getName());
342 // @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
343
346 PRECICE_ASSERT(cache.p.size() == _clusters.size());
348
349 mesh::Vertex vertex(coordinates.col(0), -1);
350 for (Eigen::Index v = 0; v < coordinates.cols(); ++v) {
351 vertex.setCoords(coordinates.col(v));
352 auto [clusterIDs, normalizedWeights] = computeNormalizedWeight(vertex, this->input()->getName());
353 // Use the weight to interpolate the solution
354 for (std::size_t i = 0; i < clusterIDs.size(); ++i) {
355 PRECICE_ASSERT(clusterIDs[i] < static_cast<int>(_clusters.size()));
356 auto id = clusterIDs[i];
357 // the input mesh refers here to a consistent constraint
358 Eigen::VectorXd res = normalizedWeights[i] * source.col(v);
359 _clusters[id].addWriteDataToCache(vertex, res, cache.polynomialContributions[id], cache.p[id], *this->output().get());
360 }
361 }
362}
363
364template <typename RADIAL_BASIS_FUNCTION_T>
366{
368 PRECICE_ASSERT(!cache.p.empty());
370 precice::profiling::Event e("map.pou.completeJustInTimeMapping.From" + input()->getName());
371
372 for (std::size_t c = 0; c < _clusters.size(); ++c) {
373 // If there is no contribution, we don't have to evaluate
374 if (cache.p[c].squaredNorm() > 0) {
375 _clusters[c].evaluateConservativeCache(cache.polynomialContributions[c], cache.p[c], buffer);
376 }
377 }
378}
379
380template <typename RADIAL_BASIS_FUNCTION_T>
382{
385 cache.p.resize(_clusters.size());
387 for (std::size_t c = 0; c < _clusters.size(); ++c) {
388 _clusters[c].initializeCacheData(cache.polynomialContributions[c], cache.p[c], cache.getDataDimensions());
389 }
390}
391
392template <typename RADIAL_BASIS_FUNCTION_T>
394{
395 // We cannot synchronize this event, as the call to this function is rank-local only
396 precice::profiling::Event e("map.pou.updateMappingDataCache.From" + input()->getName());
397 PRECICE_ASSERT(cache.p.size() == _clusters.size());
399 Eigen::Map<const Eigen::MatrixXd> inMatrix(in.data(), cache.getDataDimensions(), in.size() / cache.getDataDimensions());
400 for (std::size_t c = 0; c < _clusters.size(); ++c) {
401 _clusters[c].computeCacheData(inMatrix, cache.polynomialContributions[c], cache.p[c]);
402 }
403}
404
405template <typename RADIAL_BASIS_FUNCTION_T>
406void PartitionOfUnityMapping<RADIAL_BASIS_FUNCTION_T>::mapConsistentAt(const Eigen::Ref<const Eigen::MatrixXd> &coordinates, const impl::MappingDataCache &cache, Eigen::Ref<Eigen::MatrixXd> values)
407{
408 precice::profiling::Event e("map.pou.mapConsistentAt.From" + input()->getName());
409 // @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
412
413 // First, make sure that everything is reset before we start
414 values.setZero();
415
416 mesh::Vertex vertex(coordinates.col(0), -1);
417 for (Eigen::Index v = 0; v < values.cols(); ++v) {
418 vertex.setCoords(coordinates.col(v));
419 auto [clusterIDs, normalizedWeights] = computeNormalizedWeight(vertex, this->output()->getName());
420 // Use the weight to interpolate the solution
421 for (std::size_t i = 0; i < clusterIDs.size(); ++i) {
422 PRECICE_ASSERT(clusterIDs[i] < static_cast<int>(_clusters.size()));
423 auto id = clusterIDs[i];
424 // the input mesh refers here to a consistent constraint
425 Eigen::VectorXd localRes = normalizedWeights[i] * _clusters[id].interpolateAt(vertex, cache.polynomialContributions[id], cache.p[id], *this->input().get());
426 values.col(v) += localRes;
427 }
428 }
429}
430
431template <typename RADIAL_BASIS_FUNCTION_T>
433{
435 mesh::PtrMesh filterMesh, outMesh;
437 filterMesh = this->output(); // remote
438 outMesh = this->input(); // local
439 } else {
440 filterMesh = this->input(); // remote
441 outMesh = this->output(); // local
442 }
443
444 if (outMesh->empty())
445 return; // Ranks not at the interface should never hold interface vertices
446
447 // The geometric filter of the repartitioning is always disabled for the PU-RBF.
448 // The main rationale: if we use only a fraction of the mesh then we might end up
449 // with too few vertices per rank and we cannot prevent too few vertices from being
450 // tagged, if we have filtered too much vertices beforehand. When using the filtering,
451 // the user could increase the safety-factor or disable the filtering, but that's
452 // a bit hard to understand for users. When no geometric filter is applid,
453 // vertices().size() is here the same as getGlobalNumberOfVertices. Hence, it is much
454 // safer to make use of the unfiltered mesh for the parallel tagging.
455 //
456 // Drawback: the "estimateClusterRadius" below makes use of the mesh R* index tree, and
457 // constructing the tree on the (unfiltered) global mesh is computationally expensive (O( N logN)).
458 // We could pre-filter the global mesh to a local fraction (using our own geometric filtering,
459 // maybe with an increased safety margin or even an iterative increase of the safety margin),
460 // but then there is again the question on how to do this in a safe way, without risking
461 // failures depending on the partitioning. So we stick here to the computationally more
462 // demanding, but safer version.
463 // See also https://github.com/precice/precice/pull/1912#issuecomment-2551143620
464
465 // Get the local bounding boxes
466 auto localBB = outMesh->getBoundingBox();
467 // we cannot check for empty'ness here, as a single output mesh vertex
468 // would lead to a 0D box with zero volume (considered empty). Thus, we
469 // simply check here for default'ness, which is equivalent to outMesh->empty()
470 // further above
471 PRECICE_ASSERT(!localBB.isDefault());
472
473 if (_clusterRadius == 0)
475
476 PRECICE_DEBUG("Cluster radius estimate: {}", _clusterRadius);
478
479 // Now we extend the bounding box by the radius
480 localBB.expandBy(2 * _clusterRadius);
481
482 // ... and tag all affected vertices
483 auto verticesNew = filterMesh->index().getVerticesInsideBox(localBB);
484
485 std::for_each(verticesNew.begin(), verticesNew.end(), [&filterMesh](VertexID v) { filterMesh->vertex(v).tag(); });
486}
487
488template <typename RADIAL_BASIS_FUNCTION_T>
490{
491 // 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.
492}
493
494template <typename RADIAL_BASIS_FUNCTION_T>
496{
498
499 auto dataRadius = centerMesh.createData("radius", 1, -1);
500 auto dataCardinality = centerMesh.createData("number-of-vertices", 1, -1);
501 centerMesh.allocateDataValues();
502 dataRadius->values().fill(_clusterRadius);
503 for (unsigned int i = 0; i < _clusters.size(); ++i) {
504 dataCardinality->values()[i] = static_cast<double>(_clusters[i].getNumberOfInputVertices());
505 }
506
507 // We have to create the global offsets in order to export things in parallel
509 // send number of vertices
510 PRECICE_DEBUG("Send number of vertices: {}", centerMesh.nVertices());
511 int numberOfVertices = centerMesh.nVertices();
512 utils::IntraComm::getCommunication()->send(numberOfVertices, 0);
513
514 // receive vertex offsets
515 mesh::Mesh::VertexOffsets vertexOffsets;
516 utils::IntraComm::getCommunication()->broadcast(vertexOffsets, 0);
517 PRECICE_DEBUG("Vertex offsets: {}", vertexOffsets);
518 PRECICE_ASSERT(centerMesh.getVertexOffsets().empty());
519 centerMesh.setVertexOffsets(std::move(vertexOffsets));
520 } else if (utils::IntraComm::isPrimary()) {
521
523 vertexOffsets[0] = centerMesh.nVertices();
524
525 // receive number of secondary vertices and fill vertex offsets
526 for (int secondaryRank : utils::IntraComm::allSecondaryRanks()) {
527 int numberOfSecondaryRankVertices = -1;
528 utils::IntraComm::getCommunication()->receive(numberOfSecondaryRankVertices, secondaryRank);
529 PRECICE_ASSERT(numberOfSecondaryRankVertices >= 0);
530 vertexOffsets[secondaryRank] = numberOfSecondaryRankVertices + vertexOffsets[secondaryRank - 1];
531 }
532
533 // broadcast vertex offsets
534 PRECICE_DEBUG("Vertex offsets: {}", centerMesh.getVertexOffsets());
535 utils::IntraComm::getCommunication()->broadcast(vertexOffsets);
536 centerMesh.setVertexOffsets(std::move(vertexOffsets));
537 }
538
539 dataRadius->setSampleAtTime(0, time::Sample{1, dataRadius->values()});
540 dataCardinality->setSampleAtTime(0, time::Sample{1, dataCardinality->values()});
542 exporter.doExport(0, 0.0);
543}
544
545template <typename RADIAL_BASIS_FUNCTION_T>
547{
549 _clusters.clear();
550 // TODO: Don't reset this here
551 _clusterRadius = 0;
552 this->_hasComputedMapping = false;
553}
554
555template <typename RADIAL_BASIS_FUNCTION_T>
557{
558 return "partition-of-unity RBF";
559}
560} // namespace mapping
561} // 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)
T transform_reduce(T... args)