preCICE v3.2.0
Loading...
Searching...
No Matches
Mapping.cpp
Go to the documentation of this file.
1#include "Mapping.hpp"
2#include <boost/config.hpp>
3#include <ostream>
5#include "mesh/Utils.hpp"
6#include "profiling/Event.hpp"
7#include "utils/IntraComm.hpp"
8#include "utils/assertion.hpp"
9
10namespace precice::mapping {
11
27
29 const mesh::PtrMesh &input,
30 const mesh::PtrMesh &output)
31{
32 _input = input;
34}
35
37{
38 return _input;
39}
40
42{
43 return _output;
44}
45
50
55
57{
58 PRECICE_ASSERT(requiresInitialGuess(), "This mapping isn't iterative, so it cannot have an initial guess.");
59 PRECICE_ASSERT(_initialGuess != nullptr, "The last solution wasn't provided.");
60 return _initialGuess->size() > 0;
61}
62
63const Eigen::VectorXd &Mapping::initialGuess() const
64{
65 PRECICE_ASSERT(requiresInitialGuess(), "This mapping isn't iterative, so it doesn't have an initial guess.");
66 PRECICE_ASSERT(_initialGuess != nullptr, "The last solution wasn't provided.");
67 return *_initialGuess;
68}
69
70Eigen::VectorXd &Mapping::initialGuess()
71{
72 PRECICE_ASSERT(requiresInitialGuess(), "This mapping isn't iterative, so it doesn't have an initial guess.");
73 PRECICE_ASSERT(_initialGuess != nullptr, "The last solution wasn't provided.");
74 return *_initialGuess;
75}
76
81
86
88{
89 return _input;
90}
91
93{
94 return _output;
95}
96
98 MeshRequirement requirement)
99{
100 _inputRequirement = requirement;
101}
102
104 MeshRequirement requirement)
105{
106 _outputRequirement = requirement;
107}
108
110{
111 return _dimensions;
112}
113
115{
117}
118
119void Mapping::map(int inputDataID, int outputDataID, Eigen::VectorXd &initialGuess)
120{
121 PRECICE_ASSERT(_initialGuess == nullptr);
123 map(inputDataID, outputDataID);
124 _initialGuess = nullptr;
125}
126
127void Mapping::map(int inputDataID,
128 int outputDataID)
129{
131 PRECICE_ASSERT(!requiresInitialGuess() || _initialGuess != nullptr, "Call the map version with lastSolution");
132
137 PRECICE_ASSERT(input()->data(inputDataID)->getDimensions() == output()->data(outputDataID)->getDimensions(),
138 input()->data(inputDataID)->getDimensions(), output()->data(outputDataID)->getDimensions());
139 PRECICE_ASSERT(input()->data(inputDataID)->values().size() / input()->data(inputDataID)->getDimensions() == static_cast<int>(input()->nVertices()),
140 input()->data(inputDataID)->values().size(), input()->data(inputDataID)->getDimensions(), input()->nVertices());
141 PRECICE_ASSERT(output()->data(outputDataID)->values().size() / output()->data(outputDataID)->getDimensions() == static_cast<int>(output()->nVertices()),
142 output()->data(outputDataID)->values().size(), output()->data(outputDataID)->getDimensions(), output()->nVertices());
143
144 time::Sample sample{input()->data(inputDataID)->getDimensions(),
145 input()->data(inputDataID)->values(),
146 input()->data(inputDataID)->gradients()};
147 map(sample, output()->data(outputDataID)->values());
148}
149
150void Mapping::map(const time::Sample &input, Eigen::VectorXd &output, Eigen::VectorXd &lastSolution)
151{
152 PRECICE_ASSERT(_initialGuess == nullptr);
153 _initialGuess = &lastSolution;
154 map(input, output);
155 _initialGuess = nullptr;
156}
157
158void Mapping::map(const time::Sample &input, Eigen::VectorXd &output)
159{
161 PRECICE_ASSERT(!requiresInitialGuess() || _initialGuess != nullptr, "Call the map version with lastSolution");
162
165 } else if (hasConstraint(CONSISTENT)) {
167 } else if (isScaledConsistent()) {
170 } else {
171 PRECICE_UNREACHABLE("Unknown mapping constraint.")
172 }
173}
174
175void Mapping::scaleConsistentMapping(const Eigen::VectorXd &input, Eigen::VectorXd &output, Mapping::Constraint constraint) const
176{
178
179 if (input.size() == 0 || output.size() == 0) {
180 return;
181 }
182 PRECICE_ASSERT(input.size() > 0 && output.size() > 0);
183
184 bool volumeMode = hasConstraint(SCALED_CONSISTENT_VOLUME);
185 logging::Logger _log{"mapping::Mapping"};
186 // Only serial participant is supported for scale-consistent mapping
188
189 // If rank is not empty and do not contain connectivity information, raise error
190 int spaceDimension = this->input()->getDimensions();
191 bool requiresEdges = (spaceDimension == 2 and !volumeMode);
192 bool requiresTriangles = (spaceDimension == 2 and volumeMode) or (spaceDimension == 3 and !volumeMode);
193 bool requiresTetra = (spaceDimension == 3 and volumeMode);
194
195 for (mesh::PtrMesh mesh : {this->input(), this->output()}) {
196 if (not mesh->empty()) {
197
198 PRECICE_CHECK(!(requiresEdges && mesh->edges().empty()), "Edges connectivity information is missing for the mesh \"{}\". "
199 "Scaled consistent mapping requires connectivity information.",
200 mesh->getName());
201
202 PRECICE_CHECK(!(requiresTriangles && mesh->triangles().empty()), "Triangles connectivity information is missing for the mesh \"{}\". "
203 "Scaled consistent mapping requires connectivity information.",
204 mesh->getName());
205
206 PRECICE_CHECK(!(requiresTetra && mesh->tetrahedra().empty()), "Tetrahedra connectivity information is missing for the mesh \"{}\". "
207 "Scaled consistent mapping requires connectivity information.",
208 mesh->getName());
209 }
210 }
211
212 const int valueDimensions = input.size() / this->input()->nVertices();
213
214 Eigen::VectorXd integralInput;
215 Eigen::VectorXd integralOutput;
216
217 // Integral is calculated on each direction separately
218 if (!volumeMode) {
219 integralInput = mesh::integrateSurface(this->input(), input);
220 integralOutput = mesh::integrateSurface(this->output(), output);
221 } else {
222 integralInput = mesh::integrateVolume(this->input(), input);
223 integralOutput = mesh::integrateVolume(this->output(), output);
224 }
225
226 // Create reshape the output values vector to matrix
227 Eigen::Map<Eigen::MatrixXd> outputValuesMatrix(output.data(), valueDimensions, output.size() / valueDimensions);
228
229 // Scale in each direction
230 // We cannot handle the case with zero output data and non-zero input data.
231 // To fulfill the constraint, we would need to scale the output data in such a way, that the integral sum of the input is preserved.
232 // That's not possible using a constant scaling factor as the output sum will always be zero. Here, we return 1 and emit a warning afterwards.
233 const Eigen::VectorXd scalingFactor = integralInput.binaryExpr(integralOutput, [](double lhs, double rhs) { return (rhs == 0.0) ? 1.0 : (lhs / rhs); });
234 PRECICE_DEBUG("Scaling factor in scaled-consistent mapping: {}", scalingFactor);
235
236 PRECICE_DEBUG("Scaling factor in scaled-consistent mapping: {}", scalingFactor);
237 outputValuesMatrix.array().colwise() *= scalingFactor.array();
238
239 // check whether the constraint is fulfilled
240 for (Eigen::Index i = 0; i < scalingFactor.size(); ++i) {
241 double consistency = scalingFactor[i] * integralOutput[i] - integralInput[i];
243 math::greater(std::abs(consistency), 0.0),
244 "Failed to fulfill consistency constraint of component {} for scaled-consistent mapping from mesh \"{}\" to mesh \"{}\". Consistency difference between input and scaled output is \"{}\".", i, this->input()->getName(), this->output()->getName(), consistency);
245 }
246}
247
248bool Mapping::hasConstraint(const Constraint &constraint) const
249{
250 return (getConstraint() == constraint);
251}
252
254{
255 return _hasComputedMapping;
256}
257
262
264{
267 return _input->isJustInTime() || _output->isJustInTime();
268}
269
270void Mapping::updateMappingDataCache(impl::MappingDataCache &cache, const Eigen::Ref<const Eigen::VectorXd> &in)
271{
272 precice::profiling::Event e("map.updateMappingDataCache.From" + input()->getName());
273 // By default, we simply store the time interpolant of the last function call,
274 // such that we don't need to evaluate the waveform relaxation for each provided
275 // coordinate. That's already sufficient for NN, as we cannot precompute anything
276 // more specific (as opposed to PUM or (albeit not implemented) RBF interpolation,
277 // where we can further compute the RBF coefficients belonging to the time sample)
278 cache.inData.sample.values = in;
279}
280
282{
283 // Do nothing by default, only relevant for just-in-time mapping using PUM, but we need the interface.
284 // We don't enforce its implementation through the (virtual) base class,
285 // but instead provide an empty default implementation and implement it
286 // only in derived classes where necessary.
287
288 // Note that an implementation for NN is not required, and this function is for NN a NOOP
289 // as opposed to the default of, e.g., mapConsistentAt, where we abort in the default setting
290}
291
292void Mapping::mapConservativeAt(const Eigen::Ref<const Eigen::MatrixXd> &coordinates, const Eigen::Ref<const Eigen::MatrixXd> &source, impl::MappingDataCache &cache, Eigen::Ref<Eigen::MatrixXd> target)
293{
294 // Function for just-in-time mapping. Only implemented for PUM and NN.
295 // We don't enforce its implementation through the (virtual) base class,
296 // but instead provide an abortive default implementation and implement it
297 // only in derived classes where deemed useful
298 PRECICE_ASSERT(false, "Not implemented");
299}
300
301void Mapping::completeJustInTimeMapping(impl::MappingDataCache &cache, Eigen::Ref<Eigen::MatrixXd> buffer)
302{
303 // Do nothing by default, only relevant for just-in-time mapping using PUM, but we need the interface.
304 // We don't enforce its implementation through the (virtual) base class,
305 // but instead provide an empty default implementation and implement it
306 // only in derived classes where necessary.
307
308 // Note that an implementation for NN is not required, and this function is for NN a NOOP
309 // as opposed to the default of mapConsistentAt, where we abort in the default setting
310}
311
312void Mapping::mapConsistentAt(const Eigen::Ref<const Eigen::MatrixXd> &coordinates, const impl::MappingDataCache &cache, Eigen::Ref<Eigen::MatrixXd> values)
313{
314 // Function for just-in-time mapping. Only implemented for PUM and NN.
315 // We don't enforce its implementation through the (virtual) base class,
316 // but instead provide an abortive default implementation and implement it
317 // only in derived classes where deemed useful
318 PRECICE_ASSERT(false, "Not implemented");
319}
320
322{
323 switch (lhs) {
327 return rhs == Mapping::MeshRequirement::FULL;
329 return false;
330 };
331 BOOST_UNREACHABLE_RETURN(false);
332}
333
335{
336 switch (val) {
338 out << "UNDEFINED";
339 break;
341 out << "VERTEX";
342 break;
344 out << "FULL";
345 break;
346 default:
347 PRECICE_ASSERT(false, "Implementation does not cover all cases");
348 };
349 return out;
350}
351
352} // namespace precice::mapping
#define PRECICE_WARN_IF(condition,...)
Definition LogMacros.hpp:18
#define PRECICE_DEBUG(...)
Definition LogMacros.hpp:61
#define PRECICE_CHECK(check,...)
Definition LogMacros.hpp:32
#define PRECICE_ASSERT(...)
Definition assertion.hpp:85
#define PRECICE_UNREACHABLE(...)
Definition assertion.hpp:93
This class provides a lightweight logger.
Definition Logger.hpp:17
bool requiresInitialGuess() const
Return true if the mapping requires an initial guess.
Definition Mapping.cpp:51
mesh::PtrMesh output() const
Returns pointer to output mesh.
Definition Mapping.cpp:92
virtual void initializeMappingDataCache(impl::MappingDataCache &cache)
Allocates memory and sets up the data structures inside the MappingDataCache.
Definition Mapping.cpp:281
Constraint _constraint
Determines whether mapping is consistent or conservative.
Definition Mapping.hpp:341
mesh::PtrMesh _input
Pointer to input mesh.
Definition Mapping.hpp:350
virtual void mapConsistent(const time::Sample &input, Eigen::VectorXd &output)=0
Maps data using a consistent constraint.
MeshRequirement
Specifies requirements for the input and output meshes of a mapping.
Definition Mapping.hpp:46
Constraint
Specifies additional constraints for a mapping.
Definition Mapping.hpp:30
Eigen::VectorXd * _initialGuess
Pointer to the initialGuess set and unset by map.
Definition Mapping.hpp:361
virtual void completeJustInTimeMapping(impl::MappingDataCache &cache, Eigen::Ref< Eigen::MatrixXd > result)
Completes a just-in-time mapping for conservative constraints.
Definition Mapping.cpp:301
InitialGuessRequirement _initialGuessRequirement
The InitialGuessRequirement of the Mapping.
Definition Mapping.hpp:358
virtual void mapConsistentAt(const Eigen::Ref< const Eigen::MatrixXd > &coordinates, const impl::MappingDataCache &cache, Eigen::Ref< Eigen::MatrixXd > values)
Just-in-time mapping variant of mapConsistent.
Definition Mapping.cpp:312
virtual void updateMappingDataCache(impl::MappingDataCache &cache, const Eigen::Ref< const Eigen::VectorXd > &in)
Allows updating a so-called MappingDataCache for more efficient just-in-time mappings.
Definition Mapping.cpp:270
void setMeshes(const mesh::PtrMesh &input, const mesh::PtrMesh &output)
Sets input and output meshes carrying data to be mapped.
Definition Mapping.cpp:28
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 isJustInTimeMapping() const
Definition Mapping.cpp:263
Constraint getConstraint() const
Returns the constraint (consistent/conservative) of the mapping.
Definition Mapping.cpp:46
bool isScaledConsistent() const
Returns true if mapping is a form of scaled consistent mapping.
Definition Mapping.cpp:258
virtual void scaleConsistentMapping(const Eigen::VectorXd &input, Eigen::VectorXd &output, Constraint type) const
Scales the consistently mapped output data such that the surface integral of the values on input mesh...
Definition Mapping.cpp:175
void setInputRequirement(MeshRequirement requirement)
Sets the mesh requirement for the input mesh.
Definition Mapping.cpp:97
bool hasInitialGuess() const
True if initialGuess().size() == 0.
Definition Mapping.cpp:56
mesh::PtrMesh _output
Pointer to output mesh.
Definition Mapping.hpp:353
bool requiresGradientData() const
Returns whether the mapping requires gradient data.
Definition Mapping.cpp:114
virtual void mapConservativeAt(const Eigen::Ref< const Eigen::MatrixXd > &coordinates, const Eigen::Ref< const Eigen::MatrixXd > &source, impl::MappingDataCache &cache, Eigen::Ref< Eigen::MatrixXd > target)
Just-in-time mapping variant of mapConservative.
Definition Mapping.cpp:292
MeshRequirement _inputRequirement
Requirement on input mesh.
Definition Mapping.hpp:344
virtual std::string getName() const =0
Returns the name of the mapping method for logging purpose.
virtual void mapConservative(const time::Sample &input, Eigen::VectorXd &output)=0
Maps data using a conservative constraint.
MeshRequirement _outputRequirement
Requirement on output mesh.
Definition Mapping.hpp:347
const mesh::PtrMesh & getOutputMesh() const
Definition Mapping.cpp:41
void setOutputRequirement(MeshRequirement requirement)
Sets the mesh requirement for the output mesh.
Definition Mapping.cpp:103
const Eigen::VectorXd & initialGuess() const
Return the provided initial guess of a mapping using an initialGuess.
Definition Mapping.cpp:63
bool hasComputedMapping() const
Returns true, if the mapping has been computed.
Definition Mapping.cpp:253
void map(int inputDataID, int outputDataID)
Definition Mapping.cpp:127
MeshRequirement getInputRequirement() const
Returns the requirement on the input mesh.
Definition Mapping.cpp:77
const mesh::PtrMesh & getInputMesh() const
Definition Mapping.cpp:36
MeshRequirement getOutputRequirement() const
Returns the requirement on the output mesh.
Definition Mapping.cpp:82
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
bool _requiresGradientData
Flag if gradient data is required for the mapping.
Definition Mapping.hpp:310
static bool isPrimary()
True if this process is running the primary rank.
Definition IntraComm.cpp:52
static bool isSecondary()
True if this process is running a secondary rank.
Definition IntraComm.cpp:57
contains data mapping from points to meshes.
bool operator<(Mapping::MeshRequirement lhs, Mapping::MeshRequirement rhs)
Definition Mapping.cpp:321
std::ostream & operator<<(std::ostream &out, Mapping::MeshRequirement val)
Definition Mapping.cpp:334
std::enable_if< std::is_arithmetic< Scalar >::value, bool >::type greater(Scalar A, Scalar B, Scalar tolerance=NUMERICAL_ZERO_DIFFERENCE)
provides Mesh, Data and primitives.
Eigen::VectorXd integrateSurface(const PtrMesh &mesh, const Eigen::VectorXd &input)
Given the data and the mesh, this function returns the surface integral. Assumes no overlap exists fo...
Definition Utils.cpp:11
Eigen::VectorXd integrateVolume(const PtrMesh &mesh, const Eigen::VectorXd &input)
Given the data and the mesh, this function returns the volume integral. Assumes no overlap exists for...
Definition Utils.cpp:41
std::shared_ptr< Mesh > PtrMesh
static precice::logging::Logger _log("precicec")
Eigen::VectorXd values
Definition Sample.hpp:64