preCICE v3.2.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ExplicitCouplingSchemeTest.cpp
Go to the documentation of this file.
1#include <Eigen/Core>
2#include <algorithm>
3#include <cmath>
4#include <memory>
5#include <string>
6#include <vector>
14#include "m2n/M2N.hpp"
15#include "m2n/SharedPointer.hpp"
17#include "math/differences.hpp"
18#include "mesh/Data.hpp"
19#include "mesh/Mesh.hpp"
21#include "mesh/Vertex.hpp"
26#include "testing/Testing.hpp"
27#include "xml/XMLTag.hpp"
28
29using namespace precice;
30using namespace precice::cplscheme;
31
32#ifndef PRECICE_NO_MPI
33
34BOOST_AUTO_TEST_SUITE(CplSchemeTests)
35
37 CouplingScheme &cplScheme,
38 const std::string &participantName,
39 const mesh::MeshConfiguration &meshConfig)
40{
41 BOOST_TEST(meshConfig.meshes().size() == 1);
42 mesh::PtrMesh mesh = meshConfig.meshes().at(0);
43 BOOST_TEST(mesh->data().size() == 2);
44 auto &dataValues0 = mesh->data(0)->values();
45 auto &dataValues1 = mesh->data(1)->values();
46 BOOST_TEST(mesh->nVertices() > 0);
47 mesh::Vertex &vertex = mesh->vertex(0);
48 double valueData0 = 1.0;
49 Eigen::VectorXd valueData1 = Eigen::VectorXd::Constant(3, 1.0);
50
51 double computedTime = 0.0;
52 int computedTimesteps = 0;
53
54 if (participantName == std::string("Participant0")) {
55 mesh->data(0)->setSampleAtTime(0, time::Sample{mesh->data(0)->getDimensions(), mesh->data(0)->values()});
56 cplScheme.initialize();
57 BOOST_TEST(not cplScheme.hasDataBeenReceived());
58 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::WriteCheckpoint));
59 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::ReadCheckpoint));
60 BOOST_TEST(not cplScheme.isTimeWindowComplete());
61 BOOST_TEST(cplScheme.isCouplingOngoing());
62 while (cplScheme.isCouplingOngoing()) {
63 dataValues0(vertex.getID()) = valueData0;
64 BOOST_TEST(cplScheme.getNextTimeStepMaxSize() > 0.0);
65 computedTime += cplScheme.getNextTimeStepMaxSize();
66 computedTimesteps++;
67 cplScheme.addComputedTime(cplScheme.getNextTimeStepMaxSize());
68 mesh->data(0)->setSampleAtTime(cplScheme.getTime(), time::Sample{mesh->data(0)->getDimensions(), mesh->data(0)->values()});
69 cplScheme.firstSynchronization({});
70 cplScheme.firstExchange();
71 cplScheme.secondSynchronization();
72 cplScheme.secondExchange();
73 BOOST_TEST(cplScheme.isTimeWindowComplete());
74 BOOST_TEST(testing::equals(computedTime, cplScheme.getTime()));
75 BOOST_TEST(computedTimesteps == cplScheme.getTimeWindows() - 1);
76 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::WriteCheckpoint));
77 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::ReadCheckpoint));
78 BOOST_TEST(cplScheme.isTimeWindowComplete());
79 if (cplScheme.isCouplingOngoing()) {
80 // No receive takes place for the participant that has started the
81 // coupled simulation, in the last advance call
82 Eigen::VectorXd value = dataValues1.segment(vertex.getID() * 3, 3);
83 BOOST_TEST(testing::equals(value, valueData1));
84 }
85 BOOST_TEST(cplScheme.hasDataBeenReceived());
86 // Increment data values, to test if send/receive operations are also
87 // correct in following timesteps.
88 valueData0 += 1.0;
89 valueData1 += Eigen::VectorXd::Constant(3, 1.0);
90 }
91 cplScheme.finalize();
92 // Validate results
93 BOOST_TEST(testing::equals(computedTime, 1.0));
94 BOOST_TEST(computedTimesteps == 10);
95 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::WriteCheckpoint));
96 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::ReadCheckpoint));
97 BOOST_TEST(cplScheme.isTimeWindowComplete());
98 BOOST_TEST(not cplScheme.isCouplingOngoing());
99 BOOST_TEST(cplScheme.getNextTimeStepMaxSize() == 0.0);
100 } else if (participantName == std::string("Participant1")) {
101 mesh->data(1)->setSampleAtTime(0, time::Sample{mesh->data(1)->getDimensions(), mesh->data(1)->values()});
102 cplScheme.initialize();
103 BOOST_TEST(cplScheme.hasDataBeenReceived());
104 double value = dataValues0(vertex.getID());
105 BOOST_TEST(testing::equals(value, valueData0));
106 valueData0 += 1.0;
107 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::WriteCheckpoint));
108 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::ReadCheckpoint));
109 BOOST_TEST(not cplScheme.isTimeWindowComplete());
110 BOOST_TEST(cplScheme.isCouplingOngoing());
111 while (cplScheme.isCouplingOngoing()) {
112 dataValues1.segment(vertex.getID() * 3, 3) = valueData1;
113 BOOST_TEST(cplScheme.getNextTimeStepMaxSize() > 0.0);
114 computedTime += cplScheme.getNextTimeStepMaxSize();
115 computedTimesteps++;
116 cplScheme.addComputedTime(cplScheme.getNextTimeStepMaxSize());
117 mesh->data(1)->setSampleAtTime(cplScheme.getTime(), time::Sample{mesh->data(1)->getDimensions(), mesh->data(1)->values()});
118 cplScheme.firstSynchronization({});
119 cplScheme.firstExchange();
120 cplScheme.secondSynchronization();
121 cplScheme.secondExchange();
122 BOOST_TEST(testing::equals(computedTime, cplScheme.getTime()));
123 BOOST_TEST(computedTimesteps == cplScheme.getTimeWindows() - 1);
124 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::WriteCheckpoint));
125 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::ReadCheckpoint));
126 BOOST_TEST(cplScheme.isTimeWindowComplete());
127 if (cplScheme.isCouplingOngoing()) {
128 // The participant not starting the coupled simulation does neither
129 // receive nor send data in the last call to advance
130 BOOST_TEST(cplScheme.hasDataBeenReceived());
131 double value = dataValues0(vertex.getID());
132 BOOST_TEST(testing::equals(value, valueData0));
133 }
134 valueData0 += 1.0;
135 valueData1 += Eigen::VectorXd::Constant(3, 1.0);
136 }
137 cplScheme.finalize();
138 // Validate results
139 BOOST_TEST(testing::equals(computedTime, 1.0));
140 BOOST_TEST(computedTimesteps == 10);
141 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::WriteCheckpoint));
142 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::ReadCheckpoint));
143 BOOST_TEST(cplScheme.isTimeWindowComplete());
144 BOOST_TEST(not cplScheme.isCouplingOngoing());
145 BOOST_TEST(cplScheme.getNextTimeStepMaxSize() == 0.0);
146 }
147}
148
150 CouplingScheme &cplScheme,
151 const std::string &participantName,
152 const mesh::MeshConfiguration &meshConfig)
153{
154 BOOST_TEST(meshConfig.meshes().size() == 1);
155 mesh::PtrMesh mesh = meshConfig.meshes().at(0);
156 BOOST_TEST(mesh->data().size() == 2);
157 BOOST_TEST(mesh->nVertices() > 0);
158 mesh::Vertex &vertex = mesh->vertex(0);
159 double valueData0 = 1.0;
160 Eigen::VectorXd valueData1 = Eigen::VectorXd::Constant(3, 1.0);
161 auto &dataValues0 = mesh->data(0)->values();
162 auto &dataValues1 = mesh->data(1)->values();
163
164 double computedTime = 0.0;
165 int computedTimesteps = 0;
166 std::string nameParticipant0("Participant0");
167 std::string nameParticipant1("Participant1");
168 BOOST_TEST(((participantName == nameParticipant0) || (participantName == nameParticipant1)));
169 if (participantName == nameParticipant0) {
170 mesh->data(0)->setSampleAtTime(0, time::Sample{mesh->data(0)->getDimensions(), mesh->data(0)->values()});
171 cplScheme.initialize();
172 mesh->data(0)->timeStepsStorage().trim();
173 double dtDesired = cplScheme.getNextTimeStepMaxSize() / 2.0;
174 double dtUsed = dtDesired;
175 BOOST_TEST(not cplScheme.hasDataBeenReceived());
176 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::WriteCheckpoint));
177 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::ReadCheckpoint));
178 BOOST_TEST(not cplScheme.isTimeWindowComplete());
179 BOOST_TEST(cplScheme.isCouplingOngoing());
180 while (cplScheme.isCouplingOngoing()) {
181 // If the dt from preCICE is larger than the desired one, do subcycling,
182 // else, use the dt from preCICE
183 BOOST_TEST(cplScheme.getNextTimeStepMaxSize() > 0.0);
184 dtUsed = cplScheme.getNextTimeStepMaxSize() > dtDesired
185 ? dtDesired
186 : cplScheme.getNextTimeStepMaxSize();
187 BOOST_TEST(testing::equals(computedTime, cplScheme.getTime()));
188 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::WriteCheckpoint));
189 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::ReadCheckpoint));
190 dataValues0(vertex.getID()) = valueData0;
191 computedTime += dtUsed;
192 computedTimesteps++;
193 cplScheme.addComputedTime(dtUsed);
194 mesh->data(0)->setSampleAtTime(cplScheme.getTime(), time::Sample{mesh->data(0)->getDimensions(), mesh->data(0)->values()});
195 cplScheme.firstSynchronization({});
196 cplScheme.firstExchange();
197 cplScheme.secondSynchronization();
198 cplScheme.secondExchange();
199 if (computedTimesteps % 2 == 0) {
200 // Data exchange takes only place at every second local timestep,
201 // since a subcycling of 2 is used.
202 BOOST_TEST(cplScheme.isTimeWindowComplete());
203 if (cplScheme.isCouplingOngoing()) {
204 // No receive takes place for the participant that has started the
205 // coupled simulation, in the last advance call.
206 Eigen::VectorXd value = dataValues1.segment(vertex.getID() * 3, 3);
207 BOOST_TEST(testing::equals(value, valueData1));
208 }
209 BOOST_TEST(cplScheme.hasDataBeenReceived());
210 // Increment data values, to test if send/receive operations are also
211 // correct in following timesteps.
212 valueData0 += 1.0;
213 valueData1 += Eigen::VectorXd::Constant(3, 1.0);
214 mesh->data(0)->timeStepsStorage().trim();
215 } else {
216 BOOST_TEST(not cplScheme.isTimeWindowComplete());
217 }
218 }
219 cplScheme.finalize();
220 BOOST_TEST(testing::equals(computedTime, 1.0));
221 BOOST_TEST(computedTimesteps == 20);
222 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::WriteCheckpoint));
223 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::ReadCheckpoint));
224 BOOST_TEST(cplScheme.isTimeWindowComplete());
225 BOOST_TEST(not cplScheme.isCouplingOngoing());
226 BOOST_TEST(cplScheme.getNextTimeStepMaxSize() == 0.0);
227 } else if (participantName == nameParticipant1) {
228 // Start coupling
229 mesh->data(1)->setSampleAtTime(0, time::Sample{mesh->data(1)->getDimensions(), mesh->data(1)->values()});
230 cplScheme.initialize();
231 BOOST_TEST(cplScheme.hasDataBeenReceived());
232 // Validate current coupling status
233 BOOST_TEST(testing::equals(dataValues0(vertex.getID()), valueData0));
234 valueData0 += 1.0;
235 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::WriteCheckpoint));
236 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::ReadCheckpoint));
237 BOOST_TEST(not cplScheme.isTimeWindowComplete());
238 BOOST_TEST(cplScheme.isCouplingOngoing());
239 while (cplScheme.isCouplingOngoing()) {
240 dataValues1.segment(vertex.getID() * 3, 3) = valueData1;
241 BOOST_TEST(cplScheme.getNextTimeStepMaxSize() > 0.0);
242 computedTime += cplScheme.getNextTimeStepMaxSize();
243 computedTimesteps++;
244 cplScheme.addComputedTime(cplScheme.getNextTimeStepMaxSize());
245 mesh->data(1)->setSampleAtTime(cplScheme.getTime(), time::Sample{mesh->data(1)->getDimensions(), mesh->data(1)->values()});
246 cplScheme.firstSynchronization({});
247 cplScheme.firstExchange();
248 cplScheme.secondSynchronization();
249 cplScheme.secondExchange();
250 BOOST_TEST(testing::equals(computedTime, cplScheme.getTime()));
251 BOOST_TEST(computedTimesteps == cplScheme.getTimeWindows() - 1);
252 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::WriteCheckpoint));
253 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::ReadCheckpoint));
254 BOOST_TEST(cplScheme.isTimeWindowComplete());
255 if (cplScheme.isCouplingOngoing()) {
256 // The participant not starting the coupled simulation does neither
257 // receive nor send data in the last call to advance
258 BOOST_TEST(cplScheme.hasDataBeenReceived());
259 BOOST_TEST(testing::equals(dataValues0(vertex.getID()), valueData0));
260 BOOST_TEST(cplScheme.hasDataBeenReceived());
261 }
262 valueData0 += 1.0;
263 valueData1 += Eigen::VectorXd::Constant(3, 1.0);
264 }
265 cplScheme.finalize();
266 BOOST_TEST(testing::equals(computedTime, 1.0));
267 BOOST_TEST(computedTimesteps == 10);
268 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::WriteCheckpoint));
269 BOOST_TEST(not cplScheme.isActionRequired(CouplingScheme::Action::ReadCheckpoint));
270 BOOST_TEST(cplScheme.isTimeWindowComplete());
271 BOOST_TEST(not cplScheme.isCouplingOngoing());
272 BOOST_TEST(cplScheme.getNextTimeStepMaxSize() == 0.0);
273 }
274}
275
278
280 {
281 _pathToTests = testing::getPathToSources() + "/cplscheme/tests/";
282 }
283
285 const std::string &participant0,
286 const std::string &participant1,
287 const std::string &localParticipant,
288 m2n::PtrM2N &communication)
289 {
290 BOOST_TEST(communication);
291 BOOST_TEST(not communication->isConnected());
292 useOnlyPrimaryCom(communication) = true;
293 if (participant0 == localParticipant) {
294 communication->requestPrimaryRankConnection(participant1, participant0, "");
295 } else {
296 BOOST_TEST(participant1 == localParticipant);
297 communication->acceptPrimaryRankConnection(participant1, participant0, "");
298 }
299 }
300};
301
302BOOST_FIXTURE_TEST_SUITE(ExplicitCouplingSchemeTests, ExplicitCouplingSchemeFixture)
303
304
305
306PRECICE_TEST_SETUP("Participant0"_on(1_rank), "Participant1"_on(1_rank), Require::Events)
307BOOST_AUTO_TEST_CASE(testSimpleExplicitCoupling)
308{
309 PRECICE_TEST();
311 options.useOnlyPrimaryCom = true;
312 auto m2n = context.connectPrimaryRanks("Participant0", "Participant1", options);
313
316 dataConfig->addData("Data0", mesh::Data::typeName::SCALAR);
317 dataConfig->addData("Data1", mesh::Data::typeName::VECTOR);
318 mesh::MeshConfiguration meshConfig(root, dataConfig);
319 mesh::PtrMesh mesh(new mesh::Mesh("Mesh", 3, testing::nextMeshID()));
320 mesh->createData("Data0", 1, 0_dataID);
321 mesh->createData("Data1", 3, 1_dataID);
322 mesh->createVertex(Eigen::Vector3d::Zero());
323 mesh->allocateDataValues();
324 meshConfig.insertMeshToMeshDimensionsMap(mesh->getName(), mesh->getDimensions());
325 meshConfig.addMesh(mesh);
326
327 const double maxTime = 1.0;
328 const int maxTimeWindows = 10;
329 const double timeWindowSize = 0.1;
330 std::string nameParticipant0("Participant0");
331 std::string nameParticipant1("Participant1");
332 int sendDataIndex = -1;
333 int receiveDataIndex = -1;
334
335 if (context.isNamed(nameParticipant0)) {
336 sendDataIndex = 0;
337 receiveDataIndex = 1;
338 } else {
339 sendDataIndex = 1;
340 receiveDataIndex = 0;
341 }
342 cplscheme::SerialCouplingScheme cplScheme(maxTime, maxTimeWindows, timeWindowSize, nameParticipant0, nameParticipant1, context.name, m2n, constants::FIXED_TIME_WINDOW_SIZE, BaseCouplingScheme::Explicit);
343 cplScheme.addDataToSend(mesh->data(sendDataIndex), mesh, false, true);
344 cplScheme.addDataToReceive(mesh->data(receiveDataIndex), mesh, false, true);
346 runSimpleExplicitCoupling(cplScheme, context.name, meshConfig);
347}
348
350PRECICE_TEST_SETUP("Participant0"_on(1_rank), "Participant1"_on(1_rank), Require::Events)
351BOOST_AUTO_TEST_CASE(testConfiguredSimpleExplicitCoupling)
352{
353 PRECICE_TEST();
354
355 using namespace mesh;
356
357 std::string configurationPath(_pathToTests + "explicit-coupling-scheme-1.xml");
358 std::string nameParticipant0("Participant0");
359 std::string nameParticipant1("Participant1");
360
362 PtrDataConfiguration dataConfig(new DataConfiguration(root));
363 PtrMeshConfiguration meshConfig(new MeshConfiguration(root, dataConfig));
366 CouplingSchemeConfiguration cplSchemeConfig(root, meshConfig, m2nConfig, participantConfig);
367
368 xml::ConfigurationContext ccontext{context.name, 0, 1};
369 xml::configure(root, ccontext, configurationPath);
370 m2n::PtrM2N m2n = m2nConfig->getM2N(nameParticipant0, nameParticipant1);
371
372 // some dummy mesh
373 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(1.0, 1.0, 1.0));
374 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(2.0, 1.0, -1.0));
375 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(3.0, 1.0, 1.0));
376 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(4.0, 1.0, -1.0));
377 meshConfig->meshes().at(0)->allocateDataValues();
378
379 connect(nameParticipant0, nameParticipant1, context.name, m2n);
380 runSimpleExplicitCoupling(*cplSchemeConfig.getCouplingScheme(context.name),
381 context.name, *meshConfig);
382}
383
385PRECICE_TEST_SETUP("Participant0"_on(1_rank), "Participant1"_on(1_rank), Require::Events)
386BOOST_AUTO_TEST_CASE(testExplicitCouplingFirstParticipantSetsDt)
387{
388 PRECICE_TEST();
389
390 using namespace mesh;
391 std::string configurationPath(_pathToTests + "explicit-coupling-scheme-2.xml");
392 std::string nameParticipant0("Participant0");
393 std::string nameParticipant1("Participant1");
394
396 PtrDataConfiguration dataConfig(new DataConfiguration(root));
397 PtrMeshConfiguration meshConfig(new MeshConfiguration(root, dataConfig));
400 CouplingSchemeConfiguration cplSchemeConfig(root, meshConfig, m2nConfig, participantConfig);
401
402 xml::ConfigurationContext ccontext{context.name, 0, 1};
403 xml::configure(root, ccontext, configurationPath);
404 m2n::PtrM2N m2n = m2nConfig->getM2N(nameParticipant0, nameParticipant1);
405
406 // some dummy mesh
407 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(1.0, 1.0, 1.0));
408 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(2.0, 1.0, -1.0));
409 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(3.0, 1.0, 1.0));
410 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(4.0, 1.0, -1.0));
411 meshConfig->meshes().at(0)->allocateDataValues();
412
413 connect(nameParticipant0, nameParticipant1, context.name, m2n);
414 CouplingScheme &cplScheme = *cplSchemeConfig.getCouplingScheme(context.name);
415
416 double computedTime = 0.0;
417 double maxTime = 1.0; // from max-time
418 int computedTimesteps = 0;
419
420 mesh::PtrMesh mesh = meshConfig->meshes().at(0);
421
422 if (context.isNamed(nameParticipant0)) {
423 double solverDt = 0.3;
424 double preciceDt, dt;
425 mesh->data(0)->setSampleAtTime(0, time::Sample{mesh->data(0)->getDimensions(), mesh->data(0)->values()});
426 cplScheme.initialize();
427 BOOST_TEST(not cplScheme.hasDataBeenReceived());
428 BOOST_TEST(cplScheme.getNextTimeStepMaxSize() == 1);
429 BOOST_TEST(not cplScheme.hasDataBeenReceived());
430 BOOST_TEST(not cplScheme.isTimeWindowComplete());
431 BOOST_TEST(cplScheme.isCouplingOngoing());
432 while (cplScheme.isCouplingOngoing()) {
433 preciceDt = cplScheme.getNextTimeStepMaxSize();
434 dt = std::min({solverDt, preciceDt});
435 mesh->data(0)->setSampleAtTime(computedTime + dt, time::Sample{mesh->data(0)->getDimensions(), mesh->data(0)->values()});
436 cplScheme.addComputedTime(dt);
437 computedTime += dt;
438 computedTimesteps++;
439 cplScheme.firstSynchronization({});
440 cplScheme.firstExchange();
441 cplScheme.secondSynchronization();
442 cplScheme.secondExchange();
443 BOOST_TEST(cplScheme.isTimeWindowComplete());
444 BOOST_TEST(testing::equals(computedTime, cplScheme.getTime()));
445 BOOST_TEST(computedTimesteps == cplScheme.getTimeWindows() - 1);
446 if (cplScheme.isCouplingOngoing()) {
447 BOOST_TEST(cplScheme.hasDataBeenReceived());
448 }
449 }
450 cplScheme.finalize();
451 BOOST_TEST(testing::equals(computedTime, maxTime));
452 BOOST_TEST(computedTimesteps == 4);
453 BOOST_TEST(cplScheme.isTimeWindowComplete());
454 BOOST_TEST(not cplScheme.isCouplingOngoing());
455 } else {
456 BOOST_TEST(context.isNamed(nameParticipant1));
457 mesh->data(1)->setSampleAtTime(0, time::Sample{mesh->data(1)->getDimensions(), mesh->data(1)->values()});
458 cplScheme.initialize();
459 BOOST_TEST(cplScheme.hasDataBeenReceived());
460 BOOST_TEST(not cplScheme.isTimeWindowComplete());
461 BOOST_TEST(cplScheme.isCouplingOngoing());
462 while (cplScheme.isCouplingOngoing()) {
463 mesh->data(1)->setSampleAtTime(computedTime + cplScheme.getTimeWindowSize(), time::Sample{mesh->data(1)->getDimensions(), mesh->data(1)->values()});
464 cplScheme.addComputedTime(cplScheme.getTimeWindowSize());
465 computedTime += cplScheme.getTimeWindowSize();
466 computedTimesteps++;
467 cplScheme.firstSynchronization({});
468 cplScheme.firstExchange();
469 cplScheme.secondSynchronization();
470 cplScheme.secondExchange();
471 BOOST_TEST(cplScheme.isTimeWindowComplete());
472 BOOST_TEST(testing::equals(computedTime, cplScheme.getTime()));
473 BOOST_TEST(computedTimesteps == cplScheme.getTimeWindows() - 1);
474 if (cplScheme.isCouplingOngoing()) {
475 BOOST_TEST(cplScheme.hasDataBeenReceived());
476 }
477 }
478 cplScheme.finalize();
479 BOOST_TEST(testing::equals(computedTime, maxTime));
480 BOOST_TEST(computedTimesteps == 4);
481 BOOST_TEST(cplScheme.isTimeWindowComplete());
482 BOOST_TEST(not cplScheme.isCouplingOngoing());
483 }
484}
485
492PRECICE_TEST_SETUP("Participant0"_on(1_rank), "Participant1"_on(1_rank), Require::Events)
493BOOST_AUTO_TEST_CASE(testSerialDataInitialization)
494{
495 PRECICE_TEST();
496
497 using namespace mesh;
498
499 std::string configurationPath(_pathToTests + "serial-explicit-coupling-datainit.xml");
500 std::string nameParticipant0("Participant0");
501 std::string nameParticipant1("Participant1");
502
504 PtrDataConfiguration dataConfig(new DataConfiguration(root));
505 PtrMeshConfiguration meshConfig(new MeshConfiguration(root, dataConfig));
508 CouplingSchemeConfiguration cplSchemeConfig(root, meshConfig, m2nConfig, participantConfig);
509
510 xml::ConfigurationContext ccontext{context.name, 0, 1};
511 xml::configure(root, ccontext, configurationPath);
512 m2n::PtrM2N m2n = m2nConfig->getM2N(nameParticipant0, nameParticipant1);
513
514 // some dummy mesh
515 meshConfig->meshes().at(0)->createVertex(Eigen::Vector2d(1.0, 1.0));
516 meshConfig->meshes().at(0)->createVertex(Eigen::Vector2d(2.0, -1.0));
517 meshConfig->meshes().at(0)->createVertex(Eigen::Vector2d(3.0, 1.0));
518 meshConfig->meshes().at(0)->createVertex(Eigen::Vector2d(4.0, -1.0));
519 meshConfig->meshes().at(0)->allocateDataValues();
520
521 connect(nameParticipant0, nameParticipant1, context.name, m2n);
522 CouplingScheme &cplScheme = *cplSchemeConfig.getCouplingScheme(context.name);
523 BOOST_TEST(cplScheme.isActionRequired(CouplingScheme::Action::InitializeData));
524
525 BOOST_TEST(meshConfig->meshes().size() == 1);
526 mesh::PtrMesh mesh = meshConfig->meshes().at(0);
527 BOOST_TEST(mesh->data().size() == 3);
528 auto &dataValues0 = mesh->data(0)->values();
529 auto &dataValues1 = mesh->data(1)->values();
530 auto &dataValues2 = mesh->data(2)->values();
531
532 BOOST_TEST(mesh->data(0)->getName() == "Data0");
533 BOOST_TEST(mesh->data(1)->getName() == "Data1");
534 BOOST_TEST(mesh->data(2)->getName() == "Data2");
535
536 if (context.isNamed(nameParticipant0)) {
537 BOOST_TEST(cplScheme.isActionRequired(CouplingScheme::Action::InitializeData));
538 dataValues2(0) = 3.0;
539 cplScheme.markActionFulfilled(CouplingScheme::Action::InitializeData);
540 BOOST_TEST(not cplScheme.hasDataBeenReceived());
541 mesh->data(2)->setSampleAtTime(0, time::Sample{mesh->data(2)->getDimensions(), mesh->data(2)->values()});
542 cplScheme.initialize();
543 BOOST_TEST(cplScheme.hasDataBeenReceived()); // receives initial data
544 // BOOST_TEST(testing::equals(dataValues0(0), 0.0)); // @todo Should receive 0.0, because Data0 is not initialized. See https://github.com/precice/precice/issues/1693
545 BOOST_TEST(testing::equals(dataValues0(0), 5.0)); // @todo Incorrect due to bug. See https://github.com/precice/precice/issues/1693
546 BOOST_TEST(testing::equals(dataValues1(0), 1.0));
547 dataValues2(0) = 2.0;
548 cplScheme.addComputedTime(cplScheme.getNextTimeStepMaxSize());
549 mesh->data(2)->setSampleAtTime(cplScheme.getTime(), time::Sample{mesh->data(2)->getDimensions(), mesh->data(2)->values()});
550 cplScheme.firstSynchronization({});
551 cplScheme.firstExchange();
552 cplScheme.secondSynchronization();
553 cplScheme.secondExchange();
554 BOOST_TEST(cplScheme.hasDataBeenReceived());
555 BOOST_TEST(testing::equals(dataValues0(0), 4.0));
556 BOOST_TEST(not cplScheme.isCouplingOngoing());
557 cplScheme.finalize();
558 } else {
559 BOOST_TEST(context.isNamed(nameParticipant1));
560 BOOST_TEST(cplScheme.isActionRequired(CouplingScheme::Action::InitializeData));
561 dataValues0(0) = 5.0; // Data0 is written, but initialization is turned off.
562 dataValues1(0) = 1.0;
563 cplScheme.markActionFulfilled(CouplingScheme::Action::InitializeData);
564 mesh->data(0)->setSampleAtTime(0, time::Sample{mesh->data(0)->getDimensions(), mesh->data(0)->values()});
565 mesh->data(1)->setSampleAtTime(0, time::Sample{mesh->data(1)->getDimensions(), mesh->data(1)->values()});
566 cplScheme.initialize();
567 BOOST_TEST(cplScheme.hasDataBeenReceived()); // receives initial data
568 BOOST_TEST(testing::equals(dataValues2(0), 2.0));
569 dataValues0(0) = 4.0;
570 cplScheme.addComputedTime(cplScheme.getNextTimeStepMaxSize());
571 mesh->data(0)->setSampleAtTime(cplScheme.getTime(), time::Sample{mesh->data(0)->getDimensions(), mesh->data(0)->values()});
572 mesh->data(1)->setSampleAtTime(cplScheme.getTime(), time::Sample{mesh->data(1)->getDimensions(), mesh->data(1)->values()});
573 cplScheme.firstSynchronization({});
574 cplScheme.firstExchange();
575 cplScheme.secondSynchronization();
576 cplScheme.secondExchange();
577 BOOST_TEST(not cplScheme.hasDataBeenReceived()); // first participant did not send any further data
578 BOOST_TEST(not cplScheme.isCouplingOngoing());
579 cplScheme.finalize();
580 }
581}
582
589PRECICE_TEST_SETUP("Participant0"_on(1_rank), "Participant1"_on(1_rank), Require::Events)
590BOOST_AUTO_TEST_CASE(testParallelDataInitialization)
591{
592 PRECICE_TEST();
593
594 using namespace mesh;
595
596 std::string configurationPath(_pathToTests + "parallel-explicit-coupling-datainit.xml");
597 std::string nameParticipant0("Participant0");
598 std::string nameParticipant1("Participant1");
599
601 PtrDataConfiguration dataConfig(new DataConfiguration(root));
602 PtrMeshConfiguration meshConfig(new MeshConfiguration(root, dataConfig));
605 CouplingSchemeConfiguration cplSchemeConfig(root, meshConfig, m2nConfig, participantConfig);
606
607 xml::ConfigurationContext ccontext{context.name, 0, 1};
608 xml::configure(root, ccontext, configurationPath);
609 m2n::PtrM2N m2n = m2nConfig->getM2N(nameParticipant0, nameParticipant1);
610
611 // some dummy mesh
612 meshConfig->meshes().at(0)->createVertex(Eigen::Vector2d(1.0, 1.0));
613 meshConfig->meshes().at(0)->createVertex(Eigen::Vector2d(2.0, -1.0));
614 meshConfig->meshes().at(0)->createVertex(Eigen::Vector2d(3.0, 1.0));
615 meshConfig->meshes().at(0)->createVertex(Eigen::Vector2d(4.0, -1.0));
616 meshConfig->meshes().at(0)->allocateDataValues();
617
618 connect(nameParticipant0, nameParticipant1, context.name, m2n);
619 CouplingScheme &cplScheme = *cplSchemeConfig.getCouplingScheme(context.name);
620 BOOST_TEST(cplScheme.isActionRequired(CouplingScheme::Action::InitializeData));
621
622 BOOST_TEST(meshConfig->meshes().size() == 1);
623 mesh::PtrMesh mesh = meshConfig->meshes().at(0);
624 BOOST_TEST(mesh->data().size() == 3);
625 auto &dataValues0 = mesh->data(0)->values();
626 auto &dataValues1 = mesh->data(1)->values();
627 auto &dataValues2 = mesh->data(2)->values();
628
629 BOOST_TEST(mesh->data(0)->getName() == "Data0");
630 BOOST_TEST(mesh->data(1)->getName() == "Data1");
631 BOOST_TEST(mesh->data(2)->getName() == "Data2");
632
633 if (context.isNamed(nameParticipant0)) {
634 BOOST_TEST(cplScheme.isActionRequired(CouplingScheme::Action::InitializeData));
635 dataValues2(0) = 3.0;
636 cplScheme.markActionFulfilled(CouplingScheme::Action::InitializeData);
637 BOOST_TEST(not cplScheme.hasDataBeenReceived());
638 mesh->data(2)->setSampleAtTime(0, time::Sample{mesh->data(2)->getDimensions(), mesh->data(2)->values()});
639 cplScheme.initialize();
640 BOOST_TEST(cplScheme.hasDataBeenReceived()); // receives initial data
641 // BOOST_TEST(testing::equals(dataValues0(0), 0.0)); // @todo Should receive 0.0, because Data0 is not initialized. See https://github.com/precice/precice/issues/1693
642 BOOST_TEST(testing::equals(dataValues0(0), 5.0)); // @todo Incorrect due to bug. See https://github.com/precice/precice/issues/1693
643 BOOST_TEST(testing::equals(dataValues1(0), 1.0));
644 dataValues2(0) = 2.0;
645 cplScheme.addComputedTime(cplScheme.getNextTimeStepMaxSize());
646 mesh->data(2)->setSampleAtTime(cplScheme.getTime(), time::Sample{mesh->data(2)->getDimensions(), mesh->data(2)->values()});
647 cplScheme.firstSynchronization({});
648 cplScheme.firstExchange();
649 cplScheme.secondSynchronization();
650 cplScheme.secondExchange();
651 BOOST_TEST(cplScheme.hasDataBeenReceived());
652 BOOST_TEST(testing::equals(dataValues0(0), 4.0));
653 BOOST_TEST(not cplScheme.isCouplingOngoing());
654 cplScheme.finalize();
655 } else {
656 BOOST_TEST(context.isNamed(nameParticipant1));
657 BOOST_TEST(cplScheme.isActionRequired(CouplingScheme::Action::InitializeData));
658 dataValues0(0) = 5.0; // Data0 is written, but initialization is turned off.
659 dataValues1(0) = 1.0;
660 cplScheme.markActionFulfilled(CouplingScheme::Action::InitializeData);
661 mesh->data(0)->setSampleAtTime(0, time::Sample{mesh->data(0)->getDimensions(), mesh->data(0)->values()});
662 mesh->data(1)->setSampleAtTime(0, time::Sample{mesh->data(1)->getDimensions(), mesh->data(1)->values()});
663 cplScheme.initialize();
664 BOOST_TEST(cplScheme.hasDataBeenReceived()); // receives initial data
665 BOOST_TEST(testing::equals(dataValues2(0), 3.0));
666 dataValues0(0) = 4.0;
667 cplScheme.addComputedTime(cplScheme.getNextTimeStepMaxSize());
668 mesh->data(0)->setSampleAtTime(cplScheme.getTime(), time::Sample{mesh->data(0)->getDimensions(), mesh->data(0)->values()});
669 mesh->data(1)->setSampleAtTime(cplScheme.getTime(), time::Sample{mesh->data(1)->getDimensions(), mesh->data(1)->values()});
670 cplScheme.firstSynchronization({});
671 cplScheme.firstExchange();
672 cplScheme.secondSynchronization();
673 cplScheme.secondExchange();
674 BOOST_TEST(cplScheme.hasDataBeenReceived());
675 BOOST_TEST(testing::equals(dataValues2(0), 2.0));
676 BOOST_TEST(not cplScheme.isCouplingOngoing());
677 cplScheme.finalize();
678 }
679}
680
682PRECICE_TEST_SETUP("Participant0"_on(1_rank), "Participant1"_on(1_rank), Require::Events)
683BOOST_AUTO_TEST_CASE(testExplicitCouplingWithSubcycling)
684{
685 PRECICE_TEST();
687 options.useOnlyPrimaryCom = true;
688 auto m2n = context.connectPrimaryRanks("Participant0", "Participant1", options);
689
692 dataConfig->addData("Data0", mesh::Data::typeName::SCALAR);
693 dataConfig->addData("Data1", mesh::Data::typeName::VECTOR);
694 mesh::MeshConfiguration meshConfig(root, dataConfig);
695 mesh::PtrMesh mesh(new mesh::Mesh("Mesh", 3, testing::nextMeshID()));
696 mesh->createData("Data0", 1, 0_dataID);
697 mesh->createData("Data1", 3, 1_dataID);
698 mesh->createVertex(Eigen::Vector3d::Zero());
699 mesh->allocateDataValues();
700 meshConfig.insertMeshToMeshDimensionsMap(mesh->getName(), mesh->getDimensions());
701 meshConfig.addMesh(mesh);
702
703 const double maxTime = 1.0;
704 const int maxTimeWindows = 10;
705 const double timeWindowSize = 0.1;
706 std::string nameParticipant0("Participant0");
707 std::string nameParticipant1("Participant1");
708 int sendDataIndex = -1;
709 int receiveDataIndex = -1;
710 if (context.isNamed(nameParticipant0)) {
711 sendDataIndex = 0;
712 receiveDataIndex = 1;
713 } else {
714 sendDataIndex = 1;
715 receiveDataIndex = 0;
716 }
717 cplscheme::SerialCouplingScheme cplScheme(maxTime, maxTimeWindows, timeWindowSize, nameParticipant0, nameParticipant1, context.name, m2n, constants::FIXED_TIME_WINDOW_SIZE, BaseCouplingScheme::Explicit);
718 cplScheme.addDataToSend(mesh->data(sendDataIndex), mesh, false, true);
719 cplScheme.addDataToReceive(mesh->data(receiveDataIndex), mesh, false, true);
720 cplScheme.determineInitialDataExchange();
721 runExplicitCouplingWithSubcycling(cplScheme, context.name, meshConfig);
722}
723
725PRECICE_TEST_SETUP("Participant0"_on(1_rank), "Participant1"_on(1_rank), Require::Events)
726BOOST_AUTO_TEST_CASE(testConfiguredExplicitCouplingWithSubcycling)
727{
728 PRECICE_TEST();
729
730 using namespace mesh;
731
732 std::string configurationPath(_pathToTests + "explicit-coupling-scheme-1.xml");
733 std::string nameParticipant0("Participant0");
734 std::string nameParticipant1("Participant1");
735
737 PtrDataConfiguration dataConfig(new DataConfiguration(root));
738 PtrMeshConfiguration meshConfig(new MeshConfiguration(root, dataConfig));
741 CouplingSchemeConfiguration cplSchemeConfig(root, meshConfig, m2nConfig, participantConfig);
742
743 xml::ConfigurationContext ccontext{context.name, 0, 1};
744 xml::configure(root, ccontext, configurationPath);
745 m2n::PtrM2N m2n = m2nConfig->getM2N(nameParticipant0, nameParticipant1);
746 // some dummy mesh
747 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(1.0, 1.0, 1.0));
748 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(2.0, -1.0, 1.0));
749 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(3.0, 1.0, 1.0));
750 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(4.0, -1.0, 1.0));
751 meshConfig->meshes().at(0)->allocateDataValues();
752
753 connect(nameParticipant0, nameParticipant1, context.name, m2n);
755 *cplSchemeConfig.getCouplingScheme(context.name), context.name,
756 *meshConfig);
757}
758
761
762#endif // not PRECICE_NO_MPI
BOOST_AUTO_TEST_CASE(testIQNIMVJPPWithSubsteps)
void runSimpleExplicitCoupling(CouplingScheme &cplScheme, const std::string &participantName, const mesh::MeshConfiguration &meshConfig)
void runExplicitCouplingWithSubcycling(CouplingScheme &cplScheme, const std::string &participantName, const mesh::MeshConfiguration &meshConfig)
BOOST_AUTO_TEST_SUITE(PreProcess)
BOOST_AUTO_TEST_SUITE_END()
#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
Performs XML configuration of a participant.
void addDataToReceive(const mesh::PtrData &data, mesh::PtrMesh mesh, bool requiresInitialization, bool exchangeSubsteps)
Adds data to be received on data exchange.
void addDataToSend(const mesh::PtrData &data, mesh::PtrMesh mesh, bool requiresInitialization, bool exchangeSubsteps)
Adds data to be sent on data exchange and possibly be modified during coupling iterations.
void determineInitialDataExchange() override
Determines which data is initialized and therefore has to be exchanged during initialize.
Interface for all coupling schemes.
virtual void initialize()=0
Initializes the coupling scheme and establishes a communication connection to the coupling partner....
virtual ChangedMeshes firstSynchronization(const ChangedMeshes &changes)=0
virtual bool addComputedTime(double timeToAdd)=0
Adds newly computed time. Has to be called before every advance.
virtual double getTime() const =0
Returns the currently computed time of the coupling scheme.
virtual ChangedMeshes secondSynchronization()=0
virtual void markActionFulfilled(Action action)=0
Tells the coupling scheme that the accessor has performed the given action.
virtual double getNextTimeStepMaxSize() const =0
Returns the maximal size of the next time step to be computed.
virtual bool isTimeWindowComplete() const =0
Returns true, when the accessor can advance to the next time window.
virtual double getTimeWindowSize() const =0
Returns the time window size, if one is given by the coupling scheme.
virtual void finalize()=0
Finalizes the coupling and disconnects communication.
virtual bool isCouplingOngoing() const =0
Returns true, when the coupled simulation is still ongoing.
virtual int getTimeWindows() const =0
Returns the currently computed time windows of the coupling scheme.
virtual bool isActionRequired(Action action) const =0
Returns true, if the given action has to be performed by the accessor.
virtual bool hasDataBeenReceived() const =0
Returns true, if data has been exchanged in last call of advance().
Coupling scheme for serial coupling, i.e. staggered execution of two coupled participants.
Configuration for communication channels between solvers.
Performs and provides configuration for Data objects from XML files.
void addMesh(const mesh::PtrMesh &mesh)
void insertMeshToMeshDimensionsMap(const std::string &mesh, int dimensions)
Initialize the map between meshes and dimensions, for unit tests that directly create mesh objects wi...
const std::vector< PtrMesh > & meshes() const
Returns all configured meshes.
Container and creator for meshes.
Definition Mesh.hpp:38
Vertex of a mesh.
Definition Vertex.hpp:16
VertexID getID() const
Returns the unique (among vertices of one mesh on one processor) ID of the vertex.
Definition Vertex.hpp:109
Represents an XML tag to be configured automatically.
Definition XMLTag.hpp:28
T min(T... args)
contains implementations of coupling schemes for coupled simulations.
std::shared_ptr< DataConfiguration > PtrDataConfiguration
std::shared_ptr< MeshConfiguration > PtrMeshConfiguration
boost::test_tools::predicate_result equals(const std::vector< float > &VectorA, const std::vector< float > &VectorB, float tolerance)
equals to be used in tests. Compares two std::vectors using a given tolerance. Prints both operands o...
Definition Testing.cpp:93
std::string getPathToSources()
Returns the base path to the sources.
Definition Testing.cpp:33
XMLTag getRootTag()
Returns an empty root tag with name "configuration".
Definition XMLTag.cpp:278
std::string configure(XMLTag &tag, const precice::xml::ConfigurationContext &context, std::string_view configurationFilename)
Configures the given configuration from file configurationFilename.
Definition XMLTag.cpp:284
Main namespace of the precice library.
STL namespace.
void connect(const std::string &participant0, const std::string &participant1, const std::string &localParticipant, m2n::PtrM2N &communication)
struct giving access _useOnlyPrimaryCom
Definition M2N.hpp:267
static auto useOnlyPrimaryCom(PtrM2N m2n) -> typename std::add_lvalue_reference< decltype(m2n->_useOnlyPrimaryCom)>::type
Definition M2N.hpp:268
Tightly coupled to the parameters of Participant()
Definition XMLTag.hpp:21