preCICE
Loading...
Searching...
No Matches
PartitionOfUnityMappingTest.cpp
Go to the documentation of this file.
1#include <Eigen/Core>
2#include <algorithm>
3#include <memory>
4#include <ostream>
5#include <string>
6#include <utility>
7#include <vector>
8#include "logging/Logger.hpp"
9#include "mapping/Mapping.hpp"
13#include "mesh/Data.hpp"
14#include "mesh/Mesh.hpp"
16#include "mesh/Utils.hpp"
17#include "mesh/Vertex.hpp"
20#include "testing/Testing.hpp"
21
22using namespace precice;
23using namespace precice::mesh;
24using namespace precice::mapping;
25using namespace precice::testing;
27
28BOOST_AUTO_TEST_SUITE(MappingTests)
30
31void addGlobalIndex(mesh::PtrMesh &mesh, int offset = 0)
32{
33 for (mesh::Vertex &v : mesh->vertices()) {
34 v.setGlobalIndex(v.getID() + offset);
35 }
36}
37
38double sumComponentWise(const Eigen::VectorXd &vec, int component, int dataDimension)
39{
40 PRECICE_ASSERT(component < dataDimension);
41 double sum = 0;
42 for (unsigned int i = 0; i < vec.size() / dataDimension; ++i) {
43 sum += vec[(i * dataDimension) + component];
44 }
45 return sum;
46}
47
49
51{
52 int dimensions = 2;
53 using Eigen::Vector2d;
54
55 // Create mesh to map from
56 mesh::PtrMesh inMesh(new mesh::Mesh("InMesh", dimensions, testing::nextMeshID()));
57 mesh::PtrData inData = inMesh->createData("InData", 1, 0_dataID);
58 int inDataID = inData->getID();
59 inMesh->createVertex(Vector2d(0.0, 0.0));
60 inMesh->createVertex(Vector2d(1.0, 0.0));
61 inMesh->createVertex(Vector2d(1.0, 1.0));
62 inMesh->createVertex(Vector2d(0.0, 1.0));
63
64 inMesh->createVertex(Vector2d(2.0, 0.0));
65 inMesh->createVertex(Vector2d(3.0, 0.0));
66 inMesh->createVertex(Vector2d(3.0, 1.0));
67 inMesh->createVertex(Vector2d(2.0, 1.0));
68
69 inMesh->createVertex(Vector2d(4.0, 0.0));
70 inMesh->createVertex(Vector2d(5.0, 0.0));
71 inMesh->createVertex(Vector2d(5.0, 1.0));
72 inMesh->createVertex(Vector2d(4.0, 1.0));
73
74 inMesh->allocateDataValues();
75 addGlobalIndex(inMesh);
76
77 auto &values = inData->values();
78 values << 1.0, 2.0, 2.0, 1.0, 3.0, 4.0, 4.0, 3.0, 5.0, 6.0, 6.0, 5.0;
79
80 // Create mesh to map to
81 mesh::PtrMesh outMesh(new mesh::Mesh("OutMesh", dimensions, testing::nextMeshID()));
82 mesh::PtrData outData = outMesh->createData("OutData", 1, 1_dataID);
83 int outDataID = outData->getID();
84 mesh::Vertex &vertex = outMesh->createVertex(Vector2d(0, 0));
85 outMesh->createVertex(Vector2d(3.5, 0.5));
86 outMesh->createVertex(Vector2d(2.5, 0.5));
87 // vertex will be changed
88 outMesh->createVertex(Vector2d(0, 0));
89 outMesh->createVertex(Vector2d(5, 1));
90 outMesh->allocateDataValues();
91 addGlobalIndex(outMesh);
92
93 // Setup mapping with mapping coordinates and geometry used
94 mapping.setMeshes(inMesh, outMesh);
95 BOOST_TEST(mapping.hasComputedMapping() == false);
96
97 vertex.setCoords(Vector2d(0.0, 0.0));
98 mapping.computeMapping();
99 mapping.map(inDataID, outDataID);
100 double value = outData->values()(0);
101 double value1 = outData->values()(1);
102 double value2 = outData->values()(2);
103 BOOST_TEST(mapping.hasComputedMapping() == true);
104 BOOST_TEST(value == 1.0);
105 BOOST_TEST(value1 == 4.5);
106 BOOST_TEST(value2 == 3.5);
107
108 vertex.setCoords(Vector2d(0.0, 0.5));
109 mapping.clear();
110 outData->values().setZero();
111 BOOST_TEST(mapping.hasComputedMapping() == false);
112 mapping.computeMapping();
113 mapping.map(inDataID, outDataID);
114 value = outData->values()(0);
115 BOOST_TEST(mapping.hasComputedMapping() == true);
116 BOOST_TEST(value == 1.0);
117
118 vertex.setCoords(Vector2d(0.0, 1.0));
119 mapping.clear();
120 outData->values().setZero();
121 mapping.computeMapping();
122 mapping.map(inDataID, outDataID);
123 value = outData->values()(0);
124 BOOST_TEST(mapping.hasComputedMapping() == true);
125 BOOST_TEST(value == 1.0);
126
127 vertex.setCoords(Vector2d(1.0, 0.0));
128 mapping.clear();
129 outData->values().setZero();
130 mapping.computeMapping();
131 mapping.map(inDataID, outDataID);
132 value = outData->values()(0);
133 BOOST_TEST(mapping.hasComputedMapping() == true);
134 BOOST_TEST(value == 2.0);
135
136 vertex.setCoords(Vector2d(1.0, 0.5));
137 mapping.clear();
138 outData->values().setZero();
139 mapping.computeMapping();
140 mapping.map(inDataID, outDataID);
141 value = outData->values()(0);
142 BOOST_TEST(mapping.hasComputedMapping() == true);
143 BOOST_TEST(value == 2.0);
144
145 vertex.setCoords(Vector2d(1.0, 1.0));
146 mapping.clear();
147 outData->values().setZero();
148 mapping.computeMapping();
149 mapping.map(inDataID, outDataID);
150 value = outData->values()(0);
151 BOOST_TEST(mapping.hasComputedMapping() == true);
152 BOOST_TEST(value == 2.0);
153
154 vertex.setCoords(Vector2d(0.5, 0.0));
155 mapping.clear();
156 outData->values().setZero();
157 mapping.computeMapping();
158 mapping.map(inDataID, outDataID);
159 value = outData->values()(0);
160 BOOST_TEST(mapping.hasComputedMapping() == true);
161 BOOST_TEST(value == 1.5);
162
163 vertex.setCoords(Vector2d(0.5, 0.5));
164 mapping.clear();
165 outData->values().setZero();
166 mapping.computeMapping();
167 mapping.map(inDataID, outDataID);
168 value = outData->values()(0);
169 BOOST_TEST(mapping.hasComputedMapping() == true);
170 BOOST_TEST(value == 1.5);
171
172 vertex.setCoords(Vector2d(0.5, 1.0));
173 mapping.clear();
174 outData->values().setZero();
175 mapping.computeMapping();
176 mapping.map(inDataID, outDataID);
177 value = outData->values()(0);
178 BOOST_TEST(mapping.hasComputedMapping() == true);
179 BOOST_TEST(value == 1.5);
180}
181
183{
184 int dimensions = 2;
185 int dataDimensions = dimensions;
186 using Eigen::Vector2d;
187
188 // Create mesh to map from
189 mesh::PtrMesh inMesh(new mesh::Mesh("InMesh", dimensions, testing::nextMeshID()));
190 mesh::PtrData inData = inMesh->createData("InData", dataDimensions, 0_dataID);
191 int inDataID = inData->getID();
192 inMesh->createVertex(Vector2d(0.0, 0.0));
193 inMesh->createVertex(Vector2d(1.0, 0.0));
194 inMesh->createVertex(Vector2d(1.0, 1.0));
195 inMesh->createVertex(Vector2d(0.0, 1.0));
196
197 inMesh->createVertex(Vector2d(2.0, 0.0));
198 inMesh->createVertex(Vector2d(3.0, 0.0));
199 inMesh->createVertex(Vector2d(3.0, 1.0));
200 inMesh->createVertex(Vector2d(2.0, 1.0));
201
202 inMesh->createVertex(Vector2d(4.0, 0.0));
203 inMesh->createVertex(Vector2d(5.0, 0.0));
204 inMesh->createVertex(Vector2d(5.0, 1.0));
205 inMesh->createVertex(Vector2d(4.0, 1.0));
206
207 inMesh->allocateDataValues();
208 addGlobalIndex(inMesh);
209
210 auto &values = inData->values();
211 // We select the second component = 2 * first component
212 values << 1.0, 2.0, 2.0, 4.0, 2.0, 4.0, 1.0, 2.0, 3.0, 6.0, 4.0, 8.0, 4.0, 8.0, 3.0, 6.0, 5.0, 10.0, 6.0, 12.0, 6.0, 12.0, 5.0, 10.0;
213
214 // Create mesh to map to
215 mesh::PtrMesh outMesh(new mesh::Mesh("OutMesh", dimensions, testing::nextMeshID()));
216 mesh::PtrData outData = outMesh->createData("OutData", dataDimensions, 1_dataID);
217 int outDataID = outData->getID();
218 mesh::Vertex &vertex = outMesh->createVertex(Vector2d(0, 0));
219 outMesh->createVertex(Vector2d(3.5, 0.5));
220 outMesh->createVertex(Vector2d(2.5, 0.5));
221 // vertex will be changed
222 outMesh->createVertex(Vector2d(0, 0));
223 outMesh->createVertex(Vector2d(5, 1));
224 outMesh->allocateDataValues();
225 addGlobalIndex(outMesh);
226
227 // Setup mapping with mapping coordinates and geometry used
228 mapping.setMeshes(inMesh, outMesh);
229 BOOST_TEST(mapping.hasComputedMapping() == false);
230
231 vertex.setCoords(Vector2d(0.0, 0.0));
232 mapping.computeMapping();
233 mapping.map(inDataID, outDataID);
234 DataID index = 0;
235 DataID index1 = 1 * dataDimensions;
236 DataID index2 = 2 * dataDimensions;
237 BOOST_TEST(mapping.hasComputedMapping() == true);
238 BOOST_TEST(outData->values()(index) == 1.0);
239 BOOST_TEST(outData->values()(index + 1) == 2.0);
240 BOOST_TEST(outData->values()(index1) == 4.5);
241 BOOST_TEST(outData->values()(index1 + 1) == 9.0);
242 BOOST_TEST(outData->values()(index2) == 3.5);
243 BOOST_TEST(outData->values()(index2 + 1) == 7.0);
244
245 vertex.setCoords(Vector2d(0.0, 0.5));
246 mapping.clear();
247 outData->values().setZero();
248 mapping.computeMapping();
249 mapping.map(inDataID, outDataID);
250 BOOST_TEST(mapping.hasComputedMapping() == true);
251 BOOST_TEST(outData->values()(0) == 1.0);
252 BOOST_TEST(outData->values()(1) == 2.0);
253
254 vertex.setCoords(Vector2d(0.0, 1.0));
255 mapping.clear();
256 outData->values().setZero();
257 mapping.computeMapping();
258 mapping.map(inDataID, outDataID);
259 BOOST_TEST(mapping.hasComputedMapping() == true);
260 BOOST_TEST(outData->values()(0) == 1.0);
261 BOOST_TEST(outData->values()(1) == 2.0);
262
263 vertex.setCoords(Vector2d(1.0, 0.0));
264 mapping.clear();
265 outData->values().setZero();
266 mapping.computeMapping();
267 mapping.map(inDataID, outDataID);
268 BOOST_TEST(mapping.hasComputedMapping() == true);
269 BOOST_TEST(outData->values()(0) == 2.0);
270 BOOST_TEST(outData->values()(1) == 4.0);
271
272 vertex.setCoords(Vector2d(1.0, 0.5));
273 mapping.clear();
274 outData->values().setZero();
275 mapping.computeMapping();
276 mapping.map(inDataID, outDataID);
277 BOOST_TEST(mapping.hasComputedMapping() == true);
278 BOOST_TEST(outData->values()(0) == 2.0);
279 BOOST_TEST(outData->values()(1) == 4.0);
280
281 vertex.setCoords(Vector2d(1.0, 1.0));
282 mapping.clear();
283 outData->values().setZero();
284 mapping.computeMapping();
285 mapping.map(inDataID, outDataID);
286 BOOST_TEST(mapping.hasComputedMapping() == true);
287 BOOST_TEST(outData->values()(0) == 2.0);
288 BOOST_TEST(outData->values()(1) == 4.0);
289
290 vertex.setCoords(Vector2d(0.5, 0.0));
291 mapping.clear();
292 outData->values().setZero();
293 mapping.computeMapping();
294 mapping.map(inDataID, outDataID);
295 BOOST_TEST(mapping.hasComputedMapping() == true);
296 BOOST_TEST(outData->values()(0) == 1.5);
297 BOOST_TEST(outData->values()(1) == 3.0);
298
299 vertex.setCoords(Vector2d(0.5, 0.5));
300 mapping.clear();
301 outData->values().setZero();
302 mapping.computeMapping();
303 mapping.map(inDataID, outDataID);
304 BOOST_TEST(mapping.hasComputedMapping() == true);
305 BOOST_TEST(outData->values()(0) == 1.5);
306 BOOST_TEST(outData->values()(1) == 3.0);
307
308 vertex.setCoords(Vector2d(0.5, 1.0));
309 mapping.clear();
310 outData->values().setZero();
311 mapping.computeMapping();
312 mapping.map(inDataID, outDataID);
313 BOOST_TEST(mapping.hasComputedMapping() == true);
314 BOOST_TEST(outData->values()(0) == 1.5);
315 BOOST_TEST(outData->values()(1) == 3.0);
316}
317
318// Tests the automatic reduction of dead axis
320{
321 // Create mesh to map from
322 mesh::PtrMesh inMesh(new mesh::Mesh("InMesh", dim, testing::nextMeshID()));
323 mesh::PtrData inData = inMesh->createData("InData", 1, 0_dataID);
324 int inDataID = inData->getID();
325
326 // create 20 vertices with two very close lines
327 for (unsigned int i = 0; i < 20; ++i)
328 if (dim == 2) {
329 inMesh->createVertex(Eigen::Vector2d(0.0, 0.0 + i * dim));
330 inMesh->createVertex(Eigen::Vector2d(1e-5, 0.0 + i * dim));
331 } else {
332 inMesh->createVertex(Eigen::Vector3d(7.0, 7.0, 40 + i * dim));
333 inMesh->createVertex(Eigen::Vector3d(7.001, 7.001, 40 + i * dim));
334 }
335
336 inMesh->allocateDataValues();
337 addGlobalIndex(inMesh);
338
339 auto &values = inData->values();
340 for (std::size_t v = 0; v < 20; ++v) {
341 values[v * 2] = v * dim * 1e-5;
342 values[v * 2 + 1] = v * dim * 1e-5 + 2;
343 }
344
345 // Create mesh to map to
346 mesh::PtrMesh outMesh(new mesh::Mesh("OutMesh", dim, testing::nextMeshID()));
347 mesh::PtrData outData = outMesh->createData("OutData", 1, 1_dataID);
348 int outDataID = outData->getID();
349
350 for (unsigned int i = 0; i < 15; ++i) {
351 if (dim == 2)
352 outMesh->createVertex(Eigen::Vector2d(.1, 1 + 1 + i * dim));
353 else {
354 outMesh->createVertex(Eigen::Vector3d(7.4, 7.4, 41 + i * dim));
355 }
356 }
357 outMesh->allocateDataValues();
358 addGlobalIndex(outMesh);
359
360 // Setup mapping with mapping coordinates and geometry used
361 mapping.setMeshes(inMesh, outMesh);
362 BOOST_TEST(mapping.hasComputedMapping() == false);
363
364 mapping.computeMapping();
365 mapping.map(inDataID, outDataID);
366 double value = outData->values()(0);
367 double value1 = outData->values()(1);
368 double value2 = outData->values()(2);
369 BOOST_TEST(mapping.hasComputedMapping() == true);
370 if (dim == 2) {
371 BOOST_TEST(math::equals(value, 19935.374757794027, 0.2));
372 BOOST_TEST(math::equals(value1, 19935.37795225389, 0.2));
373 BOOST_TEST(math::equals(value2, 19935.35164938603, 0.2));
374 } else {
375 BOOST_TEST(value == 829.28063055069435);
376 BOOST_TEST(value1 == 819.35577218983303);
377 BOOST_TEST(value2 == 829.38388713302811);
378 }
379}
380
382{
383 int dimensions = 2;
384 using Eigen::Vector2d;
385
386 // Create mesh to map from
387 mesh::PtrMesh inMesh(new mesh::Mesh("InMesh", dimensions, testing::nextMeshID()));
388 mesh::PtrData inData = inMesh->createData("InData", 1, 0_dataID);
389 int inDataID = inData->getID();
390
391 // vertices will be changed
392 inMesh->createVertex(Vector2d(1.0, 0.0));
393 inMesh->createVertex(Vector2d(3.5, 0.0));
394 inMesh->createVertex(Vector2d(2.5, 0.5));
395
396 inMesh->createVertex(Vector2d(0, 0));
397 inMesh->createVertex(Vector2d(5, 1));
398 inMesh->allocateDataValues();
399 addGlobalIndex(inMesh);
400 inMesh->setGlobalNumberOfVertices(inMesh->nVertices());
401
402 auto &values = inData->values();
403 values << 10.0, 0.0, 0.0, 10.0, 0.0;
404 // Create mesh to map to
405 mesh::PtrMesh outMesh(new mesh::Mesh("OutMesh", dimensions, testing::nextMeshID()));
406 mesh::PtrData outData = outMesh->createData("OutData", 1, 1_dataID);
407 int outDataID = outData->getID();
408
409 outMesh->createVertex(Vector2d(0.0, 0.0));
410 outMesh->createVertex(Vector2d(1.0, 0.0));
411 outMesh->createVertex(Vector2d(1.0, 1.0));
412 outMesh->createVertex(Vector2d(0.0, 1.0));
413
414 outMesh->createVertex(Vector2d(2.0, 0.0));
415 outMesh->createVertex(Vector2d(3.0, 0.0));
416 outMesh->createVertex(Vector2d(3.0, 1.0));
417 outMesh->createVertex(Vector2d(2.0, 1.0));
418
419 outMesh->createVertex(Vector2d(4.0, 0.0));
420 outMesh->createVertex(Vector2d(5.0, 0.0));
421 outMesh->createVertex(Vector2d(5.0, 1.0));
422 outMesh->createVertex(Vector2d(4.0, 1.0));
423
424 outMesh->allocateDataValues();
425 addGlobalIndex(outMesh);
426 outMesh->setGlobalNumberOfVertices(outMesh->nVertices());
427
428 // Setup mapping with mapping coordinates and geometry used
429 mapping.setMeshes(inMesh, outMesh);
430 BOOST_TEST(mapping.hasComputedMapping() == false);
431
432 // Test that we get point-wise exact data values on output vertices 1 and 2
433 // remaining vertices are zero
434 mapping.computeMapping();
435 mapping.map(inDataID, outDataID);
436
437 BOOST_TEST(outData->values().sum() == inData->values().sum());
438 BOOST_TEST(outData->values()(0) == 10);
439 BOOST_TEST(outData->values()(1) == 10);
440 BOOST_TEST(outData->values()(2) == 0);
441 BOOST_TEST(outData->values()(3) == 0);
442
443 // Test that we have a symmetric solution if we have a force acting
444 // in between two output vertices (here 5 and 8), there is actually
445 // no guarantee, but it holds for this setup
446 values << 0.0, 10.0, 0.0, 0.0, 0.0;
447
448 mapping.clear();
449 outData->values().setZero();
450 mapping.computeMapping();
451 mapping.map(inDataID, outDataID);
452 BOOST_TEST(outData->values().sum() == inData->values().sum());
453 BOOST_TEST(outData->values()(5) == outData->values()(8));
454
455 // Test the conservation property if we have everywhere non-zero input data
456 values << 5.0, 10.0, 7.0, 3.0, 4.0;
457
458 mapping.clear();
459 outData->values().setZero();
460 mapping.computeMapping();
461 mapping.map(inDataID, outDataID);
462
463 BOOST_TEST(outData->values().sum() == inData->values().sum());
464 BOOST_TEST(mapping.hasComputedMapping() == true);
465
466 // Test the conservation property if we have everywhere non-zero input data
467 values << 3.0, 4.0, 5.0, 7.0, 9.0;
468
469 mapping.clear();
470 outData->values().setZero();
471 mapping.computeMapping();
472 mapping.map(inDataID, outDataID);
473 BOOST_TEST(outData->values().sum() == inData->values().sum());
474 BOOST_TEST(mapping.hasComputedMapping() == true);
475 BOOST_TEST(outData->values()(5) == 3.2931869752057001);
476}
477
479{
480 int dimensions = 2;
481 int dataDimensions = dimensions;
482 using Eigen::Vector2d;
483
484 // Create mesh to map to
485 mesh::PtrMesh inMesh(new mesh::Mesh("InMesh", dimensions, testing::nextMeshID()));
486 mesh::PtrData inData = inMesh->createData("InData", dataDimensions, 0_dataID);
487 DataID inDataID = inData->getID();
488 mesh::Vertex &vertex = inMesh->createVertex(Vector2d(0, 0));
489 inMesh->createVertex(Vector2d(3.5, 0.5));
490 inMesh->createVertex(Vector2d(2.5, 0.5));
491 // vertex will be changed
492 inMesh->createVertex(Vector2d(0, 0));
493 inMesh->createVertex(Vector2d(5, 1));
494
495 inMesh->allocateDataValues();
496 addGlobalIndex(inMesh);
497
498 auto &values = inData->values();
499 // We select the second component = 2 * first component
500 values << 1.0, 2.0, 2.0, 4.0, 2.0, 4.0, 1.0, 2.0, 3.0, 6.0;
501
502 // Create mesh to map from
503 mesh::PtrMesh outMesh(new mesh::Mesh("OutMesh", dimensions, testing::nextMeshID()));
504 mesh::PtrData outData = outMesh->createData("OutData", dataDimensions, 1_dataID);
505 DataID outDataID = outData->getID();
506
507 outMesh->createVertex(Vector2d(0.0, 0.0));
508 outMesh->createVertex(Vector2d(1.0, 0.0));
509 outMesh->createVertex(Vector2d(1.0, 1.0));
510 outMesh->createVertex(Vector2d(0.0, 1.0));
511
512 outMesh->createVertex(Vector2d(2.0, 0.0));
513 outMesh->createVertex(Vector2d(3.0, 0.0));
514 outMesh->createVertex(Vector2d(3.0, 1.0));
515 outMesh->createVertex(Vector2d(2.0, 1.0));
516
517 outMesh->createVertex(Vector2d(4.0, 0.0));
518 outMesh->createVertex(Vector2d(5.0, 0.0));
519 outMesh->createVertex(Vector2d(5.0, 1.0));
520 outMesh->createVertex(Vector2d(4.0, 1.0));
521
522 outMesh->allocateDataValues();
523 addGlobalIndex(outMesh);
524
525 // Setup mapping with mapping coordinates and geometry used
526 mapping.setMeshes(inMesh, outMesh);
527 BOOST_TEST(mapping.hasComputedMapping() == false);
528
529 // Check that we preserve data component-wise
530 vertex.setCoords(Vector2d(1.0, 0.0));
531 mapping.computeMapping();
532 mapping.map(inDataID, outDataID);
533
534 // component 0
535 double insumc0 = sumComponentWise(inData->values(), 0, dataDimensions);
536 double outsumc0 = sumComponentWise(outData->values(), 0, dataDimensions);
537 BOOST_TEST(insumc0 == outsumc0);
538
539 // component 1
540 double insumc1 = sumComponentWise(inData->values(), 1, dataDimensions);
541 double outsumc1 = sumComponentWise(outData->values(), 1, dataDimensions);
542
543 BOOST_TEST(insumc0 * 2 == insumc1);
544 BOOST_TEST(outsumc0 * 2 == outsumc1);
545 BOOST_TEST(insumc1 == outsumc1);
546
547 BOOST_TEST(mapping.hasComputedMapping() == true);
548
549 // Check for specific sum values for each component
550 values << 1.0, 0.0, 12.0, 0.0, 2.0, 0.0, 1.0, 0.0, 3.0, 0.0;
551
552 mapping.clear();
553 outData->values().setZero();
554 mapping.computeMapping();
555 mapping.map(inDataID, outDataID);
556
557 // component 0
558 outsumc0 = sumComponentWise(outData->values(), 0, dataDimensions);
559 BOOST_TEST(19.0 == outsumc0);
560
561 // we expect no contribution for the zeroth component
562 // component 1
563 outsumc1 = sumComponentWise(outData->values(), 1, dataDimensions);
564 BOOST_TEST(0.0 == outsumc1);
565
566 BOOST_TEST(mapping.hasComputedMapping() == true);
567
568 // Check for specific sum values for each component
569 values << 0.0, 2.0, 0.0, 4.0, 0.0, 8.0, 0.0, 7.0, 0.0, 0.0;
570
571 mapping.clear();
572 outData->values().setZero();
573 mapping.computeMapping();
574 mapping.map(inDataID, outDataID);
575
576 // component 0
577 outsumc0 = sumComponentWise(outData->values(), 0, dataDimensions);
578 BOOST_TEST(0.0 == outsumc0);
579
580 // we expect no contribution for the zeroth component
581 // component 1
582 outsumc1 = sumComponentWise(outData->values(), 1, dataDimensions);
583 BOOST_TEST(21.0 == outsumc1);
584
585 BOOST_TEST(mapping.hasComputedMapping() == true);
586
587 // Check for the exact reproduction of matching vertices
588 values << 10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 27.0;
589
590 mapping.clear();
591 outData->values().setZero();
592 mapping.computeMapping();
593 mapping.map(inDataID, outDataID);
594
595 // component 0
596 outsumc0 = sumComponentWise(outData->values(), 0, dataDimensions);
597 BOOST_TEST(10.0 == outsumc0);
598 BOOST_TEST(outData->values()(2) == 10);
599
600 // component 1
601 outsumc1 = sumComponentWise(outData->values(), 1, dataDimensions);
602 BOOST_TEST(27.0 == outsumc1);
603 BOOST_TEST(outData->values()(21) == 27);
604
605 BOOST_TEST(mapping.hasComputedMapping() == true);
606
607 // Check for the interpolation at some vertex
608 values << 3.0, 6.0, 2.0, 4.0, 12.0, 24.0, 1.0, 2.0, 3.0, 6.0;
609
610 mapping.clear();
611 outData->values().setZero();
612 mapping.computeMapping();
613 mapping.map(inDataID, outDataID);
614
615 BOOST_TEST(outData->values().sum() == inData->values().sum());
616
617 double expectedValue = 3.5933508322619825;
618 // component 0
619 BOOST_TEST(outData->values()(12) == expectedValue);
620
621 // component 1
622 BOOST_TEST(outData->values()(13) == 2 * expectedValue);
623}
624
626{
627 int dimensions = 3;
628 using Eigen::Vector3d;
629
630 // Create mesh to map from
631 mesh::PtrMesh inMesh(new mesh::Mesh("InMesh", dimensions, testing::nextMeshID()));
632 mesh::PtrData inData = inMesh->createData("InData", 1, 0_dataID);
633 int inDataID = inData->getID();
634 inMesh->createVertex(Vector3d(0.0, 0.0, 0.0));
635 inMesh->createVertex(Vector3d(1.0, 0.0, 0.0));
636 inMesh->createVertex(Vector3d(1.0, 1.0, 0.0));
637 inMesh->createVertex(Vector3d(0.0, 1.0, 0.0));
638
639 inMesh->createVertex(Vector3d(0.0, 0.0, 1.0));
640 inMesh->createVertex(Vector3d(1.0, 0.0, 1.0));
641 inMesh->createVertex(Vector3d(1.0, 1.0, 1.0));
642 inMesh->createVertex(Vector3d(0.0, 1.0, 1.0));
643
644 inMesh->createVertex(Vector3d(2.0, 0.0, 0.0));
645 inMesh->createVertex(Vector3d(3.0, 0.0, 0.0));
646 inMesh->createVertex(Vector3d(3.0, 1.0, 0.0));
647 inMesh->createVertex(Vector3d(2.0, 1.0, 0.0));
648
649 inMesh->createVertex(Vector3d(2.0, 0.0, 1.0));
650 inMesh->createVertex(Vector3d(3.0, 0.0, 1.0));
651 inMesh->createVertex(Vector3d(3.0, 1.0, 1.0));
652 inMesh->createVertex(Vector3d(2.0, 1.0, 1.0));
653
654 inMesh->createVertex(Vector3d(4.0, 0.0, 0.0));
655 inMesh->createVertex(Vector3d(5.0, 0.0, 0.0));
656 inMesh->createVertex(Vector3d(5.0, 1.0, 0.0));
657 inMesh->createVertex(Vector3d(4.0, 1.0, 0.0));
658
659 inMesh->createVertex(Vector3d(4.0, 0.0, 1.0));
660 inMesh->createVertex(Vector3d(5.0, 0.0, 1.0));
661 inMesh->createVertex(Vector3d(5.0, 1.0, 1.0));
662 inMesh->createVertex(Vector3d(4.0, 1.0, 1.0));
663
664 inMesh->allocateDataValues();
665 addGlobalIndex(inMesh);
666
667 auto &values = inData->values();
668 // Set the values in the parallel (z) plane 3*values
669 values << 1.0, 2.0, 2.0, 1.0, 3.0, 6.0, 6.0, 3.0, 3.0, 4.0, 4.0, 3.0, 9.0, 12.0, 12.0, 9.0, 5.0, 6.0, 6.0, 5.0, 15.0, 18.0, 18.0, 15.0;
670
671 // Create mesh to map to
672 mesh::PtrMesh outMesh(new mesh::Mesh("OutMesh", dimensions, testing::nextMeshID()));
673 mesh::PtrData outData = outMesh->createData("OutData", 1, 1_dataID);
674 int outDataID = outData->getID();
675 mesh::Vertex &vertex = outMesh->createVertex(Vector3d(0, 0, 0));
676 outMesh->createVertex(Vector3d(3.5, 0.5, 0.5));
677 outMesh->createVertex(Vector3d(2.5, 0.5, 1.0));
678 outMesh->createVertex(Vector3d(0, 0, 0.5));
679 outMesh->createVertex(Vector3d(5, 1, 0.5));
680 outMesh->allocateDataValues();
681 addGlobalIndex(outMesh);
682
683 // Setup mapping with mapping coordinates and geometry used
684 mapping.setMeshes(inMesh, outMesh);
685 BOOST_TEST(mapping.hasComputedMapping() == false);
686
687 vertex.setCoords(Vector3d(0.0, 0.0, 0.0));
688 mapping.computeMapping();
689 mapping.map(inDataID, outDataID);
690 double value = outData->values()(0);
691 double value1 = outData->values()(1);
692 double value2 = outData->values()(2);
693 BOOST_TEST(mapping.hasComputedMapping() == true);
694 BOOST_TEST(value == 1.0);
695 BOOST_TEST(value1 == 9.0);
696 BOOST_TEST(value2 == 10.5);
697
698 vertex.setCoords(Vector3d(0.0, 0.5, 0.5));
699 mapping.clear();
700 outData->values().setZero();
701 mapping.computeMapping();
702 mapping.map(inDataID, outDataID);
703 value = outData->values()(0);
704 BOOST_TEST(mapping.hasComputedMapping() == true);
705 BOOST_TEST(value == 2.0);
706
707 vertex.setCoords(Vector3d(0.0, 1.0, 1.0));
708 mapping.clear();
709 outData->values().setZero();
710 mapping.computeMapping();
711 mapping.map(inDataID, outDataID);
712 value = outData->values()(0);
713 BOOST_TEST(mapping.hasComputedMapping() == true);
714 BOOST_TEST(value == 3.0);
715
716 vertex.setCoords(Vector3d(1.0, 0.0, 0.0));
717 mapping.clear();
718 outData->values().setZero();
719 mapping.computeMapping();
720 mapping.map(inDataID, outDataID);
721 value = outData->values()(0);
722 BOOST_TEST(mapping.hasComputedMapping() == true);
723 BOOST_TEST(value == 2.0);
724
725 vertex.setCoords(Vector3d(1.0, 0.5, 0.5));
726 mapping.clear();
727 outData->values().setZero();
728 mapping.computeMapping();
729 mapping.map(inDataID, outDataID);
730 value = outData->values()(0);
731 BOOST_TEST(mapping.hasComputedMapping() == true);
732 BOOST_TEST(value == 4.0);
733
734 vertex.setCoords(Vector3d(1.0, 1.0, 1.0));
735 mapping.clear();
736 outData->values().setZero();
737 mapping.computeMapping();
738 mapping.map(inDataID, outDataID);
739 value = outData->values()(0);
740 BOOST_TEST(mapping.hasComputedMapping() == true);
741 BOOST_TEST(value == 6.0);
742
743 vertex.setCoords(Vector3d(0.5, 0.0, 0.5));
744 mapping.clear();
745 outData->values().setZero();
746 mapping.computeMapping();
747 mapping.map(inDataID, outDataID);
748 value = outData->values()(0);
749 BOOST_TEST(mapping.hasComputedMapping() == true);
750 BOOST_TEST(value == 3.0);
751
752 vertex.setCoords(Vector3d(0.5, 0.5, 1.0));
753 mapping.clear();
754 outData->values().setZero();
755 mapping.computeMapping();
756 mapping.map(inDataID, outDataID);
757 value = outData->values()(0);
758 BOOST_TEST(mapping.hasComputedMapping() == true);
759 BOOST_TEST(value == 4.5);
760
761 vertex.setCoords(Vector3d(0.5, 1.0, 0.0));
762 mapping.clear();
763 outData->values().setZero();
764 mapping.computeMapping();
765 mapping.map(inDataID, outDataID);
766 value = outData->values()(0);
767 BOOST_TEST(mapping.hasComputedMapping() == true);
768 BOOST_TEST(value == 1.5);
769}
770
771// uses scalar data in 3D
773{
774 const int dimensions = 3;
775 const int dataComponents = 1;
776
777 // Create mesh to map from
778 mesh::PtrMesh inMesh(new mesh::Mesh("InMesh", dimensions, testing::nextMeshID()));
779 mesh::PtrData inData = inMesh->createData("InData", dataComponents, 0_dataID);
780 inMesh->createVertex(Eigen::Vector3d(0.0, 0.0, 0.0));
781 inMesh->createVertex(Eigen::Vector3d(1.0, 0.0, 0.0));
782 inMesh->createVertex(Eigen::Vector3d(1.0, 1.0, 0.0));
783 inMesh->createVertex(Eigen::Vector3d(0.0, 1.0, 0.0));
784
785 inMesh->createVertex(Eigen::Vector3d(0.0, 0.0, 1.0));
786 inMesh->createVertex(Eigen::Vector3d(1.0, 0.0, 1.0));
787 inMesh->createVertex(Eigen::Vector3d(1.0, 1.0, 1.0));
788 inMesh->createVertex(Eigen::Vector3d(0.0, 1.0, 1.0));
789
790 inMesh->createVertex(Eigen::Vector3d(2.0, 0.0, 0.0));
791 inMesh->createVertex(Eigen::Vector3d(3.0, 0.0, 0.0));
792 inMesh->createVertex(Eigen::Vector3d(3.0, 1.0, 0.0));
793 inMesh->createVertex(Eigen::Vector3d(2.0, 1.0, 0.0));
794
795 inMesh->createVertex(Eigen::Vector3d(2.0, 0.0, 1.0));
796 inMesh->createVertex(Eigen::Vector3d(3.0, 0.0, 1.0));
797 inMesh->createVertex(Eigen::Vector3d(3.0, 1.0, 1.0));
798 inMesh->createVertex(Eigen::Vector3d(2.0, 1.0, 1.0));
799
800 inMesh->createVertex(Eigen::Vector3d(4.0, 0.0, 0.0));
801 inMesh->createVertex(Eigen::Vector3d(5.0, 0.0, 0.0));
802 inMesh->createVertex(Eigen::Vector3d(5.0, 1.0, 0.0));
803 inMesh->createVertex(Eigen::Vector3d(4.0, 1.0, 0.0));
804
805 inMesh->createVertex(Eigen::Vector3d(4.0, 0.0, 1.0));
806 inMesh->createVertex(Eigen::Vector3d(5.0, 0.0, 1.0));
807 inMesh->createVertex(Eigen::Vector3d(5.0, 1.0, 1.0));
808 inMesh->createVertex(Eigen::Vector3d(4.0, 1.0, 1.0));
809
810 inMesh->allocateDataValues();
811 addGlobalIndex(inMesh);
812
813 auto &values = inData->values();
814
815 // Set the values in the parallel (z) plane 3*values
816 values << 1.0, 2.0, 2.0, 1.0, 3.0, 6.0, 6.0, 3.0, 3.0, 4.0, 4.0, 3.0, 9.0, 12.0, 12.0, 9.0, 5.0, 6.0, 6.0, 5.0, 15.0, 18.0, 18.0, 15.0;
817
818 // the dummy target mesh
820
821 // Setup mapping with mapping coordinates and geometry used
822 mapping.setMeshes(inMesh, toMesh);
823 BOOST_TEST(mapping.hasComputedMapping() == false);
824 // compute the mapping (affects only the inMesh)
825 mapping.computeMapping();
826 BOOST_TEST(mapping.hasComputedMapping() == true);
827
828 // Now, we can setup the MappingDataCache with the structures
829 // from computeMapping
830 mapping::impl::MappingDataCache cache(dataComponents);
831 mapping.initializeMappingDataCache(cache);
832
833 // computeMapping and the initializeMappingDataCache are only required for changes in the input coords
834 // whereas the cache update is for new data values
835 mapping.updateMappingDataCache(cache, values);
836 // we can also give the cache a time stamp (not strictly necessary)
837 double stamp = 1;
838 cache.setTimeStamp(stamp);
839
840 // Test infrastructure
841 Eigen::MatrixXd coords(dimensions, 1);
842 Eigen::MatrixXd result(dataComponents, 1);
843
844 // Now we can evaluate at any point we want
845 coords.setZero();
846 // Check that we have the right time
847 BOOST_TEST(cache.hasDataAtTimeStamp(stamp));
848 mapping.mapConsistentAt(coords, cache, result);
849 BOOST_TEST(result(0, 0) == 1.0);
850
851 coords.col(0) = Eigen::RowVector3d(3.5, 0.5, 0.5);
852 // Check that we have the right time
853 BOOST_TEST(cache.hasDataAtTimeStamp(stamp));
854 mapping.mapConsistentAt(coords, cache, result);
855 BOOST_TEST(result(0, 0) == 9.0);
856
857 coords.col(0) = Eigen::RowVector3d(2.5, 0.5, 1.0);
858 // Check that we have the right time
859 BOOST_TEST(cache.hasDataAtTimeStamp(stamp));
860 mapping.mapConsistentAt(coords, cache, result);
861 BOOST_TEST(result(0, 0) == 10.5);
862
863 // We can also pass multiple vertices at once
864 coords.resize(dimensions, 3);
865 result.resize(dataComponents, 3);
866
867 coords.col(0) = Eigen::RowVector3d(0.0, 0.5, 0.5);
868 coords.col(1) = Eigen::RowVector3d(0.0, 1.0, 1.0);
869 coords.col(2) = Eigen::RowVector3d(1.0, 0.0, 0.0);
870 // Check that we have the right time
871 BOOST_TEST(cache.hasDataAtTimeStamp(stamp));
872 mapping.mapConsistentAt(coords, cache, result);
873 BOOST_TEST(result(0, 0) == 2.0);
874 BOOST_TEST(result(0, 1) == 3.0);
875 BOOST_TEST(result(0, 2) == 2.0);
876
877 // Now we alter the data (double values)
878 values *= 2;
879 // Mapping remains the same
880 BOOST_TEST(mapping.hasComputedMapping() == true);
881 // Step 1: invalidate cache (happens in the DataContext)
882 cache.resetTimeStamp();
883 BOOST_TEST(!cache.hasDataAtTimeStamp(stamp));
884 // Step 2: update the cache
885 mapping.updateMappingDataCache(cache, values);
886 // Step 3: mark the cache
887 stamp = 2.0;
888 cache.setTimeStamp(stamp);
889 BOOST_TEST(cache.hasDataAtTimeStamp(stamp));
890
891 // Ready for new mappings
892 mapping.mapConsistentAt(coords, cache, result);
893 BOOST_TEST(result(0, 0) == 4.0);
894 BOOST_TEST(result(0, 1) == 6.0);
895 BOOST_TEST(result(0, 2) == 4.0);
896
897 coords.col(0) = Eigen::RowVector3d(0.5, 0.0, 0.5);
898 coords.col(1) = Eigen::RowVector3d(0.5, 0.5, 1.0);
899 coords.col(2) = Eigen::RowVector3d(0.5, 1.0, 0.0);
900 // Check that we have the right time
901 BOOST_TEST(cache.hasDataAtTimeStamp(stamp));
902 mapping.mapConsistentAt(coords, cache, result);
903 BOOST_TEST(result(0, 0) == 6.0);
904 BOOST_TEST(result(0, 1) == 9.0);
905 BOOST_TEST(result(0, 2) == 3.0);
906
907 // If we clear the mapping, the we have to recompute it
908 mapping.clear();
909 // We just clear the mesh index here instead of calling mesh.clear
910 // to not repeat all the vertices above. Recomputing the index is require
911 // when altering the mesh
912 inMesh->index().clear();
913 // We extend the mesh a bit
914 inMesh->createVertex(Eigen::Vector3d(6.0, 0.0, 0.0));
915 inMesh->createVertex(Eigen::Vector3d(7.0, 0.0, 0.0));
916 inMesh->createVertex(Eigen::Vector3d(7.0, 1.0, 0.0));
917 inMesh->createVertex(Eigen::Vector3d(6.0, 1.0, 0.0));
918 inMesh->allocateDataValues();
919 values << 1.0, 2.0, 2.0, 1.0, 3.0, 6.0, 6.0, 3.0, 3.0, 4.0, 4.0, 3.0, 9.0, 12.0, 12.0, 9.0, 5.0, 6.0, 6.0, 5.0, 15.0, 18.0, 18.0, 15.0, 7.0, 8.0, 8.0, 7.0;
920 // Setup mapping with mapping coordinates and geometry used
921 mapping.setMeshes(inMesh, toMesh);
922 BOOST_TEST(mapping.hasComputedMapping() == false);
923 // compute the mapping (affects only the inMesh)
924 mapping.computeMapping();
925 BOOST_TEST(mapping.hasComputedMapping() == true);
926
927 cache.resetTimeStamp();
928 mapping.initializeMappingDataCache(cache);
929 mapping.updateMappingDataCache(cache, values);
930 cache.setTimeStamp(stamp);
931 coords.col(0) = Eigen::RowVector3d(6.5, 1.0, 0.0);
932 mapping.mapConsistentAt(coords, cache, result);
933 BOOST_TEST(result(0, 0) == 7.5);
934 BOOST_TEST(result(0, 1) == 4.5);
935 BOOST_TEST(result(0, 2) == 1.5);
936}
937
938// uses vectorial data in 2D
940{
941 int dimensions = 2;
942 int dataComponents = 2;
943
944 // Create mesh to map from
945 mesh::PtrMesh inMesh(new mesh::Mesh("InMesh", dimensions, testing::nextMeshID()));
946 mesh::PtrData inData = inMesh->createData("InData", dataComponents, 0_dataID);
947 inMesh->createVertex(Eigen::Vector2d(0.0, 0.0));
948 inMesh->createVertex(Eigen::Vector2d(1.0, 0.0));
949 inMesh->createVertex(Eigen::Vector2d(1.0, 1.0));
950 inMesh->createVertex(Eigen::Vector2d(0.0, 1.0));
951
952 inMesh->createVertex(Eigen::Vector2d(2.0, 0.0));
953 inMesh->createVertex(Eigen::Vector2d(3.0, 0.0));
954 inMesh->createVertex(Eigen::Vector2d(3.0, 1.0));
955 inMesh->createVertex(Eigen::Vector2d(2.0, 1.0));
956
957 inMesh->createVertex(Eigen::Vector2d(4.0, 0.0));
958 inMesh->createVertex(Eigen::Vector2d(5.0, 0.0));
959 inMesh->createVertex(Eigen::Vector2d(5.0, 1.0));
960 inMesh->createVertex(Eigen::Vector2d(4.0, 1.0));
961
962 inMesh->allocateDataValues();
963 addGlobalIndex(inMesh);
964
965 auto &values = inData->values();
966
967 // Set the values in the parallel (z) plane 3*values
968 values << 1.0, 2.0, 2.0, 1.0, 3.0, 6.0, 6.0, 3.0, 3.0, 4.0, 4.0, 3.0, 9.0, 12.0, 12.0, 9.0, 5.0, 6.0, 6.0, 5.0, 15.0, 18.0, 18.0, 15.0;
969
970 // the dummy target mesh
972
973 // Setup mapping with mapping coordinates and geometry used
974 mapping.setMeshes(inMesh, toMesh);
975 BOOST_TEST(mapping.hasComputedMapping() == false);
976 // compute the mapping (affects only the inMesh)
977 mapping.computeMapping();
978 BOOST_TEST(mapping.hasComputedMapping() == true);
979
980 // Now, we can setup the MappingDataCache with the structures
981 // from computeMapping
982 mapping::impl::MappingDataCache cache(dataComponents);
983 mapping.initializeMappingDataCache(cache);
984
985 // computeMapping and the initializeMappingDataCache are only required for changes in the input coords
986 // whereas the cache update is for new data values
987 mapping.updateMappingDataCache(cache, values);
988 // we can also give the cache a time stamp (not strictly necessary)
989 double stamp = 1;
990 cache.setTimeStamp(stamp);
991
992 // Test infrastructure
993 Eigen::MatrixXd coords(dimensions, 1);
994 Eigen::MatrixXd result(dataComponents, 1);
995
996 // Now we can evaluate at any point we want
997 coords.setZero();
998 // Check that we have the right time
999 BOOST_TEST(cache.hasDataAtTimeStamp(stamp));
1000 mapping.mapConsistentAt(coords, cache, result);
1001 BOOST_TEST(result(0, 0) == 1.0);
1002 BOOST_TEST(result(1, 0) == 2.0);
1003
1004 // Second last point given
1005 coords.col(0) = Eigen::RowVector2d(5.0, 1.0);
1006 // Check that we have the right time
1007 BOOST_TEST(cache.hasDataAtTimeStamp(stamp));
1008 mapping.mapConsistentAt(coords, cache, result);
1009 BOOST_TEST(result(0, 0) == 15.0);
1010 BOOST_TEST(result(1, 0) == 18.0);
1011
1012 // Between the first and the second point
1013 coords.col(0) = Eigen::RowVector2d(0.5, 0.0);
1014 // Check that we have the right time
1015 BOOST_TEST(cache.hasDataAtTimeStamp(stamp));
1016 mapping.mapConsistentAt(coords, cache, result);
1017 BOOST_TEST(result(0, 0) == 1.71978075, boost::test_tools::tolerance(1e-7));
1018 BOOST_TEST(result(1, 0) == 1.71978075, boost::test_tools::tolerance(1e-7));
1019
1020 coords.col(0) = Eigen::RowVector2d(3.5, 0.5);
1021 // Check that we have the right time
1022 BOOST_TEST(cache.hasDataAtTimeStamp(stamp));
1023 mapping.mapConsistentAt(coords, cache, result);
1024 BOOST_TEST(result(0, 0) == 10.39684625, boost::test_tools::tolerance(1e-7));
1025 BOOST_TEST(result(1, 0) == 10.48101386, boost::test_tools::tolerance(1e-7));
1026
1027 // We can also pass multiple vertices at once
1028 coords.resize(dimensions, 2);
1029 result.resize(dataComponents, 2);
1030
1031 coords.col(0) = Eigen::RowVector2d(4.0, 0.0);
1032 coords.col(1) = Eigen::RowVector2d(5.0, 0.0);
1033 // // Check that we have the right time
1034 BOOST_TEST(cache.hasDataAtTimeStamp(stamp));
1035 mapping.mapConsistentAt(coords, cache, result);
1036 BOOST_TEST(result(0, 0) == 5.0);
1037 BOOST_TEST(result(1, 0) == 6.0);
1038 BOOST_TEST(result(0, 1) == 6.0);
1039 BOOST_TEST(result(1, 1) == 5.0);
1040
1041 // Now we alter the data (double values)
1042 values *= 0.5;
1043 // Mapping remains the same
1044 BOOST_TEST(mapping.hasComputedMapping() == true);
1045 // Step 1: invalidate cache (happens in the DataContext)
1046 cache.resetTimeStamp();
1047 BOOST_TEST(!cache.hasDataAtTimeStamp(stamp));
1048 // Step 2: update the cache
1049 mapping.updateMappingDataCache(cache, values);
1050 // Step 3: mark the cache
1051 stamp = 2.0;
1052 cache.setTimeStamp(stamp);
1053 BOOST_TEST(cache.hasDataAtTimeStamp(stamp));
1054
1055 // Ready for new mappings
1056 mapping.mapConsistentAt(coords, cache, result);
1057 BOOST_TEST(result(0, 0) == 2.5);
1058 BOOST_TEST(result(1, 0) == 3.0);
1059 BOOST_TEST(result(0, 1) == 3.0);
1060 BOOST_TEST(result(1, 1) == 2.5);
1061
1062 // If we clear the mapping, the we have to recompute it
1063 mapping.clear();
1064 // We just clear the mesh index here instead of calling mesh.clear
1065 // to not repeat all the vertices above. Recomputing the index is require
1066 // when altering the mesh
1067 inMesh->index().clear();
1068 // We extend the mesh a bit
1069 inMesh->createVertex(Eigen::Vector2d(6.0, 0.0));
1070 inMesh->createVertex(Eigen::Vector2d(7.0, 0.0));
1071 inMesh->createVertex(Eigen::Vector2d(7.0, 1.0));
1072 inMesh->createVertex(Eigen::Vector2d(6.0, 1.0));
1073 inMesh->allocateDataValues();
1074 values << 1.0, 2.0, 2.0, 1.0, 3.0, 6.0, 6.0, 3.0, 3.0, 4.0, 4.0, 3.0, 9.0, 12.0, 12.0, 9.0, 5.0, 6.0, 6.0, 5.0, 15.0, 18.0, 18.0, 15.0, 7.0, 8.0, 8.0, 7.0, 20.0, 22.0, 22.0, 20.0;
1075 // Setup mapping with mapping coordinates and geometry used
1076 mapping.setMeshes(inMesh, toMesh);
1077 BOOST_TEST(mapping.hasComputedMapping() == false);
1078 // compute the mapping (affects only the inMesh)
1079 mapping.computeMapping();
1080 BOOST_TEST(mapping.hasComputedMapping() == true);
1081
1082 cache.resetTimeStamp();
1083 mapping.initializeMappingDataCache(cache);
1084 mapping.updateMappingDataCache(cache, values);
1085 cache.setTimeStamp(stamp);
1086
1087 mapping.mapConsistentAt(coords, cache, result);
1088 BOOST_TEST(result(0, 0) == 5.0);
1089 BOOST_TEST(result(1, 0) == 6.0);
1090 BOOST_TEST(result(0, 1) == 6.0);
1091 BOOST_TEST(result(1, 1) == 5.0);
1092
1093 coords.col(0) = Eigen::RowVector2d(7.0, 1.0);
1094 coords.col(1) = Eigen::RowVector2d(6.0, 0.0);
1095 mapping.mapConsistentAt(coords, cache, result);
1096 BOOST_TEST(result(0, 0) == 20.0);
1097 BOOST_TEST(result(1, 0) == 22.0);
1098 BOOST_TEST(result(0, 1) == 7.0);
1099 BOOST_TEST(result(1, 1) == 8.0);
1100}
1101
1103{
1104 int dimensions = 3;
1105 int dataDimensions = dimensions;
1106
1107 using Eigen::Vector3d;
1108
1109 // Create mesh to map from
1110 mesh::PtrMesh inMesh(new mesh::Mesh("InMesh", dimensions, testing::nextMeshID()));
1111 mesh::PtrData inData = inMesh->createData("InData", dataDimensions, 0_dataID);
1112 int inDataID = inData->getID();
1113 inMesh->createVertex(Vector3d(0.0, 0.0, 0.0));
1114 inMesh->createVertex(Vector3d(1.0, 0.0, 0.0));
1115 inMesh->createVertex(Vector3d(1.0, 1.0, 0.0));
1116 inMesh->createVertex(Vector3d(0.0, 1.0, 0.0));
1117
1118 inMesh->createVertex(Vector3d(0.0, 0.0, 1.0));
1119 inMesh->createVertex(Vector3d(1.0, 0.0, 1.0));
1120 inMesh->createVertex(Vector3d(1.0, 1.0, 1.0));
1121 inMesh->createVertex(Vector3d(0.0, 1.0, 1.0));
1122
1123 inMesh->createVertex(Vector3d(2.0, 0.0, 0.0));
1124 inMesh->createVertex(Vector3d(3.0, 0.0, 0.0));
1125 inMesh->createVertex(Vector3d(3.0, 1.0, 0.0));
1126 inMesh->createVertex(Vector3d(2.0, 1.0, 0.0));
1127
1128 inMesh->createVertex(Vector3d(2.0, 0.0, 1.0));
1129 inMesh->createVertex(Vector3d(3.0, 0.0, 1.0));
1130 inMesh->createVertex(Vector3d(3.0, 1.0, 1.0));
1131 inMesh->createVertex(Vector3d(2.0, 1.0, 1.0));
1132
1133 inMesh->createVertex(Vector3d(4.0, 0.0, 0.0));
1134 inMesh->createVertex(Vector3d(5.0, 0.0, 0.0));
1135 inMesh->createVertex(Vector3d(5.0, 1.0, 0.0));
1136 inMesh->createVertex(Vector3d(4.0, 1.0, 0.0));
1137
1138 inMesh->createVertex(Vector3d(4.0, 0.0, 1.0));
1139 inMesh->createVertex(Vector3d(5.0, 0.0, 1.0));
1140 inMesh->createVertex(Vector3d(5.0, 1.0, 1.0));
1141 inMesh->createVertex(Vector3d(4.0, 1.0, 1.0));
1142
1143 inMesh->allocateDataValues();
1144 addGlobalIndex(inMesh);
1145
1146 // Create mesh to map to
1147 mesh::PtrMesh outMesh(new mesh::Mesh("OutMesh", dimensions, testing::nextMeshID()));
1148 mesh::PtrData outData = outMesh->createData("OutData", dataDimensions, 1_dataID);
1149 int outDataID = outData->getID();
1150 outMesh->createVertex(Vector3d(0, 0, 0));
1151 outMesh->createVertex(Vector3d(3.5, 0.5, 0.5));
1152 outMesh->createVertex(Vector3d(2.5, 0.5, 1.0));
1153 outMesh->createVertex(Vector3d(0, 0, 0.5));
1154 outMesh->createVertex(Vector3d(5, 1, 0.5));
1155 outMesh->allocateDataValues();
1156 addGlobalIndex(outMesh);
1157
1158 // Setup mapping with mapping coordinates and geometry used
1159 mapping.setMeshes(inMesh, outMesh);
1160 BOOST_TEST(mapping.hasComputedMapping() == false);
1161
1162 for (unsigned int i = 0; i < inData->values().size() / dataDimensions; ++i) {
1163 inData->values()(i * dataDimensions) = 7;
1164 inData->values()(i * dataDimensions + 1) = 38;
1165 inData->values()(i * dataDimensions + 2) = 19;
1166 }
1167
1168 // Check for the independent interpolation of each component when applying a constant field
1169 mapping.computeMapping();
1170 mapping.map(inDataID, outDataID);
1171 BOOST_TEST(mapping.hasComputedMapping() == true);
1172 BOOST_TEST(outData->values()(0) == 7.0);
1173 BOOST_TEST(outData->values()(1) == 38.0);
1174 BOOST_TEST(outData->values()(2) == 19.0);
1175 BOOST_TEST(outData->values()(9) == 7.0);
1176 BOOST_TEST(outData->values()(10) == 38.0);
1177 BOOST_TEST(outData->values()(11) == 19.0);
1178
1179 // Check for the consistency between individual components
1180 for (unsigned int i = 0; i < inData->values().size() / dataDimensions; ++i) {
1181 inData->values()(i * dataDimensions) = std::pow(i * dataDimensions, 2);
1182 inData->values()(i * dataDimensions + 1) = 2 * std::pow(i * dataDimensions, 2);
1183 inData->values()(i * dataDimensions + 2) = 3 * std::pow(i * dataDimensions, 2);
1184 }
1185
1186 mapping.clear();
1187 outData->values().setZero();
1188 mapping.computeMapping();
1189 mapping.map(inDataID, outDataID);
1190 BOOST_TEST(mapping.hasComputedMapping() == true);
1191 BOOST_TEST(outData->values()(12) == 3673.7308684337013);
1192 BOOST_TEST(outData->values()(13) == 2 * outData->values()(12));
1193 BOOST_TEST(outData->values()(14) == 3 * outData->values()(12));
1194
1195 // The remaining parts should already be covered by the other 3D/2D tests
1196}
1197
1199{
1200 int dimensions = 3;
1201 using Eigen::Vector3d;
1202
1203 // Create mesh to map from
1204 mesh::PtrMesh inMesh(new mesh::Mesh("InMesh", dimensions, testing::nextMeshID()));
1205 mesh::PtrData inData = inMesh->createData("InData", 1, 0_dataID);
1206 const DataID inDataID = inData->getID();
1207 inMesh->createVertex(Vector3d(0, 0, 0));
1208 inMesh->createVertex(Vector3d(3.5, 0.5, 0.5));
1209 inMesh->createVertex(Vector3d(2.5, 0.5, 1.0));
1210 inMesh->createVertex(Vector3d(1, 1, 1));
1211 inMesh->createVertex(Vector3d(5, 1, 0.5));
1212 inMesh->allocateDataValues();
1213 addGlobalIndex(inMesh);
1214
1215 // Create mesh to map from
1216 mesh::PtrMesh outMesh(new mesh::Mesh("OutMesh", dimensions, testing::nextMeshID()));
1217 mesh::PtrData outData = outMesh->createData("OutData", 1, 1_dataID);
1218 const DataID outDataID = outData->getID();
1219 outMesh->createVertex(Vector3d(0.0, 0.0, 0.0));
1220 outMesh->createVertex(Vector3d(1.0, 0.0, 0.0));
1221 outMesh->createVertex(Vector3d(1.0, 1.0, 0.0));
1222 outMesh->createVertex(Vector3d(0.0, 1.0, 0.0));
1223
1224 outMesh->createVertex(Vector3d(0.0, 0.0, 1.0));
1225 outMesh->createVertex(Vector3d(1.0, 0.0, 1.0));
1226 outMesh->createVertex(Vector3d(1.0, 1.0, 1.0));
1227 outMesh->createVertex(Vector3d(0.0, 1.0, 1.0));
1228
1229 outMesh->createVertex(Vector3d(2.0, 0.0, 0.0));
1230 outMesh->createVertex(Vector3d(3.0, 0.0, 0.0));
1231 outMesh->createVertex(Vector3d(3.0, 1.0, 0.0));
1232 outMesh->createVertex(Vector3d(2.0, 1.0, 0.0));
1233
1234 outMesh->createVertex(Vector3d(2.0, 0.0, 1.0));
1235 outMesh->createVertex(Vector3d(3.0, 0.0, 1.0));
1236 outMesh->createVertex(Vector3d(3.0, 1.0, 1.0));
1237 outMesh->createVertex(Vector3d(2.0, 1.0, 1.0));
1238
1239 outMesh->createVertex(Vector3d(4.0, 0.0, 0.0));
1240 outMesh->createVertex(Vector3d(5.0, 0.0, 0.0));
1241 outMesh->createVertex(Vector3d(5.0, 1.0, 0.0));
1242 outMesh->createVertex(Vector3d(4.0, 1.0, 0.0));
1243
1244 outMesh->createVertex(Vector3d(4.0, 0.0, 1.0));
1245 outMesh->createVertex(Vector3d(5.0, 0.0, 1.0));
1246 outMesh->createVertex(Vector3d(5.0, 1.0, 1.0));
1247 outMesh->createVertex(Vector3d(4.0, 1.0, 1.0));
1248
1249 outMesh->allocateDataValues();
1250 addGlobalIndex(outMesh);
1251
1252 // Setup mapping with mapping coordinates and geometry used
1253 mapping.setMeshes(inMesh, outMesh);
1254 BOOST_TEST(mapping.hasComputedMapping() == false);
1255
1256 auto &values = inData->values();
1257 // Some arbitrary input values in order to check conservation
1258 values << 1.0, 2.0, 2.0, 1.0, 3.0;
1259
1260 mapping.computeMapping();
1261 mapping.map(inDataID, outDataID);
1262 BOOST_TEST(mapping.hasComputedMapping() == true);
1263 BOOST_TEST(outData->values().sum() == inData->values().sum());
1264
1265 // Check for the exact reproduction of individual values
1266 values << 12.0, 5.0, 7.0, 8.0, 9.0;
1267
1268 mapping.clear();
1269 outData->values().setZero();
1270 mapping.computeMapping();
1271 mapping.map(inDataID, outDataID);
1272 BOOST_TEST(mapping.hasComputedMapping() == true);
1273 const double expectedSum = 41;
1274 BOOST_TEST(outData->values().sum() == expectedSum);
1275 BOOST_TEST(outData->values()(6) == 8);
1276 BOOST_TEST(outData->values()(0) == 12);
1277
1278 // Check for consistency (applying a heavy load to the front layer z = 1)
1279 values << 0.0, 50.0, 107.0, 108.0, 48.0;
1280
1281 mapping.clear();
1282 outData->values().setZero();
1283 mapping.computeMapping();
1284 mapping.map(inDataID, outDataID);
1285 BOOST_TEST(mapping.hasComputedMapping() == true);
1286 BOOST_TEST(outData->values().sum() == inData->values().sum());
1287 BOOST_TEST(outData->values()(0) == 0.0);
1288 BOOST_TEST(outData->values()(6) > outData->values()(1));
1289 BOOST_TEST(outData->values()(13) > outData->values()(9));
1290
1291 // Check for symmetry when applying a central load (not guaranteed ?)
1292 values << 0.0, 100.0, 0.0, 0.0, 0.0;
1293
1294 mapping.clear();
1295 outData->values().setZero();
1296 mapping.computeMapping();
1297 mapping.map(inDataID, outDataID);
1298 BOOST_TEST(mapping.hasComputedMapping() == true);
1299 BOOST_TEST(outData->values().sum() == inData->values().sum());
1300 BOOST_TEST(outData->values()(9) == outData->values()(13));
1301 BOOST_TEST(outData->values()(9) == outData->values()(10));
1302 BOOST_TEST(outData->values()(16) == outData->values()(19));
1303 // TODO: There is no symmetry between the (3, x, x) and (4, x , x) layer
1304 // as the domain length is 5 and we have a partition center at x = 2.9 and x = 3.75
1305 // BOOST_TEST(outData->values()(16) == outData->values()(9));
1306 BOOST_TEST(outData->values()(20) == outData->values()(23));
1307 BOOST_TEST(outData->values()(16) == outData->values()(20));
1308 BOOST_TEST(outData->values()(9) == 15.470584170385226);
1309}
1310
1312{
1313 const int dimensions = 3;
1314 const int dataComponents = 1;
1315
1316 // the dummy from mesh
1318
1319 // Create mesh to map from
1320 mesh::PtrMesh outMesh(new mesh::Mesh("OutMesh", dimensions, testing::nextMeshID()));
1321 mesh::PtrData outData = outMesh->createData("OutData", dataComponents, 1_dataID);
1322
1323 outMesh->createVertex(Eigen::Vector3d(0.0, 0.0, 0.0));
1324 outMesh->createVertex(Eigen::Vector3d(1.0, 0.0, 0.0));
1325 outMesh->createVertex(Eigen::Vector3d(1.0, 1.0, 0.0));
1326 outMesh->createVertex(Eigen::Vector3d(0.0, 1.0, 0.0));
1327
1328 outMesh->createVertex(Eigen::Vector3d(0.0, 0.0, 1.0));
1329 outMesh->createVertex(Eigen::Vector3d(1.0, 0.0, 1.0));
1330 outMesh->createVertex(Eigen::Vector3d(1.0, 1.0, 1.0));
1331 outMesh->createVertex(Eigen::Vector3d(0.0, 1.0, 1.0));
1332
1333 outMesh->createVertex(Eigen::Vector3d(2.0, 0.0, 0.0));
1334 outMesh->createVertex(Eigen::Vector3d(3.0, 0.0, 0.0));
1335 outMesh->createVertex(Eigen::Vector3d(3.0, 1.0, 0.0));
1336 outMesh->createVertex(Eigen::Vector3d(2.0, 1.0, 0.0));
1337
1338 outMesh->createVertex(Eigen::Vector3d(2.0, 0.0, 1.0));
1339 outMesh->createVertex(Eigen::Vector3d(3.0, 0.0, 1.0));
1340 outMesh->createVertex(Eigen::Vector3d(3.0, 1.0, 1.0));
1341 outMesh->createVertex(Eigen::Vector3d(2.0, 1.0, 1.0));
1342
1343 outMesh->createVertex(Eigen::Vector3d(4.0, 0.0, 0.0));
1344 outMesh->createVertex(Eigen::Vector3d(5.0, 0.0, 0.0));
1345 outMesh->createVertex(Eigen::Vector3d(5.0, 1.0, 0.0));
1346 outMesh->createVertex(Eigen::Vector3d(4.0, 1.0, 0.0));
1347
1348 outMesh->createVertex(Eigen::Vector3d(4.0, 0.0, 1.0));
1349 outMesh->createVertex(Eigen::Vector3d(5.0, 0.0, 1.0));
1350 outMesh->createVertex(Eigen::Vector3d(5.0, 1.0, 1.0));
1351 outMesh->createVertex(Eigen::Vector3d(4.0, 1.0, 1.0));
1352
1353 outMesh->allocateDataValues();
1354 addGlobalIndex(outMesh);
1355
1356 // Setup mapping with mapping coordinates and geometry used
1357 mapping.setMeshes(inMesh, outMesh);
1358 BOOST_TEST(mapping.hasComputedMapping() == false);
1359
1360 mapping.computeMapping();
1361 BOOST_TEST(mapping.hasComputedMapping() == true);
1362
1363 // Now, we can setup the MappingDataCache with the structures
1364 // from computeMapping before starting the mappings
1365 mapping::impl::MappingDataCache cache(dataComponents);
1366 mapping.initializeMappingDataCache(cache);
1367
1368 // Test infrastructure/ the user input
1369 Eigen::MatrixXd coords(dimensions, 1);
1370 Eigen::MatrixXd inData(dataComponents, 1);
1371 Eigen::Map<Eigen::MatrixXd> outValues(outData->values().data(), dataComponents, outMesh->vertices().size());
1372
1373 // before writing first, we have to reset the cache to contain zeros
1374 cache.resetData();
1375 outValues.setZero();
1376
1377 coords.col(0) = Eigen::RowVector3d(5.0, 0.0, 1.0);
1378 inData(0, 0) = 4.3;
1379 // note that the outvalues are only filled in the completeJustInTimeMapping
1380 mapping.mapConservativeAt(coords, inData, cache, outValues);
1381
1382 // Once all values are written, we complete the mapping (expensive part)
1383 mapping.completeJustInTimeMapping(cache, outValues);
1384 BOOST_TEST(outValues.sum() == inData.sum());
1385 Eigen::VectorXd expectedValues(24);
1386 expectedValues.setZero();
1387 expectedValues(21) = 4.3;
1388 BOOST_TEST(outData->values() == expectedValues, boost::test_tools::per_element());
1389
1390 // clear data again for the next go
1391 cache.resetData();
1392 outValues.setZero();
1393
1394 // if we call the function twice for the same coordinate, we get twice the contribution
1395 mapping.mapConservativeAt(coords, inData, cache, outValues);
1396 mapping.mapConservativeAt(coords, inData, cache, outValues);
1397 mapping.completeJustInTimeMapping(cache, outValues);
1398 BOOST_TEST(outValues.sum() == 2 * inData.sum());
1399 BOOST_TEST(outData->values() == 2 * expectedValues, boost::test_tools::per_element());
1400
1401 // clear data again for the next go
1402 cache.resetData();
1403 outValues.setZero();
1404
1405 double expectedSum = 0;
1406 mapping.mapConservativeAt(coords, inData, cache, outValues);
1407 expectedSum += inData.sum();
1408
1409 // We can also change the shape of the user input
1410 coords.resize(dimensions, 3);
1411 inData.resize(dataComponents, 3);
1412 coords.col(0) = Eigen::RowVector3d(3.5, 0.5, 0.5);
1413 coords.col(1) = Eigen::RowVector3d(4.5, 1.0, 1.0);
1414 coords.col(2) = Eigen::RowVector3d(0.1, 0.0, 1.0);
1415 inData(0, 0) = 4.3;
1416 inData(0, 1) = 17.3;
1417 inData(0, 2) = 5.8;
1418 mapping.mapConservativeAt(coords, inData, cache, outValues);
1419 expectedSum += inData.sum();
1420
1421 mapping.completeJustInTimeMapping(cache, outValues);
1422 BOOST_TEST(outValues.sum() == expectedSum);
1423 BOOST_TEST(outValues(0, 6) == 0.063700286667, boost::test_tools::tolerance(1e-7));
1424 BOOST_TEST(outValues(0, 23) == 9.2744883594, boost::test_tools::tolerance(1e-7));
1425
1426 // next go
1427 cache.resetData();
1428 outValues.setZero();
1429 expectedSum = 0;
1430
1431 // We can use different shapes for different calls
1432 coords.col(0) = Eigen::RowVector3d(0, 0, 0);
1433 coords.col(1) = Eigen::RowVector3d(3.5, 0.5, 0.5);
1434 coords.col(2) = Eigen::RowVector3d(2.5, 0.5, 1.0);
1435 inData(0, 0) = 0;
1436 inData(0, 1) = 50;
1437 inData(0, 2) = 107;
1438 mapping.mapConservativeAt(coords, inData, cache, outValues);
1439 expectedSum += inData.sum();
1440
1441 coords.resize(dimensions, 2);
1442 inData.resize(dataComponents, 2);
1443 coords.col(0) = Eigen::RowVector3d(1, 1, 1);
1444 coords.col(1) = Eigen::RowVector3d(5, 1, 0.5);
1445 inData(0, 0) = 108;
1446 inData(0, 1) = 48;
1447 mapping.mapConservativeAt(coords, inData, cache, outValues);
1448 expectedSum += inData.sum();
1449
1450 mapping.completeJustInTimeMapping(cache, outValues);
1451 BOOST_TEST(outValues.sum() == expectedSum);
1452
1453 BOOST_TEST(mapping.hasComputedMapping() == true);
1454 BOOST_TEST(outData->values()(0) == 0.0);
1455 BOOST_TEST(outData->values()(6) > outData->values()(1));
1456 BOOST_TEST(outData->values()(13) > outData->values()(9));
1457
1458 // Now we check for re-computing the mapping after changing the mesh
1459 mapping.clear();
1460 outMesh->index().clear();
1461 outMesh->createVertex(Eigen::Vector3d(6, 0, 0));
1462 outMesh->allocateDataValues();
1463
1464 BOOST_TEST(mapping.hasComputedMapping() == false);
1465 mapping.computeMapping();
1466 BOOST_TEST(mapping.hasComputedMapping() == true);
1467
1468 mapping.initializeMappingDataCache(cache);
1469
1470 Eigen::Map<Eigen::MatrixXd> outValues2(outData->values().data(), dataComponents, outMesh->vertices().size());
1471
1472 // before writing first, we have to reset the cache to contain zeros
1473 cache.resetData();
1474 outValues2.setZero();
1475 expectedSum = 0;
1476
1477 coords.resize(dimensions, 1);
1478 inData.resize(dataComponents, 1);
1479 coords.col(0) = Eigen::RowVector3d(0.5, 0.5, 0.5);
1480 inData(0, 0) = 4.3;
1481 mapping.mapConservativeAt(coords, inData, cache, outValues2);
1482 expectedSum += inData.sum();
1483 coords.col(0) = Eigen::RowVector3d(6.0, 0, 0);
1484 inData(0, 0) = 42;
1485 mapping.mapConservativeAt(coords, inData, cache, outValues2);
1486 expectedSum += inData.sum();
1487
1488 mapping.completeJustInTimeMapping(cache, outValues2);
1489 BOOST_TEST(outValues2.sum() == expectedSum);
1490 BOOST_TEST(outValues2(0, 24) == 42, boost::test_tools::tolerance(1e-12));
1491 BOOST_TEST(outValues2(0, 0) == 0.505106848, boost::test_tools::tolerance(1e-7));
1492}
1493
1495{
1496 const int dimensions = 2;
1497 const int dataComponents = 2;
1498
1499 // the dummy from mesh
1501
1502 // Create mesh to map from
1503 mesh::PtrMesh outMesh(new mesh::Mesh("OutMesh", dimensions, testing::nextMeshID()));
1504 mesh::PtrData outData = outMesh->createData("OutData", dataComponents, 1_dataID);
1505
1506 outMesh->createVertex(Eigen::Vector2d(0.0, 0.0));
1507 outMesh->createVertex(Eigen::Vector2d(1.0, 0.0));
1508 outMesh->createVertex(Eigen::Vector2d(1.0, 1.0));
1509 outMesh->createVertex(Eigen::Vector2d(0.0, 1.0));
1510
1511 outMesh->createVertex(Eigen::Vector2d(2.0, 0.0));
1512 outMesh->createVertex(Eigen::Vector2d(3.0, 0.0));
1513 outMesh->createVertex(Eigen::Vector2d(3.0, 1.0));
1514 outMesh->createVertex(Eigen::Vector2d(2.0, 1.0));
1515
1516 outMesh->createVertex(Eigen::Vector2d(4.0, 0.0));
1517 outMesh->createVertex(Eigen::Vector2d(5.0, 0.0));
1518 outMesh->createVertex(Eigen::Vector2d(5.0, 1.0));
1519 outMesh->createVertex(Eigen::Vector2d(4.0, 1.0));
1520
1521 outMesh->allocateDataValues();
1522 addGlobalIndex(outMesh);
1523
1524 // Setup mapping with mapping coordinates and geometry used
1525 mapping.setMeshes(inMesh, outMesh);
1526 BOOST_TEST(mapping.hasComputedMapping() == false);
1527
1528 mapping.computeMapping();
1529 BOOST_TEST(mapping.hasComputedMapping() == true);
1530
1531 // Now, we can setup the MappingDataCache with the structures
1532 // from computeMapping before starting the mappings
1533 mapping::impl::MappingDataCache cache(dataComponents);
1534 mapping.initializeMappingDataCache(cache);
1535
1536 // Test infrastructure/ the user input
1537 Eigen::MatrixXd coords(dimensions, 1);
1538 Eigen::MatrixXd inData(dataComponents, 1);
1539 Eigen::Map<Eigen::MatrixXd> outValues(outData->values().data(), dataComponents, outMesh->vertices().size());
1540
1541 // before writing first, we have to reset the cache to contain zeros
1542 cache.resetData();
1543 outValues.setZero();
1544
1545 coords.col(0) = Eigen::RowVector2d(5.0, 0.0);
1546 inData.col(0) = Eigen::RowVector2d(7.3, 14.6);
1547
1548 // note that the outvalues are only filled in the completeJustInTimeMapping
1549 mapping.mapConservativeAt(coords, inData, cache, outValues);
1550
1551 // Once all values are written, we complete the mapping (expensive part)
1552 mapping.completeJustInTimeMapping(cache, outValues);
1553 BOOST_TEST(outValues.sum() == inData.sum());
1554 Eigen::MatrixXd expectedValues(dataComponents, 12);
1555 expectedValues.setZero();
1556 expectedValues.col(9) = Eigen::RowVector2d(7.3, 14.6);
1557 BOOST_TEST(outValues.row(0) == expectedValues.row(0), boost::test_tools::per_element());
1558 BOOST_TEST(outValues.row(1) == expectedValues.row(1), boost::test_tools::per_element());
1559 BOOST_TEST(outValues.row(0) == 0.5 * outValues.row(1), boost::test_tools::per_element());
1560
1561 // clear data again for the next go
1562 cache.resetData();
1563 outValues.setZero();
1564
1565 // // if we call the function twice for the same coordinate, we get twice the contribution
1566 mapping.mapConservativeAt(coords, inData, cache, outValues);
1567 mapping.mapConservativeAt(coords, inData, cache, outValues);
1568 mapping.completeJustInTimeMapping(cache, outValues);
1569 BOOST_TEST(outValues.row(0) == 2 * expectedValues.row(0), boost::test_tools::per_element());
1570 BOOST_TEST(outValues.row(1) == 2 * expectedValues.row(1), boost::test_tools::per_element());
1571 BOOST_TEST(outValues.row(0) == 0.5 * outValues.row(1), boost::test_tools::per_element());
1572
1573 // // clear data again for the next go
1574 cache.resetData();
1575 outValues.setZero();
1576
1577 Eigen::Vector2d expectedSum;
1578 expectedSum.setZero();
1579 mapping.mapConservativeAt(coords, inData, cache, outValues);
1580 expectedSum += inData.rowwise().sum();
1581
1582 // We can also change the shape of the user input
1583 coords.resize(dimensions, 3);
1584 inData.resize(dataComponents, 3);
1585 coords.col(0) = Eigen::RowVector2d(3.5, 0.5);
1586 coords.col(1) = Eigen::RowVector2d(4.5, 1.0);
1587 coords.col(2) = Eigen::RowVector2d(0.1, 0.0);
1588
1589 inData.col(0) = Eigen::RowVector2d(4.3, 8.6);
1590 inData.col(1) = Eigen::RowVector2d(17.3, 34.6);
1591 inData.col(2) = Eigen::RowVector2d(5.8, 11.6);
1592
1593 mapping.mapConservativeAt(coords, inData, cache, outValues);
1594 expectedSum += inData.rowwise().sum();
1595
1596 mapping.completeJustInTimeMapping(cache, outValues);
1597 // We don't reach full conservative'ness with the RBF config
1598 BOOST_TEST(outValues.rowwise().sum()(0) == expectedSum(0), boost::test_tools::tolerance(0.6));
1599 BOOST_TEST(outValues.rowwise().sum()(1) == expectedSum(1), boost::test_tools::tolerance(0.6));
1600 BOOST_TEST(outValues.row(0) == 0.5 * outValues.row(1), boost::test_tools::per_element());
1601 BOOST_TEST(outValues(0, 10) == 8.76997588, boost::test_tools::tolerance(1e-7));
1602
1603 // Now we check for re-computing the mapping after changing the mesh
1604 mapping.clear();
1605 outMesh->index().clear();
1606 outMesh->createVertex(Eigen::Vector2d(6.0, 0.0));
1607 outMesh->allocateDataValues();
1608
1609 BOOST_TEST(mapping.hasComputedMapping() == false);
1610 mapping.computeMapping();
1611 BOOST_TEST(mapping.hasComputedMapping() == true);
1612
1613 mapping.initializeMappingDataCache(cache);
1614
1615 Eigen::Map<Eigen::MatrixXd> outValues2(outData->values().data(), dataComponents, outMesh->vertices().size());
1616
1617 // before writing first, we have to reset the cache to contain zeros
1618 cache.resetData();
1619 outValues2.setZero();
1620 expectedSum.setZero();
1621
1622 coords.resize(dimensions, 1);
1623 inData.resize(dataComponents, 1);
1624 coords.col(0) = Eigen::RowVector2d(0.5, 0.5);
1625 inData.col(0) = Eigen::RowVector2d(4.3, 43);
1626 mapping.mapConservativeAt(coords, inData, cache, outValues2);
1627 expectedSum += inData.rowwise().sum();
1628 coords.col(0) = Eigen::RowVector2d(6.0, 0);
1629 inData.col(0) = Eigen::RowVector2d(5.1, 51);
1630 mapping.mapConservativeAt(coords, inData, cache, outValues2);
1631 expectedSum += inData.rowwise().sum();
1632
1633 mapping.completeJustInTimeMapping(cache, outValues2);
1634 BOOST_TEST(outValues2.rowwise().sum()(0) == expectedSum(0), boost::test_tools::tolerance(0.6));
1635 BOOST_TEST(outValues2.rowwise().sum()(1) == expectedSum(1), boost::test_tools::tolerance(0.6));
1636 BOOST_TEST(outValues2.col(12) == Eigen::RowVector2d(5.1, 51), boost::test_tools::per_element());
1637 BOOST_TEST(outValues2(0, 0) == 1.13162327, boost::test_tools::tolerance(1e-7));
1638}
1639
1641{
1642 const int dimensions = 3;
1643 const int dataDimension = dimensions;
1644 using Eigen::Vector3d;
1645
1646 // Create mesh to map from
1647 mesh::PtrMesh inMesh(new mesh::Mesh("InMesh", dimensions, testing::nextMeshID()));
1648 mesh::PtrData inData = inMesh->createData("InData", dataDimension, 0_dataID);
1649 const DataID inDataID = inData->getID();
1650 inMesh->createVertex(Vector3d(0, 0, 0));
1651 inMesh->createVertex(Vector3d(3.5, 0.5, 0.5));
1652 inMesh->createVertex(Vector3d(2.5, 0.5, 1.0));
1653 inMesh->createVertex(Vector3d(1, 1, 1));
1654 inMesh->createVertex(Vector3d(5, 1, 0.5));
1655 inMesh->allocateDataValues();
1656 addGlobalIndex(inMesh);
1657
1658 // Create mesh to map from
1659 mesh::PtrMesh outMesh(new mesh::Mesh("OutMesh", dimensions, testing::nextMeshID()));
1660 mesh::PtrData outData = outMesh->createData("OutData", dataDimension, 1_dataID);
1661 const DataID outDataID = outData->getID();
1662 outMesh->createVertex(Vector3d(0.0, 0.0, 0.0));
1663 outMesh->createVertex(Vector3d(1.0, 0.0, 0.0));
1664 outMesh->createVertex(Vector3d(1.0, 1.0, 0.0));
1665 outMesh->createVertex(Vector3d(0.0, 1.0, 0.0));
1666
1667 outMesh->createVertex(Vector3d(0.0, 0.0, 1.0));
1668 outMesh->createVertex(Vector3d(1.0, 0.0, 1.0));
1669 outMesh->createVertex(Vector3d(1.0, 1.0, 1.0));
1670 outMesh->createVertex(Vector3d(0.0, 1.0, 1.0));
1671
1672 outMesh->createVertex(Vector3d(2.0, 0.0, 0.0));
1673 outMesh->createVertex(Vector3d(3.0, 0.0, 0.0));
1674 outMesh->createVertex(Vector3d(3.0, 1.0, 0.0));
1675 outMesh->createVertex(Vector3d(2.0, 1.0, 0.0));
1676
1677 outMesh->createVertex(Vector3d(2.0, 0.0, 1.0));
1678 outMesh->createVertex(Vector3d(3.0, 0.0, 1.0));
1679 outMesh->createVertex(Vector3d(3.0, 1.0, 1.0));
1680 outMesh->createVertex(Vector3d(2.0, 1.0, 1.0));
1681
1682 outMesh->createVertex(Vector3d(4.0, 0.0, 0.0));
1683 outMesh->createVertex(Vector3d(5.0, 0.0, 0.0));
1684 outMesh->createVertex(Vector3d(5.0, 1.0, 0.0));
1685 outMesh->createVertex(Vector3d(4.0, 1.0, 0.0));
1686
1687 outMesh->createVertex(Vector3d(4.0, 0.0, 1.0));
1688 outMesh->createVertex(Vector3d(5.0, 0.0, 1.0));
1689 outMesh->createVertex(Vector3d(5.0, 1.0, 1.0));
1690 outMesh->createVertex(Vector3d(4.0, 1.0, 1.0));
1691
1692 outMesh->allocateDataValues();
1693 addGlobalIndex(outMesh);
1694
1695 // Setup mapping with mapping coordinates and geometry used
1696 mapping.setMeshes(inMesh, outMesh);
1697 BOOST_TEST(mapping.hasComputedMapping() == false);
1698
1699 // Check for the correct sum in the first component
1700 for (unsigned int i = 0; i < inData->values().size() / dataDimension; ++i) {
1701 inData->values()(i * dataDimension) = 7;
1702 inData->values()(i * dataDimension + 1) = 0;
1703 inData->values()(i * dataDimension + 2) = 0;
1704 }
1705
1706 mapping.computeMapping();
1707 mapping.map(inDataID, outDataID);
1708 BOOST_TEST(mapping.hasComputedMapping() == true);
1709 BOOST_TEST(outData->values().sum() == inData->values().sum());
1710 BOOST_TEST(outData->values().sum() == 35);
1711 for (unsigned int i = 0; i < outData->values().size() / dataDimension; ++i) {
1712 BOOST_TEST(outData->values()(i * dataDimension + 1) == 0);
1713 BOOST_TEST(outData->values()(i * dataDimension + 2) == 0);
1714 }
1715
1716 // Check for the correct sum in the second component
1717 for (unsigned int i = 0; i < inData->values().size() / dataDimension; ++i) {
1718 inData->values()(i * dataDimension) = 0;
1719 inData->values()(i * dataDimension + 1) = 27;
1720 inData->values()(i * dataDimension + 2) = 0;
1721 }
1722 mapping.clear();
1723 outData->values().setZero();
1724 mapping.computeMapping();
1725 mapping.map(inDataID, outDataID);
1726 BOOST_TEST(mapping.hasComputedMapping() == true);
1727 BOOST_TEST(outData->values().sum() == inData->values().sum());
1728 BOOST_TEST(outData->values().sum() == 135);
1729
1730 for (unsigned int i = 0; i < outData->values().size() / dataDimension; ++i) {
1731 BOOST_TEST(outData->values()(i * dataDimension) == 0);
1732 BOOST_TEST(outData->values()(i * dataDimension + 2) == 0);
1733 }
1734
1735 // Check for the correct sum in the third component
1736 for (unsigned int i = 0; i < inData->values().size() / dataDimension; ++i) {
1737 inData->values()(i * dataDimension) = 0;
1738 inData->values()(i * dataDimension + 1) = 0;
1739 inData->values()(i * dataDimension + 2) = 3;
1740 }
1741 mapping.clear();
1742 outData->values().setZero();
1743 mapping.computeMapping();
1744 mapping.map(inDataID, outDataID);
1745 BOOST_TEST(mapping.hasComputedMapping() == true);
1746 BOOST_TEST(outData->values().sum() == inData->values().sum());
1747 BOOST_TEST(outData->values().sum() == 15);
1748
1749 for (unsigned int i = 0; i < outData->values().size() / dataDimension; ++i) {
1750 BOOST_TEST(outData->values()(i * dataDimension) == 0);
1751 BOOST_TEST(outData->values()(i * dataDimension + 1) == 0);
1752 }
1753
1754 // Check for the correct relation between components
1755 for (unsigned int i = 0; i < inData->values().size() / dataDimension; ++i) {
1756 inData->values()(i * dataDimension) = std::pow(i * dataDimension, 3);
1757 inData->values()(i * dataDimension + 1) = 5 * std::pow(i * dataDimension, 3);
1758 inData->values()(i * dataDimension + 2) = 10 * std::pow(i * dataDimension, 3);
1759 }
1760 mapping.clear();
1761 outData->values().setZero();
1762 mapping.computeMapping();
1763 mapping.map(inDataID, outDataID);
1764 BOOST_TEST(mapping.hasComputedMapping() == true);
1765 BOOST_TEST(outData->values().sum() == inData->values().sum());
1766
1767 for (unsigned int i = 0; i < outData->values().size() / dataDimension; ++i) {
1768 // Some result values are close to zero and we cannot compare the relation between these values
1769 if (outData->values()(i * dataDimension) > 1e-10) {
1770 BOOST_TEST(outData->values()(i * dataDimension + 1) == 5 * outData->values()(i * dataDimension));
1771 BOOST_TEST(outData->values()(i * dataDimension + 2) == 10 * outData->values()(i * dataDimension));
1772 }
1773 }
1774 BOOST_TEST(outData->values()(55) == 4087.8100404079933);
1775
1776 // The remaining parts should already be covered by the other 3D/2D tests
1777}
1778
1779void performReferenceTesting(Mapping &testMapping, Mapping &referenceMapping, int dim, int nComponents)
1780{
1781 // Create mesh to map from
1782 mesh::PtrMesh inMesh(new mesh::Mesh("InMesh", dim, testing::nextMeshID()));
1783 mesh::PtrData testInData = inMesh->createData("testData", nComponents, 0_dataID);
1784 mesh::PtrData refInData = inMesh->createData("refData", nComponents, 1_dataID);
1785 int testInDataID = testInData->getID();
1786 int refInDataID = refInData->getID();
1787
1788 if (dim == 2) {
1789 // 10×10 grid over the unit square [0,1]×[0,1]
1790 const int N = 10;
1791 for (int i = 0; i < N; ++i) {
1792 double x = double(i) / double(N - 1);
1793 for (int j = 0; j < N; ++j) {
1794 double y = double(j) / double(N - 1);
1795 inMesh->createVertex(Eigen::Vector2d(x, y));
1796 }
1797 }
1798 } else { // dim == 3
1799 // 7×7×7 grid over the unit cube [0,1]^3
1800 const int N = 7;
1801 for (int i = 0; i < N; ++i) {
1802 double x = double(i) / double(N - 1);
1803 for (int j = 0; j < N; ++j) {
1804 double y = double(j) / double(N - 1);
1805 for (int k = 0; k < N; ++k) {
1806 double z = double(k) / double(N - 1);
1807 inMesh->createVertex(Eigen::Vector3d(x, y, z));
1808 }
1809 }
1810 }
1811 }
1812 inMesh->allocateDataValues();
1813 addGlobalIndex(inMesh);
1814
1815 // Create mesh to map to
1816 mesh::PtrMesh outMesh(new mesh::Mesh("OutMesh", dim, testing::nextMeshID()));
1817 mesh::PtrData testOutData = outMesh->createData("testData", nComponents, 2_dataID);
1818 mesh::PtrData refOutData = outMesh->createData("refData", nComponents, 3_dataID);
1819 int testOutDataID = testOutData->getID();
1820 int refOutDataID = refOutData->getID();
1821
1822 if (dim == 2) {
1823 const int N = 9; // 9×9 test grid
1824 for (int i = 0; i < N; ++i) {
1825 // offset by half‐cell so no test‐point matches the main grid
1826 double x = (double(i) + 0.2) / double(N);
1827 for (int j = 0; j < N; ++j) {
1828 double y = (double(j) + 0.5) / double(N);
1829 outMesh->createVertex(Eigen::Vector2d(x, y));
1830 }
1831 }
1832 } else { // dim == 3
1833 const int N = 8; // 8×8×8 test grid
1834 for (int i = 0; i < N; ++i) {
1835 double x = (double(i) + 0.2) / double(N);
1836 for (int j = 0; j < N; ++j) {
1837 double y = (double(j) + 0.3) / double(N);
1838 for (int k = 0; k < N; ++k) {
1839 double z = (double(k) + 0.35) / double(N);
1840 outMesh->createVertex(Eigen::Vector3d(x, y, z));
1841 }
1842 }
1843 }
1844 }
1845 outMesh->allocateDataValues();
1846 addGlobalIndex(outMesh);
1847
1848 // Setup mapping with mapping coordinates and geometry used
1849 if (testMapping.getConstraint() == Mapping::CONSISTENT) {
1850 testMapping.setMeshes(inMesh, outMesh);
1851 referenceMapping.setMeshes(inMesh, outMesh);
1852 BOOST_TEST(testMapping.hasComputedMapping() == false);
1853
1854 auto &val = testInData->values();
1855 for (std::size_t i = 0; i < inMesh->nVertices(); ++i) {
1856 // base value ramps from 0.0 to 1.0
1857 double base = double(i) / double(inMesh->nVertices() - 1);
1858 for (int c = 0; c < nComponents; ++c) {
1859 // (2*c + 1) = 1, 3, 5, = make data components linear dependent
1860 val[i * nComponents + c] = (2 * c + 1) * base;
1861 }
1862 }
1863 refInData->values() = testInData->values();
1864
1865 testMapping.computeMapping();
1866
1867 testMapping.map(testInDataID, testOutDataID);
1868 referenceMapping.computeMapping();
1869 referenceMapping.map(refInDataID, refOutDataID);
1870 BOOST_TEST(testMapping.hasComputedMapping() == true);
1871 BOOST_TEST(testOutData->values() == refOutData->values(), boost::test_tools::per_element());
1872
1873 } else {
1874 testMapping.setMeshes(outMesh, inMesh);
1875 referenceMapping.setMeshes(outMesh, inMesh);
1876 BOOST_TEST(testMapping.hasComputedMapping() == false);
1877
1878 auto &val = testOutData->values();
1879 for (size_t i = 0; i < outMesh->nVertices(); ++i) {
1880 // base value ramps from 0.0 to 1.0
1881 double base = double(i) / double(outMesh->nVertices() - 1);
1882 for (int c = 0; c < nComponents; ++c) {
1883 // (2*c + 1) = 1, 3, 5, = make data components linear dependent
1884 val[i * nComponents + c] = (2 * c + 1) * base;
1885 }
1886 }
1887 refOutData->values() = testOutData->values();
1888
1889 testMapping.computeMapping();
1890 testMapping.map(testOutDataID, testInDataID);
1891 referenceMapping.computeMapping();
1892 referenceMapping.map(refOutDataID, refInDataID);
1893 BOOST_TEST(testMapping.hasComputedMapping() == true);
1894 BOOST_TEST(testInData->values() == refInData->values(), boost::test_tools::per_element());
1895 }
1896
1897 // The remaining parts should already be covered by the other 3D/2D tests
1898 testMapping.clear();
1899 referenceMapping.clear();
1900}
1901
1902PRECICE_TEST_SETUP(1_rank)
1903BOOST_AUTO_TEST_CASE(PartitionOfUnityMappingTests)
1904{
1905 PRECICE_TEST();
1906 mapping::CompactPolynomialC0 function(3);
1908 perform2DTestConsistentMapping(consistentMap2D);
1910 perform2DTestConsistentMappingVector(consistentMap2DVector);
1912 performTestConsistentMapDeadAxis(consistentMap2DDeadAxis, 2);
1914 performTestConsistentMapDeadAxis(consistentMap3DDeadAxis, 3);
1916 perform2DTestConservativeMapping(conservativeMap2D);
1917 mapping::PartitionOfUnityMapping<CompactPolynomialC0> conservativeMap2DVector(Mapping::CONSERVATIVE, 2, function, Polynomial::SEPARATE, 5, 0.4, false);
1918 perform2DTestConservativeMappingVector(conservativeMap2DVector);
1920 perform3DTestConsistentMapping(consistentMap3D);
1921 mapping::PartitionOfUnityMapping<CompactPolynomialC0> consistentMap3DVector(Mapping::CONSISTENT, 3, function, Polynomial::SEPARATE, 5, 0.265, false);
1922 perform3DTestConsistentMappingVector(consistentMap3DVector);
1924 perform3DTestConservativeMapping(conservativeMap3D);
1925 mapping::PartitionOfUnityMapping<CompactPolynomialC0> conservativeMap3DVector(Mapping::CONSERVATIVE, 3, function, Polynomial::SEPARATE, 5, 0.265, false);
1926 perform3DTestConservativeMappingVector(conservativeMap3DVector);
1927}
1928
1929PRECICE_TEST_SETUP(1_rank)
1930BOOST_AUTO_TEST_CASE(JustInTimeMapping)
1931{
1932 PRECICE_TEST();
1933 // using scalar data
1934 mapping::CompactPolynomialC0 c0function(3);
1935 mapping::PartitionOfUnityMapping<CompactPolynomialC0> polynomial3Dconsistent(Mapping::CONSISTENT, 3, c0function, Polynomial::SEPARATE, 5, 0.265, false);
1936 perform3DTestJustInTimeMappingWithPolynomial(polynomial3Dconsistent);
1937 // using vector data
1938 mapping::CompactPolynomialC4 c4function(3);
1939 mapping::PartitionOfUnityMapping<CompactPolynomialC4> noPolynomial2Dconsistent(Mapping::CONSISTENT, 2, c4function, Polynomial::OFF, 5, 0.265, false);
1940 perform2DTestJustInTimeMappingNoPolynomial(noPolynomial2Dconsistent);
1941
1942 // using scalar data
1943 mapping::CompactPolynomialC2 c2function(3);
1944 mapping::PartitionOfUnityMapping<CompactPolynomialC2> polynomial3Dconservative(Mapping::CONSERVATIVE, 3, c2function, Polynomial::SEPARATE, 5, 0.265, false);
1945 perform3DTestJustInTimeMappingConservative(polynomial3Dconservative);
1946 // using vector data
1947 mapping::CompactPolynomialC6 c6function(10);
1948 mapping::PartitionOfUnityMapping<CompactPolynomialC6> noPolynomial2Dconservative(Mapping::CONSERVATIVE, 2, c6function, Polynomial::OFF, 5, 0.265, false);
1949 perform2DTestJustInTimeMappingConservative(noPolynomial2Dconservative);
1950}
1951
1952// Test for small meshes, where the number of requested vertices per cluster is bigger than the global
1953PRECICE_TEST_SETUP(1_rank)
1954BOOST_AUTO_TEST_CASE(TestSingleClusterPartitionOfUnity)
1955{
1956 PRECICE_TEST();
1957 mapping::CompactPolynomialC0 function(3);
1959
1960 int dimensions = 3;
1961 using Eigen::Vector3d;
1962
1963 // Create mesh to map from
1964 mesh::PtrMesh inMesh(new mesh::Mesh("InMesh", dimensions, testing::nextMeshID()));
1965 mesh::PtrData inData = inMesh->createData("InData", 1, 0_dataID);
1966 int inDataID = inData->getID();
1967 inMesh->createVertex(Vector3d(0.0, 0.0, 0.0));
1968 inMesh->createVertex(Vector3d(1.0, 0.0, 0.0));
1969 inMesh->createVertex(Vector3d(1.0, 1.0, 0.0));
1970 inMesh->createVertex(Vector3d(0.0, 1.0, 0.0));
1971
1972 inMesh->createVertex(Vector3d(0.0, 0.0, 1.0));
1973 inMesh->createVertex(Vector3d(1.0, 0.0, 1.0));
1974 inMesh->createVertex(Vector3d(1.0, 1.0, 1.0));
1975 inMesh->createVertex(Vector3d(0.0, 1.0, 1.0));
1976
1977 inMesh->createVertex(Vector3d(2.0, 0.0, 0.0));
1978 inMesh->createVertex(Vector3d(3.0, 0.0, 0.0));
1979 inMesh->createVertex(Vector3d(3.0, 1.0, 0.0));
1980 inMesh->createVertex(Vector3d(2.0, 1.0, 0.0));
1981
1982 inMesh->createVertex(Vector3d(2.0, 0.0, 1.0));
1983 inMesh->createVertex(Vector3d(3.0, 0.0, 1.0));
1984 inMesh->createVertex(Vector3d(3.0, 1.0, 1.0));
1985 inMesh->createVertex(Vector3d(2.0, 1.0, 1.0));
1986
1987 inMesh->createVertex(Vector3d(4.0, 0.0, 0.0));
1988 inMesh->createVertex(Vector3d(5.0, 0.0, 0.0));
1989 inMesh->createVertex(Vector3d(5.0, 1.0, 0.0));
1990 inMesh->createVertex(Vector3d(4.0, 1.0, 0.0));
1991
1992 inMesh->createVertex(Vector3d(4.0, 0.0, 1.0));
1993 inMesh->createVertex(Vector3d(5.0, 0.0, 1.0));
1994 inMesh->createVertex(Vector3d(5.0, 1.0, 1.0));
1995 inMesh->createVertex(Vector3d(4.0, 1.0, 1.0));
1996
1997 inMesh->allocateDataValues();
1998 addGlobalIndex(inMesh);
1999
2000 auto &values = inData->values();
2001 // Set the values in the parallel (z) plane 3*values
2002 values << 1.0, 2.0, 2.0, 1.0, 3.0, 6.0, 6.0, 3.0, 3.0, 4.0, 4.0, 3.0, 9.0, 12.0, 12.0, 9.0, 5.0, 6.0, 6.0, 5.0, 15.0, 18.0, 18.0, 15.0;
2003
2004 // Create mesh to map to
2005 mesh::PtrMesh outMesh(new mesh::Mesh("OutMesh", dimensions, testing::nextMeshID()));
2006 mesh::PtrData outData = outMesh->createData("OutData", 1, 1_dataID);
2007 int outDataID = outData->getID();
2008 mesh::Vertex &vertex = outMesh->createVertex(Vector3d(0, 0, 0));
2009 outMesh->createVertex(Vector3d(3.5, 0.5, 0.5));
2010 outMesh->createVertex(Vector3d(2.5, 0.5, 1.0));
2011 outMesh->createVertex(Vector3d(0, 0, 0.5));
2012 outMesh->createVertex(Vector3d(5, 1, 0.5));
2013 outMesh->allocateDataValues();
2014 addGlobalIndex(outMesh);
2015
2016 // Setup mapping with mapping coordinates and geometry used
2017 mapping.setMeshes(inMesh, outMesh);
2018 BOOST_TEST(mapping.hasComputedMapping() == false);
2019
2020 vertex.setCoords(Vector3d(0.0, 0.0, 0.0));
2021 mapping.computeMapping();
2022 mapping.map(inDataID, outDataID);
2023 double value = outData->values()(0);
2024 double value1 = outData->values()(1);
2025 double value2 = outData->values()(2);
2026 BOOST_TEST(mapping.hasComputedMapping() == true);
2027 BOOST_TEST(value == 1.0);
2028 BOOST_TEST(value1 == 9.0);
2029 BOOST_TEST(value2 == 10.5);
2030
2031 vertex.setCoords(Vector3d(0.0, 0.5, 0.5));
2032 mapping.clear();
2033 outData->values().setZero();
2034 mapping.computeMapping();
2035 mapping.map(inDataID, outDataID);
2036 value = outData->values()(0);
2037 BOOST_TEST(mapping.hasComputedMapping() == true);
2038 BOOST_TEST(value == 2.0);
2039
2040 vertex.setCoords(Vector3d(1.0, 0.0, 0.0));
2041 mapping.clear();
2042 outData->values().setZero();
2043 mapping.computeMapping();
2044 mapping.map(inDataID, outDataID);
2045 value = outData->values()(0);
2046 BOOST_TEST(mapping.hasComputedMapping() == true);
2047 BOOST_TEST(value == 2.0);
2048
2049 vertex.setCoords(Vector3d(1.0, 0.5, 0.5));
2050 mapping.clear();
2051 outData->values().setZero();
2052 mapping.computeMapping();
2053 mapping.map(inDataID, outDataID);
2054 value = outData->values()(0);
2055 BOOST_TEST(mapping.hasComputedMapping() == true);
2056 BOOST_TEST(value == 4.0);
2057
2058 vertex.setCoords(Vector3d(0.5, 0.5, 1.0));
2059 mapping.clear();
2060 outData->values().setZero();
2061 mapping.computeMapping();
2062 mapping.map(inDataID, outDataID);
2063 value = outData->values()(0);
2064 BOOST_TEST(mapping.hasComputedMapping() == true);
2065 BOOST_TEST(value > 4.6);
2066
2067 vertex.setCoords(Vector3d(0.5, 1.0, 0.0));
2068 mapping.clear();
2069 outData->values().setZero();
2070 mapping.computeMapping();
2071 mapping.map(inDataID, outDataID);
2072 value = outData->values()(0);
2073 BOOST_TEST(mapping.hasComputedMapping() == true);
2074 BOOST_TEST(value < 1.4);
2075}
2076
2077#ifndef PRECICE_NO_KOKKOS_KERNELS
2078
2079#define PERFORM_REFERENCE_TEST(EXECUTOR, type, function, dim) \
2080 { \
2081 MappingConfiguration::GinkgoParameter gpm; \
2082 gpm.executor = EXECUTOR; \
2083 gpm.deviceId = 0; \
2084 gpm.nThreads = 1; \
2085 int scalar = 1; \
2086 int vector = dim; \
2087 mapping::PartitionOfUnityMapping<type> testOff(Mapping::CONSISTENT, dim, function, Polynomial::OFF, 25, 0.15, false, gpm, true); \
2088 mapping::PartitionOfUnityMapping<type> testOn(Mapping::CONSISTENT, dim, function, Polynomial::OFF, 25, 0.15, false, gpm, false); \
2089 mapping::PartitionOfUnityMapping<type> ref(Mapping::CONSISTENT, dim, function, Polynomial::OFF, 25, 0.15, false); \
2090 performReferenceTesting(testOff, ref, dim, scalar); \
2091 performReferenceTesting(testOn, ref, dim, scalar); \
2092 performReferenceTesting(testOff, ref, dim, vector); \
2093 performReferenceTesting(testOn, ref, dim, vector); \
2094 mapping::PartitionOfUnityMapping<type> testPolyOff(Mapping::CONSISTENT, dim, function, Polynomial::SEPARATE, 25, 0.15, false, gpm, true); \
2095 mapping::PartitionOfUnityMapping<type> testPolyOn(Mapping::CONSISTENT, dim, function, Polynomial::SEPARATE, 25, 0.15, false, gpm, false); \
2096 mapping::PartitionOfUnityMapping<type> refPoly(Mapping::CONSISTENT, dim, function, Polynomial::SEPARATE, 25, 0.15, false); \
2097 performReferenceTesting(testPolyOff, refPoly, dim, scalar); \
2098 performReferenceTesting(testPolyOn, refPoly, dim, scalar); \
2099 performReferenceTesting(testPolyOff, refPoly, dim, vector); \
2100 performReferenceTesting(testPolyOn, refPoly, dim, vector); \
2101 mapping::PartitionOfUnityMapping<type> testConservativeOn(Mapping::CONSERVATIVE, dim, function, Polynomial::OFF, 25, 0.15, false, gpm, true); \
2102 mapping::PartitionOfUnityMapping<type> testConservativeOff(Mapping::CONSERVATIVE, dim, function, Polynomial::OFF, 25, 0.15, false, gpm, false); \
2103 mapping::PartitionOfUnityMapping<type> refConservative(Mapping::CONSERVATIVE, dim, function, Polynomial::OFF, 25, 0.15, false); \
2104 performReferenceTesting(testConservativeOn, refConservative, dim, scalar); \
2105 performReferenceTesting(testConservativeOff, refConservative, dim, scalar); \
2106 performReferenceTesting(testConservativeOn, refConservative, dim, vector); \
2107 performReferenceTesting(testConservativeOff, refConservative, dim, vector); \
2108 mapping::PartitionOfUnityMapping<type> testConservativePolyOn(Mapping::CONSERVATIVE, dim, function, Polynomial::SEPARATE, 25, 0.15, false, gpm, true); \
2109 mapping::PartitionOfUnityMapping<type> testConservativePolyOff(Mapping::CONSERVATIVE, dim, function, Polynomial::SEPARATE, 25, 0.15, false, gpm, false); \
2110 mapping::PartitionOfUnityMapping<type> refConservativePoly(Mapping::CONSERVATIVE, dim, function, Polynomial::SEPARATE, 25, 0.15, false); \
2111 performReferenceTesting(testConservativePolyOn, refConservativePoly, dim, scalar); \
2112 performReferenceTesting(testConservativePolyOff, refConservativePoly, dim, vector); \
2113 performReferenceTesting(testConservativePolyOn, refConservativePoly, dim, scalar); \
2114 performReferenceTesting(testConservativePolyOff, refConservativePoly, dim, vector); \
2115 }
2116
2117#define TEST_CPU_REFERENCE_FOR_SPD_RBFS(EXECUTOR) \
2118 PRECICE_TEST_SETUP(1_rank, Require::Ginkgo) \
2119 BOOST_AUTO_TEST_CASE(MapCompactPolynomialC0) \
2120 { \
2121 PRECICE_TEST(); \
2122 CompactPolynomialC0 fct(0.8); \
2123 PERFORM_REFERENCE_TEST(EXECUTOR, CompactPolynomialC0, fct, 2); \
2124 PERFORM_REFERENCE_TEST(EXECUTOR, CompactPolynomialC0, fct, 3); \
2125 } \
2126 PRECICE_TEST_SETUP(1_rank, Require::Ginkgo) \
2127 BOOST_AUTO_TEST_CASE(MapCompactPolynomialC2) \
2128 { \
2129 PRECICE_TEST(); \
2130 CompactPolynomialC2 fct(0.8); \
2131 PERFORM_REFERENCE_TEST(EXECUTOR, CompactPolynomialC2, fct, 2); \
2132 PERFORM_REFERENCE_TEST(EXECUTOR, CompactPolynomialC2, fct, 3); \
2133 } \
2134 PRECICE_TEST_SETUP(1_rank, Require::Ginkgo) \
2135 BOOST_AUTO_TEST_CASE(MapCompactPolynomialC4) \
2136 { \
2137 PRECICE_TEST(); \
2138 CompactPolynomialC4 fct(0.6); \
2139 PERFORM_REFERENCE_TEST(EXECUTOR, CompactPolynomialC4, fct, 2); \
2140 PERFORM_REFERENCE_TEST(EXECUTOR, CompactPolynomialC4, fct, 3); \
2141 } \
2142 PRECICE_TEST_SETUP(1_rank, Require::Ginkgo) \
2143 BOOST_AUTO_TEST_CASE(MapCompactPolynomialC6) \
2144 { \
2145 PRECICE_TEST(); \
2146 CompactPolynomialC6 fct(0.4); \
2147 PERFORM_REFERENCE_TEST(EXECUTOR, CompactPolynomialC6, fct, 2); \
2148 PERFORM_REFERENCE_TEST(EXECUTOR, CompactPolynomialC6, fct, 3); \
2149 } \
2150 PRECICE_TEST_SETUP(1_rank, Require::Ginkgo) \
2151 BOOST_AUTO_TEST_CASE(MapCompactPolynomialC8) \
2152 { \
2153 PRECICE_TEST(); \
2154 CompactPolynomialC8 fct(0.2); \
2155 PERFORM_REFERENCE_TEST(EXECUTOR, CompactPolynomialC8, fct, 2); \
2156 PERFORM_REFERENCE_TEST(EXECUTOR, CompactPolynomialC8, fct, 3); \
2157 } \
2158 PRECICE_TEST_SETUP(1_rank, Require::Ginkgo) \
2159 BOOST_AUTO_TEST_CASE(MapCompactThinPlateSplinesC2) \
2160 { \
2161 PRECICE_TEST(); \
2162 double supportRadius = 1.2; \
2163 CompactThinPlateSplinesC2 fct(supportRadius); \
2164 PERFORM_REFERENCE_TEST(EXECUTOR, CompactThinPlateSplinesC2, fct, 2); \
2165 PERFORM_REFERENCE_TEST(EXECUTOR, CompactThinPlateSplinesC2, fct, 3); \
2166 } \
2167 PRECICE_TEST_SETUP(1_rank, Require::Ginkgo) \
2168 BOOST_AUTO_TEST_CASE(MapGaussian) \
2169 { \
2170 PRECICE_TEST(); \
2171 Gaussian fct(7); \
2172 PERFORM_REFERENCE_TEST(EXECUTOR, Gaussian, fct, 2); \
2173 PERFORM_REFERENCE_TEST(EXECUTOR, Gaussian, fct, 3); \
2174 }
2175
2176#define TEST_EXECUTOR_UNIT(EXECUTOR) \
2177 PRECICE_TEST_SETUP(1_rank, Require::Ginkgo) \
2178 BOOST_AUTO_TEST_CASE(UnitTests) \
2179 { \
2180 PRECICE_TEST(); \
2181 MappingConfiguration::GinkgoParameter gpm; \
2182 gpm.executor = EXECUTOR; \
2183 gpm.deviceId = 0; \
2184 mapping::CompactPolynomialC0 function(3); \
2185 mapping::PartitionOfUnityMapping<CompactPolynomialC0> consistentMap2D(Mapping::CONSISTENT, 2, function, Polynomial::SEPARATE, 5, 0.4, false, gpm); \
2186 perform2DTestConsistentMapping(consistentMap2D); \
2187 mapping::PartitionOfUnityMapping<CompactPolynomialC6> consistentMap2DDeadAxis(Mapping::CONSISTENT, 2, mapping::CompactPolynomialC6(6), Polynomial::SEPARATE, 5, 0.4, false, gpm); \
2188 performTestConsistentMapDeadAxis(consistentMap2DDeadAxis, 2); \
2189 }
2190
2191#ifdef PRECICE_WITH_CUDA
2193TEST_EXECUTOR_UNIT("cuda");
2196#endif
2197
2198#ifdef PRECICE_WITH_HIP
2200TEST_EXECUTOR_UNIT("hip");
2203#endif
2204
2205#ifdef PRECICE_WITH_SYCL
2207TEST_EXECUTOR_UNIT("sycl");
2210#endif
2211
2212#ifdef PRECICE_WITH_OPENMP
2214TEST_EXECUTOR_UNIT("openmp");
2217#endif
2218
2219#undef PERFORM_REFERENCE_TEST
2220#undef TEST_CPU_REFERENCE_FOR_SPD_RBFS
2221#undef TEST_EXECUTOR_UNIT
2222#endif
2223
2224BOOST_AUTO_TEST_SUITE_END() // Serial
2225
2227
2228void addGlobalIndex(mesh::PtrMesh &mesh, int offset = 0)
2229{
2230 for (mesh::Vertex &v : mesh->vertices()) {
2231 v.setGlobalIndex(v.getID() + offset);
2232 }
2233}
2234
2237 int rank;
2239 std::vector<double> position;
2240 std::vector<double> value;
2241};
2242
2243/*
2244MeshSpecification format:
2245{ {rank, owner rank, {x, y, z}, {v}}, ... }
2246
2247also see struct VertexSpecification.
2248
2249- -1 on rank means all ranks
2250- -1 on owner rank means no rank
2251- x, y, z is position of vertex, z is optional, 2D mesh will be created then
2252- v is the value of the respective vertex. Only 1D supported at this time.
2253
2254ReferenceSpecification format:
2255{ {rank, {v}, ... }
2256- -1 on rank means all ranks
2257- v is the expected value of n-th vertex on that particular rank
2258*/
2259using MeshSpecification = std::vector<VertexSpecification>;
2260
2262using ReferenceSpecification = std::vector<std::pair<int, std::vector<double>>>;
2263
2265 MeshSpecification const &vertices,
2267 mesh::PtrData &data,
2268 int globalIndexOffset = 0,
2269 bool meshIsSmaller = false)
2270{
2271 Eigen::VectorXd d;
2272
2273 int i = 0;
2274 for (auto &vertex : vertices) {
2275 if (vertex.rank == context.rank or vertex.rank == -1) {
2276 if (vertex.position.size() == 3) // 3-dimensional
2277 mesh->createVertex(Eigen::Vector3d(vertex.position.data()));
2278 else if (vertex.position.size() == 2) // 2-dimensional
2279 mesh->createVertex(Eigen::Vector2d(vertex.position.data()));
2280
2281 int valueDimension = vertex.value.size();
2282
2283 if (vertex.owner == context.rank)
2284 mesh->vertices().back().setOwner(true);
2285 else
2286 mesh->vertices().back().setOwner(false);
2287
2288 d.conservativeResize(i * valueDimension + valueDimension);
2289 // Get data in every dimension
2290 for (int dim = 0; dim < valueDimension; ++dim) {
2291 d(i * valueDimension + dim) = vertex.value.at(dim);
2292 }
2293 i++;
2294 }
2295 }
2296 addGlobalIndex(mesh, globalIndexOffset);
2297 mesh->allocateDataValues();
2298 // All tests use eight vertices
2299 // if (meshIsSmaller) {
2300 // mesh->setGlobalNumberOfVertices(7);
2301 // } else {
2302 // mesh->setGlobalNumberOfVertices(8);
2303 // }
2304 data->values() = d;
2305}
2306
2307void testDistributed(const TestContext &context,
2309 MeshSpecification inMeshSpec,
2310 MeshSpecification outMeshSpec,
2311 ReferenceSpecification referenceSpec,
2312 int inGlobalIndexOffset = 0,
2313 bool meshIsSmaller = false)
2314{
2315 int meshDimension = inMeshSpec.at(0).position.size();
2316 int valueDimension = inMeshSpec.at(0).value.size();
2317
2318 mesh::PtrMesh inMesh(new mesh::Mesh("InMesh", meshDimension, testing::nextMeshID()));
2319 mesh::PtrData inData = inMesh->createData("InData", valueDimension, 0_dataID);
2320 int inDataID = inData->getID();
2321
2322 getDistributedMesh(context, inMeshSpec, inMesh, inData, inGlobalIndexOffset);
2323
2324 mesh::PtrMesh outMesh(new mesh::Mesh("outMesh", meshDimension, testing::nextMeshID()));
2325 mesh::PtrData outData = outMesh->createData("OutData", valueDimension, 1_dataID);
2326 int outDataID = outData->getID();
2327
2328 getDistributedMesh(context, outMeshSpec, outMesh, outData, 0, meshIsSmaller);
2329
2330 mapping.setMeshes(inMesh, outMesh);
2331 BOOST_TEST(mapping.hasComputedMapping() == false);
2332
2333 mapping.computeMapping();
2334 BOOST_TEST(mapping.hasComputedMapping() == true);
2335 mapping.map(inDataID, outDataID);
2336
2337 int index = 0;
2338 for (auto &referenceVertex : referenceSpec) {
2339 if (referenceVertex.first == context.rank or referenceVertex.first == -1) {
2340 for (int dim = 0; dim < valueDimension; ++dim) {
2341 BOOST_TEST_INFO("Index of vertex: " << index << " - Dimension: " << dim);
2342 BOOST_TEST(outData->values()(index * valueDimension + dim) == referenceVertex.second.at(dim));
2343 }
2344 ++index;
2345 }
2346 }
2347 BOOST_TEST(outData->values().size() == index * valueDimension);
2348}
2349
2350PRECICE_TEST_SETUP(""_on(4_ranks).setupIntraComm())
2351BOOST_AUTO_TEST_CASE(DistributedConsistent2D)
2352{
2353 PRECICE_TEST();
2354 std::vector<int> globalIndexOffsets = {0, 0, 0, 0};
2355
2356 MeshSpecification in{// Consistent mapping: The inMesh is communicated
2357 {-1, 0, {0, 0}, {1}},
2358 {-1, 0, {0, 1}, {2}},
2359 {-1, 1, {1, 0}, {3}},
2360 {-1, 1, {1, 1}, {4}},
2361 {-1, 2, {2, 0}, {5}},
2362 {-1, 2, {2, 1}, {6}},
2363 {-1, 3, {3, 0}, {7}},
2364 {-1, 3, {3, 1}, {8}}};
2365 MeshSpecification out{// The outMesh is local, distributed among all ranks
2366 {0, -1, {0, 0}, {0}},
2367 {0, -1, {0, 1}, {0}},
2368 {1, -1, {1, 0}, {0}},
2369 {1, -1, {1, 1}, {0}},
2370 {2, -1, {2, 0}, {0}},
2371 {2, -1, {2, 1}, {0}},
2372 {3, -1, {3, 0}, {0}},
2373 {3, -1, {3, 1}, {0}}};
2374
2375 ReferenceSpecification ref{// Tests for {0, 1} on the first rank, {1, 2} on the second, ...
2376 {0, {1}},
2377 {0, {2}},
2378 {1, {3}},
2379 {1, {4}},
2380 {2, {5}},
2381 {2, {6}},
2382 {3, {7}},
2383 {3, {8}}};
2384
2386 testDistributed(context, consistentMap2D, in, out, ref, globalIndexOffsets.at(context.rank));
2387}
2388
2389// Same as above, but including empty ranks not participating
2390PRECICE_TEST_SETUP(""_on(4_ranks).setupIntraComm())
2391BOOST_AUTO_TEST_CASE(DistributedConsistent2DEmptyOut)
2392{
2393 PRECICE_TEST();
2394 std::vector<int> globalIndexOffsets = {0, 0, 0, 0};
2395
2396 MeshSpecification in{// Consistent mapping: The inMesh is communicated
2397 {-1, 0, {0, 0}, {1}},
2398 {-1, 0, {0, 1}, {2}},
2399 {-1, 1, {1, 0}, {3}},
2400 {-1, 1, {1, 1}, {4}},
2401 {-1, 2, {2, 0}, {5}},
2402 {-1, 2, {2, 1}, {6}},
2403 {-1, 3, {3, 0}, {7}},
2404 {-1, 3, {3, 1}, {8}}};
2405 MeshSpecification out{// The outMesh is local, distributed among all ranks
2406 {0, 0, {0, 0}, {0}},
2407 {0, 0, {0, 1}, {0}},
2408 {1, 1, {1, 0}, {0}},
2409 {1, 1, {1, 1}, {0}},
2410 {2, 2, {2, 0}, {0}},
2411 {2, 2, {2, 1}, {0}},
2412 {2, 2, {3, 0}, {0}},
2413 {2, 2, {3, 1}, {0}}};
2414
2415 ReferenceSpecification ref{// Tests for {0, 1} on the first rank, {1, 2} on the second, ...
2416 {0, {1}},
2417 {0, {2}},
2418 {1, {3}},
2419 {1, {4}},
2420 {2, {5}},
2421 {2, {6}},
2422 {2, {7}},
2423 {2, {8}}};
2424
2426 testDistributed(context, consistentMap2D, in, out, ref, globalIndexOffsets.at(context.rank));
2427}
2428
2429// Same as above, but including empty ranks not participating
2430PRECICE_TEST_SETUP(""_on(4_ranks).setupIntraComm())
2431BOOST_AUTO_TEST_CASE(DistributedConsistent2DEmptyRank)
2432{
2433 PRECICE_TEST();
2434 std::vector<int> globalIndexOffsets = {0, 0, 0, 0};
2435
2436 MeshSpecification in{// Consistent mapping: The inMesh is communicated
2437 {-1, 0, {0, 0}, {1}},
2438 {-1, 0, {0, 1}, {2}},
2439 {-1, 1, {1, 0}, {3}},
2440 {-1, 1, {1, 1}, {4}},
2441 {-1, 2, {2, 0}, {5}},
2442 {-1, 2, {2, 1}, {6}}};
2443
2444 MeshSpecification out{// The outMesh is local, distributed among all ranks
2445 {0, 0, {0, 0}, {0}},
2446 {0, 0, {0, 1}, {0}},
2447 {1, 1, {1, 0}, {0}},
2448 {1, 1, {1, 1}, {0}},
2449 {2, 2, {2, 0}, {0}},
2450 {2, 2, {2, 1}, {0}}};
2451
2452 ReferenceSpecification ref{// Tests for {0, 1} on the first rank, {1, 2} on the second, ...
2453 {0, {1}},
2454 {0, {2}},
2455 {1, {3}},
2456 {1, {4}},
2457 {2, {5}},
2458 {2, {6}}};
2459
2461 testDistributed(context, consistentMap2D, in, out, ref, globalIndexOffsets.at(context.rank));
2462}
2463
2464PRECICE_TEST_SETUP(""_on(4_ranks).setupIntraComm())
2465BOOST_AUTO_TEST_CASE(DistributedConservative2D)
2466{
2467 PRECICE_TEST();
2468 std::vector<int> globalIndexOffsets = {0, 0, 0, 0};
2469
2470 MeshSpecification in{// Conservative mapping: The inMesh is local
2471 {0, -1, {0, 0}, {1}},
2472 {0, -1, {0, 1}, {2}},
2473 {1, -1, {1, 0}, {3}},
2474 {1, -1, {1, 1}, {4}},
2475 {2, -1, {2, 0}, {5}},
2476 {2, -1, {2, 1}, {6}},
2477 {3, -1, {3, 0}, {7}},
2478 {3, -1, {3, 1}, {8}}};
2479 MeshSpecification out{// The outMesh is remote, distributed among all ranks
2480 {0, 0, {0, 0}, {0}},
2481 {0, 0, {0, 1}, {0}},
2482 {1, 1, {1, 0}, {0}},
2483 {1, 1, {1, 1}, {0}},
2484 {2, 2, {2, 0}, {0}},
2485 {2, 2, {2, 1}, {0}},
2486 {3, 3, {3, 0}, {0}},
2487 {3, 3, {3, 1}, {0}}};
2488
2489 ReferenceSpecification ref{// Tests for {0, 1} on the first rank, {1, 2} on the second, ...
2490 {0, {1}},
2491 {0, {2}},
2492 {1, {3}},
2493 {1, {4}},
2494 {2, {5}},
2495 {2, {6}},
2496 {3, {7}},
2497 {3, {8}}};
2498
2500 testDistributed(context, conservativeMap2D, in, out, ref, globalIndexOffsets.at(context.rank));
2501}
2502
2503// Same as above, but checking with empty ranks
2504PRECICE_TEST_SETUP(""_on(4_ranks).setupIntraComm())
2505BOOST_AUTO_TEST_CASE(DistributedConservative2DEmptyRank)
2506{
2507 PRECICE_TEST();
2508 std::vector<int> globalIndexOffsets = {0, 2, 4, 6};
2509
2510 MeshSpecification in{// Conservative mapping: The inMesh is local
2511 {0, -1, {0, 0}, {1}},
2512 {0, -1, {0, 1}, {2}},
2513 {1, -1, {1, 0}, {3}},
2514 {1, -1, {1, 1}, {4}},
2515 {2, -1, {2, 0}, {5}},
2516 {2, -1, {2, 1}, {6}},
2517 {2, -1, {3, 0}, {7}},
2518 {2, -1, {3, 1}, {8}}};
2519 MeshSpecification out{// The outMesh is remote, distributed among all ranks
2520 {-1, 0, {0, 0}, {0}},
2521 {-1, 0, {0, 1}, {0}},
2522 {-1, 1, {1, 0}, {0}},
2523 {-1, 1, {1, 1}, {0}},
2524 {-1, 2, {2, 0}, {0}},
2525 {-1, 2, {2, 1}, {0}},
2526 {-1, 3, {3, 0}, {0}},
2527 {-1, 3, {3, 1}, {0}}};
2528
2529 ReferenceSpecification ref{// Tests for {0, 1} on the first rank, {1, 2} on the second, ...
2530 {0, {1}},
2531 {0, {2}},
2532 {0, {0}},
2533 {0, {0}},
2534 {0, {0}},
2535 {0, {0}},
2536 {0, {0}},
2537 {0, {0}},
2538 {1, {0}},
2539 {1, {0}},
2540 {1, {3}},
2541 {1, {4}},
2542 {1, {0}},
2543 {1, {0}},
2544 {1, {0}},
2545 {1, {0}},
2546 {2, {0}},
2547 {2, {0}},
2548 {2, {0}},
2549 {2, {0}},
2550 {2, {5}},
2551 {2, {6}},
2552 {2, {7}},
2553 {2, {8}},
2554 {3, {0}},
2555 {3, {0}},
2556 {3, {0}},
2557 {3, {0}},
2558 {3, {0}},
2559 {3, {0}},
2560 {3, {0}},
2561 {3, {0}}};
2562
2564 testDistributed(context, conservativeMap2D, in, out, ref, globalIndexOffsets.at(context.rank));
2565}
2566
2567// Same as above, but checking the primary rank for all output vertices
2568PRECICE_TEST_SETUP(""_on(2_ranks).setupIntraComm())
2569BOOST_AUTO_TEST_CASE(DistributedConservative2DTwoRanks)
2570{
2571 PRECICE_TEST();
2572 std::vector<int> globalIndexOffsets = {0, 2};
2573
2574 MeshSpecification in{// Conservative mapping: The inMesh is local
2575 {0, -1, {0, 0}, {1}},
2576 {0, -1, {0, 1}, {2}},
2577 {0, -1, {1, 0}, {3}},
2578 {0, -1, {1, 1}, {4}},
2579 {1, -1, {2, 0}, {5}},
2580 {1, -1, {2, 1}, {6}},
2581 {1, -1, {3, 0}, {7}},
2582 {1, -1, {3, 1}, {8}}};
2583 MeshSpecification out{// The outMesh is remote, distributed among all ranks
2584 {-1, 0, {0, 0}, {0}},
2585 {-1, 0, {0, 1}, {0}},
2586 {-1, 0, {1, 0}, {0}},
2587 {-1, 0, {1, 1}, {0}},
2588 {-1, 0, {2, 0}, {0}},
2589 {-1, 0, {2, 1}, {0}},
2590 {-1, 0, {3, 0}, {0}},
2591 {-1, 0, {3, 1}, {0}}};
2592
2593 ReferenceSpecification ref{// Tests for {0, 1} on the first rank, {1, 2} on the second, ...
2594 {0, {1}},
2595 {0, {2}},
2596 {0, {3}},
2597 {0, {4}},
2598 {0, {0}},
2599 {0, {0}},
2600 {0, {0}},
2601 {0, {0}},
2602 {1, {0}},
2603 {1, {0}},
2604 {1, {0}},
2605 {1, {0}},
2606 {1, {5}},
2607 {1, {6}},
2608 {1, {7}},
2609 {1, {8}}};
2610
2612 testDistributed(context, conservativeMap2D, in, out, ref, globalIndexOffsets.at(context.rank));
2613}
2614
2615void testTagging(const TestContext &context,
2616 MeshSpecification inMeshSpec,
2617 MeshSpecification outMeshSpec,
2618 MeshSpecification shouldTagFirstRound,
2619 MeshSpecification shouldTagSecondRound,
2620 bool consistent)
2621{
2622 int meshDimension = inMeshSpec.at(0).position.size();
2623 int valueDimension = inMeshSpec.at(0).value.size();
2624
2625 mesh::PtrMesh inMesh(new mesh::Mesh("InMesh", meshDimension, testing::nextMeshID()));
2626 mesh::PtrData inData = inMesh->createData("InData", valueDimension, 0_dataID);
2627 getDistributedMesh(context, inMeshSpec, inMesh, inData);
2628
2629 mesh::PtrMesh outMesh(new mesh::Mesh("outMesh", meshDimension, testing::nextMeshID()));
2630 mesh::PtrData outData = outMesh->createData("OutData", valueDimension, 1_dataID);
2631 getDistributedMesh(context, outMeshSpec, outMesh, outData);
2632
2635 inMesh->computeBoundingBox();
2636 outMesh->computeBoundingBox();
2637
2638 mapping.setMeshes(inMesh, outMesh);
2639 mapping.tagMeshFirstRound();
2640
2641 for (const auto &v : inMesh->vertices()) {
2642 auto pos = std::find_if(shouldTagFirstRound.begin(), shouldTagFirstRound.end(),
2643 [meshDimension, &v](const VertexSpecification &spec) {
2644 return std::equal(spec.position.data(), spec.position.data() + meshDimension, v.getCoords().data());
2645 });
2646 bool found = pos != shouldTagFirstRound.end();
2647 BOOST_TEST(found >= v.isTagged(),
2648 "FirstRound: Vertex " << v << " is tagged, but should not be.");
2649 BOOST_TEST(found <= v.isTagged(),
2650 "FirstRound: Vertex " << v << " is not tagged, but should be.");
2651 }
2652
2653 mapping.tagMeshSecondRound();
2654
2655 for (const auto &v : inMesh->vertices()) {
2656 auto posFirst = std::find_if(shouldTagFirstRound.begin(), shouldTagFirstRound.end(),
2657 [meshDimension, &v](const VertexSpecification &spec) {
2658 return std::equal(spec.position.data(), spec.position.data() + meshDimension, v.getCoords().data());
2659 });
2660 bool foundFirst = posFirst != shouldTagFirstRound.end();
2661 auto posSecond = std::find_if(shouldTagSecondRound.begin(), shouldTagSecondRound.end(),
2662 [meshDimension, &v](const VertexSpecification &spec) {
2663 return std::equal(spec.position.data(), spec.position.data() + meshDimension, v.getCoords().data());
2664 });
2665 bool foundSecond = posSecond != shouldTagSecondRound.end();
2666 BOOST_TEST(foundFirst <= v.isTagged(), "SecondRound: Vertex " << v
2667 << " is not tagged, but should be from the first round.");
2668 BOOST_TEST(foundSecond <= v.isTagged(), "SecondRound: Vertex " << v
2669 << " is not tagged, but should be.");
2670 BOOST_TEST((foundSecond or foundFirst) >= v.isTagged(), "SecondRound: Vertex " << v
2671 << " is tagged, but should not be.");
2672 }
2673}
2674
2675PRECICE_TEST_SETUP(""_on(4_ranks).setupIntraComm())
2676BOOST_AUTO_TEST_CASE(testTagFirstRound)
2677{
2678 PRECICE_TEST();
2679
2680 MeshSpecification outMeshSpec = {
2681 {0, -1, {0, 0}, {0}}};
2682 MeshSpecification inMeshSpec = {
2683 {0, -1, {-1, 0}, {1}}, // inside
2684 {0, -1, {-3, 0}, {1}}, // outside
2685 {0, 0, {1, 0}, {1}}, // inside, owner
2686 {0, -1, {3, 0}, {1}}, // outside
2687 {0, -1, {0, -1}, {1}}, // inside
2688 {0, -1, {0, -3}, {1}}, // outside
2689 {0, -1, {0, 1}, {1}}, // inside
2690 {0, -1, {0, 3}, {1}} // outside
2691 };
2692 MeshSpecification shouldTagFirstRound = {
2693 {0, -1, {-1, 0}, {1}},
2694 {0, -1, {1, 0}, {1}},
2695 {0, -1, {0, -1}, {1}},
2696 {0, -1, {0, 1}, {1}}};
2697 // No tagging happening in round two
2698 MeshSpecification shouldTagSecondRound;
2699
2700 testTagging(context, inMeshSpec, outMeshSpec, shouldTagFirstRound, shouldTagSecondRound, true);
2701 // For conservative just swap meshes.
2702 testTagging(context, outMeshSpec, inMeshSpec, shouldTagFirstRound, shouldTagSecondRound, false);
2703}
2704
2705BOOST_AUTO_TEST_SUITE_END() // Parallel
2706
BOOST_AUTO_TEST_CASE(testIQNIMVJPPWithSubsteps)
BOOST_AUTO_TEST_SUITE(PreProcess)
BOOST_AUTO_TEST_SUITE_END()
void testTagging(const TestContext &context, MeshSpecification inMeshSpec, MeshSpecification outMeshSpec, MeshSpecification shouldTagFirstRound, MeshSpecification shouldTagSecondRound, bool consistent)
void addGlobalIndex(mesh::PtrMesh &mesh, int offset=0)
void perform2DTestConservativeMappingVector(Mapping &mapping)
void perform3DTestConsistentMappingVector(Mapping &mapping)
void perform2DTestConsistentMappingVector(Mapping &mapping)
void perform2DTestConsistentMapping(Mapping &mapping)
void perform2DTestJustInTimeMappingConservative(Mapping &mapping)
std::vector< std::pair< int, std::vector< double > > > ReferenceSpecification
Contains which values are expected on which rank: rank -> vector of data.
void perform3DTestConsistentMapping(Mapping &mapping)
void testDistributed(const TestContext &context, Mapping &mapping, MeshSpecification inMeshSpec, MeshSpecification outMeshSpec, ReferenceSpecification referenceSpec, int inGlobalIndexOffset=0, bool meshIsSmaller=false)
double sumComponentWise(const Eigen::VectorXd &vec, int component, int dataDimension)
void perform3DTestConservativeMapping(Mapping &mapping)
void performReferenceTesting(Mapping &testMapping, Mapping &referenceMapping, int dim, int nComponents)
void perform3DTestJustInTimeMappingConservative(Mapping &mapping)
void perform2DTestConservativeMapping(Mapping &mapping)
void perform3DTestConservativeMappingVector(Mapping &mapping)
void perform2DTestJustInTimeMappingNoPolynomial(Mapping &mapping)
void perform3DTestJustInTimeMappingWithPolynomial(Mapping &mapping)
#define TEST_CPU_REFERENCE_FOR_SPD_RBFS(EXECUTOR)
void getDistributedMesh(const TestContext &context, MeshSpecification const &vertices, mesh::PtrMesh &mesh, mesh::PtrData &data, int globalIndexOffset=0, bool meshIsSmaller=false)
#define TEST_EXECUTOR_UNIT(EXECUTOR)
void performTestConsistentMapDeadAxis(Mapping &mapping, int dim)
#define PRECICE_TEST()
Definition Testing.hpp:39
#define PRECICE_TEST_SETUP(...)
Creates and attaches a TestSetup to a Boost test case.
Definition Testing.hpp:29
#define PRECICE_ASSERT(...)
Definition assertion.hpp:85
Utility class for managing MPI operations.
Definition Parallel.hpp:24
Wendland radial basis function with compact support.
Wendland radial basis function with compact support.
Wendland radial basis function with compact support.
Wendland radial basis function with compact support.
Abstract base class for mapping of data from one mesh to another.
Definition Mapping.hpp:16
Constraint
Specifies additional constraints for a mapping.
Definition Mapping.hpp:30
virtual void clear()=0
Removes a computed mapping.
void setMeshes(const mesh::PtrMesh &input, const mesh::PtrMesh &output)
Sets input and output meshes carrying data to be mapped.
Definition Mapping.cpp:28
Constraint getConstraint() const
Returns the constraint (consistent/conservative) of the mapping.
Definition Mapping.cpp:46
virtual void computeMapping()=0
Computes the mapping coefficients from the in- and output mesh.
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
DataID getID() const
Returns the ID of the data set (supposed to be unique).
Definition Data.cpp:144
Eigen::VectorXd & values()
Returns a reference to the data values.
Definition Data.cpp:52
static mesh::PtrMesh getJustInTimeMappingMesh(int dimension)
Container and creator for meshes.
Definition Mesh.hpp:38
void setGlobalNumberOfVertices(int num)
Definition Mesh.hpp:278
VertexContainer & vertices()
Returns modifieable container holding all vertices.
Definition Mesh.cpp:55
std::size_t nVertices() const
Returns the number of vertices.
Definition Mesh.cpp:65
const query::Index & index() const
Call preprocess() before index() to ensure correct projection handling.
Definition Mesh.hpp:329
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
void computeBoundingBox()
Computes the boundingBox for the vertices.
Definition Mesh.cpp:267
Vertex & createVertex(const Eigen::Ref< const Eigen::VectorXd > &coords)
Creates and initializes a Vertex object.
Definition Mesh.cpp:105
void allocateDataValues()
Allocates memory for the vertex data values and corresponding gradient values.
Definition Mesh.cpp:258
Vertex of a mesh.
Definition Vertex.hpp:16
void setCoords(const VECTOR_T &coordinates)
Sets the coordinates of the vertex.
Definition Vertex.hpp:103
void clear()
Clear the index.
Definition Index.cpp:393
Rank rank
the rank of the current participant
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.
provides Mesh, Data and primitives.
std::shared_ptr< Data > PtrData
std::shared_ptr< Mesh > PtrMesh
contains the testing framework.
Definition helper.hpp:9
Main namespace of the precice library.
int DataID
Definition Types.hpp:25
Holds rank, owner, position and value of a single vertex.
bool hasDataAtTimeStamp(double time) const
Check, if the current data vector (in inData or the std::vectors) hold data of time time.
void setTimeStamp(double time)
Set the timestamp of the MappingDataCache to the specified time.
void resetData()
Reset all data containers to zero.
void resetTimeStamp()
Reset the time stamp associated with the data.