preCICE
Loading...
Searching...
No Matches
BarycentricBaseMapping.cpp
Go to the documentation of this file.
1#include <Eigen/Core>
2#include <algorithm>
3#include <memory>
4#include <ostream>
5#include <unordered_set>
6#include <utility>
7
10#include "mapping/Mapping.hpp"
11#include "mapping/Polation.hpp"
12#include "math/differences.hpp"
13#include "mesh/Data.hpp"
14#include "mesh/Mesh.hpp"
16#include "mesh/Vertex.hpp"
17#include "profiling/Event.hpp"
18#include "query/Index.hpp"
19#include "utils/IntraComm.hpp"
20#include "utils/Statistics.hpp"
21#include "utils/assertion.hpp"
22
23namespace precice::mapping {
24
26 : Mapping(constraint, dimensions, false, Mapping::InitialGuessRequirement::None)
27{
28}
29
36
37namespace {
38
39template <int n>
40void mapTemplatedConsistent(const std::vector<Operation> &ops, const Eigen::VectorXd &in, Eigen::VectorXd &out)
41{
42 static_assert(n > 0 && n <= 3);
43 // For each output vertex, compute the linear combination of input vertices
44 // Do it for all dimensions (i.e. components if data is a vector)
45 for (const auto &op : ops) {
46 if constexpr (n == 1) {
47 // We use a direct index-loop when no dimension offset is required
48 out[op.out] += op.weight * in[op.in];
49 } else {
50 // Segments of templated size are the fastest option when the data has multiple components
51 out.segment<n>(op.out * n).noalias() += op.weight * in.segment<n>(op.in * n);
52 }
53 }
54}
55
56template <int n>
57void mapTemplatedConservative(const std::vector<Operation> &ops, const Eigen::VectorXd &in, Eigen::VectorXd &out)
58{
59 static_assert(n > 0 && n <= 3);
60 // For each input vertex, distribute the conserved data among the relevant output vertices
61 // Do it for all dimensions (i.e. components if data is a vector)
62 for (const auto &op : ops) {
63 if constexpr (n == 1) {
64 // We use a direct index-loop when no dimension offset is required
65 out[op.in] += op.weight * in[op.out];
66 } else {
67 // Segments of templated size are the fastest option when the data has multiple components
68 out.segment<n>(op.in * n).noalias() += op.weight * in.segment<n>(op.out * n);
69 }
70 }
71}
72
73} // namespace
74
75void BarycentricBaseMapping::mapConservative(const time::Sample &inData, Eigen::VectorXd &outData)
76{
78 precice::profiling::Event e("map.bbm.mapData.From" + input()->getName() + "To" + output()->getName(), profiling::Synchronize);
80 PRECICE_DEBUG("Map conservative using {}", getName());
81 const int dimensions = inData.dataDims;
82 const Eigen::VectorXd &inValues = inData.values;
83 Eigen::VectorXd &outValues = outData;
84
85 switch (dimensions) {
86 case 1:
87 mapTemplatedConservative<1>(_operations, inValues, outValues);
88 return;
89 case 2:
90 mapTemplatedConservative<2>(_operations, inValues, outValues);
91 return;
92 case 3:
93 mapTemplatedConservative<3>(_operations, inValues, outValues);
94 return;
95 default:
96 PRECICE_UNREACHABLE("Not implemented for unknown dimension");
97 // Required for https://github.com/precice/precice/issues/2085
98 // for (const auto &op : _operations) {
99 // outValues.segment(op.in * dimensions, dimensions) += op.weight * inValues.segment(op.out * dimensions, dimensions); }
100 }
101}
102
103void BarycentricBaseMapping::mapConsistent(const time::Sample &inData, Eigen::VectorXd &outData)
104{
106 precice::profiling::Event e("map.bbm.mapData.From" + input()->getName() + "To" + output()->getName(), profiling::Synchronize);
107 PRECICE_DEBUG("Map {} using {}", (hasConstraint(CONSISTENT) ? "consistent" : "scaled-consistent"), getName());
108
109 const int dimensions = inData.dataDims;
110 const Eigen::VectorXd &inValues = inData.values;
111 Eigen::VectorXd &outValues = outData;
112
113 switch (dimensions) {
114 case 1:
115 mapTemplatedConsistent<1>(_operations, inValues, outValues);
116 return;
117 case 2:
118 mapTemplatedConsistent<2>(_operations, inValues, outValues);
119 return;
120 case 3:
121 mapTemplatedConsistent<3>(_operations, inValues, outValues);
122 return;
123 default:
124 PRECICE_UNREACHABLE("Not implemented for unknown dimension");
125 // Required for https://github.com/precice/precice/issues/2085
126 // for (const auto &op : _operations) {
127 // outValues.segment(op.out * dimensions, dimensions) += op.weight * inValues.segment(op.in * dimensions, dimensions); }
128 }
129}
130
132{
134 precice::profiling::Event e("map.bbm.tagMeshFirstRound.From" + input()->getName() + "To" + output()->getName(), profiling::Synchronize);
135 PRECICE_DEBUG("Compute Mapping for Tagging");
136
138 PRECICE_DEBUG("Tagging First Round");
139
140 // Determine the Mesh to Tag
141 mesh::PtrMesh origins;
143 origins = output();
144 } else {
145 origins = input();
146 }
147
148 // Gather all vertices to be tagged in a first phase.
149 std::vector<bool> tagged(origins->nVertices(), false);
150 for (const auto &op : _operations) {
151 PRECICE_ASSERT(!math::equals(op.weight, 0.0));
152 tagged[op.in] = true;
153 }
154
155 // Now tag all vertices to be tagged in the second phase.
156 size_t ntagged = 0;
157 for (size_t i = 0; i < origins->nVertices(); ++i) {
158 if (tagged[i]) {
159 origins->vertex(i).tag();
160 ++ntagged;
161 }
162 }
163
164 PRECICE_DEBUG("First Round Tagged {}/{} Vertices", ntagged, origins->nVertices());
165
166 clear();
167}
168
170{
171 for (const auto &we : p.getWeightedElements()) {
172 if (!precice::math::equals(we.weight, 0.0)) {
173 _operations.push_back({out, we.vertexID, we.weight});
174 }
175 }
176}
177
179{
181 // We order the operations to make them write sequentially
182 std::sort(_operations.begin(), _operations.end(), [](const auto &lhs, const auto &rhs) {
183 // weak order for a pair
184 if (lhs.in < rhs.in) {
185 return true;
186 }
187 if (rhs.in < lhs.in) {
188 return false;
189 }
190 // lhs.in == rhs.in
191 return lhs.out < rhs.out;
192 });
193 }
194}
195
197{
199 // for NP mapping no operation needed here
200}
201
202} // namespace precice::mapping
#define PRECICE_DEBUG(...)
Definition LogMacros.hpp:61
#define PRECICE_TRACE(...)
Definition LogMacros.hpp:92
#define PRECICE_ASSERT(...)
Definition assertion.hpp:85
#define PRECICE_UNREACHABLE(...)
Definition assertion.hpp:93
std::size_t nVertices() const
Returns the number of vertices.
Definition Mesh.cpp:64
Vertex & vertex(VertexID id)
Mutable access to a vertex by VertexID.
Definition Mesh.cpp:42
void tagMeshFirstRound() final override
Method used by partition. Tags vertices that could be owned by this rank.
void postProcessOperations()
Post processed operations after the mapping has been computed.
void clear() final override
Removes a computed mapping.
void mapConsistent(const time::Sample &inData, Eigen::VectorXd &outData) override
Maps data using a consistent constraint.
void tagMeshSecondRound() final override
Method used by partition. Tags vertices that can be filtered out.
BarycentricBaseMapping(Constraint constraint, int dimensions)
void mapConservative(const time::Sample &inData, Eigen::VectorXd &outData) override
Maps data using a conservative constraint.
void addPolation(VertexID out, const Polation &p)
Takes a polation and registers each weighed input as one Operation.
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
Constraint getConstraint() const
Returns the constraint (consistent/conservative) of the mapping.
Definition Mapping.cpp:46
virtual std::string getName() const =0
Returns the name of the mapping method for logging purpose.
virtual void computeMapping()=0
Computes the mapping coefficients from the in- and output mesh.
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
Calculates the barycentric coordinates of a coordinate on the given vertex/edge/triangle and stores t...
Definition Polation.hpp:23
const boost::container::static_vector< WeightedElement, 4 > & getWeightedElements() const
Get the weights and indices of the calculated interpolation.
Definition Polation.cpp:82
contains data mapping from points to meshes.
constexpr bool equals(const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &B, double tolerance=NUMERICAL_ZERO_DIFFERENCE)
Compares two Eigen::MatrixBase for equality up to tolerance.
std::shared_ptr< Mesh > PtrMesh
static constexpr SynchronizeTag Synchronize
Convenience instance of the SynchronizeTag.
Definition Event.hpp:28
int VertexID
Definition Types.hpp:13
int dataDims
The dimensionality of the data.
Definition Sample.hpp:60
Eigen::VectorXd values
Definition Sample.hpp:64