preCICE v3.1.1
Loading...
Searching...
No Matches
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(0.0, 1);
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(0.0, 1);
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(0.0, 1);
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(0.0, 1);
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
306BOOST_AUTO_TEST_CASE(testSimpleExplicitCoupling)
307{
308 PRECICE_TEST("Participant0"_on(1_rank), "Participant1"_on(1_rank), Require::Events);
310 options.useOnlyPrimaryCom = true;
311 auto m2n = context.connectPrimaryRanks("Participant0", "Participant1", options);
312
315 dataConfig->addData("Data0", mesh::Data::typeName::SCALAR);
316 dataConfig->addData("Data1", mesh::Data::typeName::VECTOR);
317 mesh::MeshConfiguration meshConfig(root, dataConfig);
318 mesh::PtrMesh mesh(new mesh::Mesh("Mesh", 3, testing::nextMeshID()));
319 mesh->createData("Data0", 1, 0_dataID);
320 mesh->createData("Data1", 3, 1_dataID);
321 mesh->createVertex(Eigen::Vector3d::Zero());
322 mesh->allocateDataValues();
323 meshConfig.insertMeshToMeshDimensionsMap(mesh->getName(), mesh->getDimensions());
324 meshConfig.addMesh(mesh);
325
326 const double maxTime = 1.0;
327 const int maxTimeWindows = 10;
328 const double timeWindowSize = 0.1;
329 const double timeStepSize = timeWindowSize; // solver is not subcycling
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
350BOOST_AUTO_TEST_CASE(testConfiguredSimpleExplicitCoupling)
351{
352 PRECICE_TEST("Participant0"_on(1_rank), "Participant1"_on(1_rank), Require::Events);
353
354 using namespace mesh;
355
356 std::string configurationPath(_pathToTests + "explicit-coupling-scheme-1.xml");
357 std::string nameParticipant0("Participant0");
358 std::string nameParticipant1("Participant1");
359
361 PtrDataConfiguration dataConfig(new DataConfiguration(root));
362 PtrMeshConfiguration meshConfig(new MeshConfiguration(root, dataConfig));
365 CouplingSchemeConfiguration cplSchemeConfig(root, meshConfig, m2nConfig, participantConfig);
366
367 xml::ConfigurationContext ccontext{context.name, 0, 1};
368 xml::configure(root, ccontext, configurationPath);
369 m2n::PtrM2N m2n = m2nConfig->getM2N(nameParticipant0, nameParticipant1);
370
371 // some dummy mesh
372 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(1.0, 1.0, 1.0));
373 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(2.0, 1.0, -1.0));
374 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(3.0, 1.0, 1.0));
375 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(4.0, 1.0, -1.0));
376 meshConfig->meshes().at(0)->allocateDataValues();
377
378 connect(nameParticipant0, nameParticipant1, context.name, m2n);
379 runSimpleExplicitCoupling(*cplSchemeConfig.getCouplingScheme(context.name),
380 context.name, *meshConfig);
381}
382
384BOOST_AUTO_TEST_CASE(testExplicitCouplingFirstParticipantSetsDt)
385{
386 PRECICE_TEST("Participant0"_on(1_rank), "Participant1"_on(1_rank), Require::Events);
387
388 using namespace mesh;
389 std::string configurationPath(_pathToTests + "explicit-coupling-scheme-2.xml");
390 std::string nameParticipant0("Participant0");
391 std::string nameParticipant1("Participant1");
392
394 PtrDataConfiguration dataConfig(new DataConfiguration(root));
395 PtrMeshConfiguration meshConfig(new MeshConfiguration(root, dataConfig));
398 CouplingSchemeConfiguration cplSchemeConfig(root, meshConfig, m2nConfig, participantConfig);
399
400 xml::ConfigurationContext ccontext{context.name, 0, 1};
401 xml::configure(root, ccontext, configurationPath);
402 m2n::PtrM2N m2n = m2nConfig->getM2N(nameParticipant0, nameParticipant1);
403
404 // some dummy mesh
405 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(1.0, 1.0, 1.0));
406 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(2.0, 1.0, -1.0));
407 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(3.0, 1.0, 1.0));
408 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(4.0, 1.0, -1.0));
409 meshConfig->meshes().at(0)->allocateDataValues();
410
411 connect(nameParticipant0, nameParticipant1, context.name, m2n);
412 CouplingScheme &cplScheme = *cplSchemeConfig.getCouplingScheme(context.name);
413
414 double computedTime = 0.0;
415 double maxTime = 1.0; // from max-time
416 int computedTimesteps = 0;
417
418 mesh::PtrMesh mesh = meshConfig->meshes().at(0);
419
420 if (context.isNamed(nameParticipant0)) {
421 double solverDt = 0.3;
422 double preciceDt, dt;
423 mesh->data(0)->setSampleAtTime(0, time::Sample{mesh->data(0)->getDimensions(), mesh->data(0)->values()});
424 cplScheme.initialize(0.0, 1);
425 BOOST_TEST(not cplScheme.hasDataBeenReceived());
426 BOOST_TEST(cplScheme.getNextTimeStepMaxSize() == 1);
427 BOOST_TEST(not cplScheme.hasDataBeenReceived());
428 BOOST_TEST(not cplScheme.isTimeWindowComplete());
429 BOOST_TEST(cplScheme.isCouplingOngoing());
430 while (cplScheme.isCouplingOngoing()) {
431 preciceDt = cplScheme.getNextTimeStepMaxSize();
432 dt = std::min({solverDt, preciceDt});
433 mesh->data(0)->setSampleAtTime(computedTime + dt, time::Sample{mesh->data(0)->getDimensions(), mesh->data(0)->values()});
434 cplScheme.addComputedTime(dt);
435 computedTime += dt;
436 computedTimesteps++;
437 cplScheme.firstSynchronization({});
438 cplScheme.firstExchange();
439 cplScheme.secondSynchronization();
440 cplScheme.secondExchange();
441 BOOST_TEST(cplScheme.isTimeWindowComplete());
442 BOOST_TEST(testing::equals(computedTime, cplScheme.getTime()));
443 BOOST_TEST(computedTimesteps == cplScheme.getTimeWindows() - 1);
444 if (cplScheme.isCouplingOngoing()) {
445 BOOST_TEST(cplScheme.hasDataBeenReceived());
446 }
447 }
448 cplScheme.finalize();
449 BOOST_TEST(testing::equals(computedTime, maxTime));
450 BOOST_TEST(computedTimesteps == 4);
451 BOOST_TEST(cplScheme.isTimeWindowComplete());
452 BOOST_TEST(not cplScheme.isCouplingOngoing());
453 } else {
454 BOOST_TEST(context.isNamed(nameParticipant1));
455 mesh->data(1)->setSampleAtTime(0, time::Sample{mesh->data(1)->getDimensions(), mesh->data(1)->values()});
456 cplScheme.initialize(0.0, 1);
457 BOOST_TEST(cplScheme.hasDataBeenReceived());
458 BOOST_TEST(not cplScheme.isTimeWindowComplete());
459 BOOST_TEST(cplScheme.isCouplingOngoing());
460 while (cplScheme.isCouplingOngoing()) {
461 mesh->data(1)->setSampleAtTime(computedTime + cplScheme.getTimeWindowSize(), time::Sample{mesh->data(1)->getDimensions(), mesh->data(1)->values()});
462 cplScheme.addComputedTime(cplScheme.getTimeWindowSize());
463 computedTime += cplScheme.getTimeWindowSize();
464 computedTimesteps++;
465 cplScheme.firstSynchronization({});
466 cplScheme.firstExchange();
467 cplScheme.secondSynchronization();
468 cplScheme.secondExchange();
469 BOOST_TEST(cplScheme.isTimeWindowComplete());
470 BOOST_TEST(testing::equals(computedTime, cplScheme.getTime()));
471 BOOST_TEST(computedTimesteps == cplScheme.getTimeWindows() - 1);
472 if (cplScheme.isCouplingOngoing()) {
473 BOOST_TEST(cplScheme.hasDataBeenReceived());
474 }
475 }
476 cplScheme.finalize();
477 BOOST_TEST(testing::equals(computedTime, maxTime));
478 BOOST_TEST(computedTimesteps == 4);
479 BOOST_TEST(cplScheme.isTimeWindowComplete());
480 BOOST_TEST(not cplScheme.isCouplingOngoing());
481 }
482}
483
490BOOST_AUTO_TEST_CASE(testSerialDataInitialization)
491{
492 PRECICE_TEST("Participant0"_on(1_rank), "Participant1"_on(1_rank), Require::Events);
493
494 using namespace mesh;
495
496 std::string configurationPath(_pathToTests + "serial-explicit-coupling-datainit.xml");
497 std::string nameParticipant0("Participant0");
498 std::string nameParticipant1("Participant1");
499
501 PtrDataConfiguration dataConfig(new DataConfiguration(root));
502 PtrMeshConfiguration meshConfig(new MeshConfiguration(root, dataConfig));
505 CouplingSchemeConfiguration cplSchemeConfig(root, meshConfig, m2nConfig, participantConfig);
506
507 xml::ConfigurationContext ccontext{context.name, 0, 1};
508 xml::configure(root, ccontext, configurationPath);
509 m2n::PtrM2N m2n = m2nConfig->getM2N(nameParticipant0, nameParticipant1);
510
511 // some dummy mesh
512 meshConfig->meshes().at(0)->createVertex(Eigen::Vector2d(1.0, 1.0));
513 meshConfig->meshes().at(0)->createVertex(Eigen::Vector2d(2.0, -1.0));
514 meshConfig->meshes().at(0)->createVertex(Eigen::Vector2d(3.0, 1.0));
515 meshConfig->meshes().at(0)->createVertex(Eigen::Vector2d(4.0, -1.0));
516 meshConfig->meshes().at(0)->allocateDataValues();
517
518 connect(nameParticipant0, nameParticipant1, context.name, m2n);
519 CouplingScheme &cplScheme = *cplSchemeConfig.getCouplingScheme(context.name);
520 BOOST_TEST(cplScheme.isActionRequired(CouplingScheme::Action::InitializeData));
521
522 BOOST_TEST(meshConfig->meshes().size() == 1);
523 mesh::PtrMesh mesh = meshConfig->meshes().at(0);
524 BOOST_TEST(mesh->data().size() == 3);
525 auto &dataValues0 = mesh->data(0)->values();
526 auto &dataValues1 = mesh->data(1)->values();
527 auto &dataValues2 = mesh->data(2)->values();
528
529 BOOST_TEST(mesh->data(0)->getName() == "Data0");
530 BOOST_TEST(mesh->data(1)->getName() == "Data1");
531 BOOST_TEST(mesh->data(2)->getName() == "Data2");
532
533 if (context.isNamed(nameParticipant0)) {
534 BOOST_TEST(cplScheme.isActionRequired(CouplingScheme::Action::InitializeData));
535 dataValues2(0) = 3.0;
536 cplScheme.markActionFulfilled(CouplingScheme::Action::InitializeData);
537 BOOST_TEST(not cplScheme.hasDataBeenReceived());
538 mesh->data(2)->setSampleAtTime(0, time::Sample{mesh->data(2)->getDimensions(), mesh->data(2)->values()});
539 cplScheme.initialize(0.0, 1);
540 BOOST_TEST(cplScheme.hasDataBeenReceived()); // receives initial data
541 // 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
542 BOOST_TEST(testing::equals(dataValues0(0), 5.0)); // @todo Incorrect due to bug. See https://github.com/precice/precice/issues/1693
543 BOOST_TEST(testing::equals(dataValues1(0), 1.0));
544 dataValues2(0) = 2.0;
545 cplScheme.addComputedTime(cplScheme.getNextTimeStepMaxSize());
546 mesh->data(2)->setSampleAtTime(cplScheme.getTime(), time::Sample{mesh->data(2)->getDimensions(), mesh->data(2)->values()});
547 cplScheme.firstSynchronization({});
548 cplScheme.firstExchange();
549 cplScheme.secondSynchronization();
550 cplScheme.secondExchange();
551 BOOST_TEST(cplScheme.hasDataBeenReceived());
552 BOOST_TEST(testing::equals(dataValues0(0), 4.0));
553 BOOST_TEST(not cplScheme.isCouplingOngoing());
554 cplScheme.finalize();
555 } else {
556 BOOST_TEST(context.isNamed(nameParticipant1));
557 BOOST_TEST(cplScheme.isActionRequired(CouplingScheme::Action::InitializeData));
558 dataValues0(0) = 5.0; // Data0 is written, but initialization is turned off.
559 dataValues1(0) = 1.0;
560 cplScheme.markActionFulfilled(CouplingScheme::Action::InitializeData);
561 mesh->data(0)->setSampleAtTime(0, time::Sample{mesh->data(0)->getDimensions(), mesh->data(0)->values()});
562 mesh->data(1)->setSampleAtTime(0, time::Sample{mesh->data(1)->getDimensions(), mesh->data(1)->values()});
563 cplScheme.initialize(0.0, 1);
564 BOOST_TEST(cplScheme.hasDataBeenReceived()); // receives initial data
565 BOOST_TEST(testing::equals(dataValues2(0), 2.0));
566 dataValues0(0) = 4.0;
567 cplScheme.addComputedTime(cplScheme.getNextTimeStepMaxSize());
568 mesh->data(0)->setSampleAtTime(cplScheme.getTime(), time::Sample{mesh->data(0)->getDimensions(), mesh->data(0)->values()});
569 mesh->data(1)->setSampleAtTime(cplScheme.getTime(), time::Sample{mesh->data(1)->getDimensions(), mesh->data(1)->values()});
570 cplScheme.firstSynchronization({});
571 cplScheme.firstExchange();
572 cplScheme.secondSynchronization();
573 cplScheme.secondExchange();
574 BOOST_TEST(not cplScheme.hasDataBeenReceived()); // first participant did not send any further data
575 BOOST_TEST(not cplScheme.isCouplingOngoing());
576 cplScheme.finalize();
577 }
578}
579
586BOOST_AUTO_TEST_CASE(testParallelDataInitialization)
587{
588 PRECICE_TEST("Participant0"_on(1_rank), "Participant1"_on(1_rank), Require::Events);
589
590 using namespace mesh;
591
592 std::string configurationPath(_pathToTests + "parallel-explicit-coupling-datainit.xml");
593 std::string nameParticipant0("Participant0");
594 std::string nameParticipant1("Participant1");
595
597 PtrDataConfiguration dataConfig(new DataConfiguration(root));
598 PtrMeshConfiguration meshConfig(new MeshConfiguration(root, dataConfig));
601 CouplingSchemeConfiguration cplSchemeConfig(root, meshConfig, m2nConfig, participantConfig);
602
603 xml::ConfigurationContext ccontext{context.name, 0, 1};
604 xml::configure(root, ccontext, configurationPath);
605 m2n::PtrM2N m2n = m2nConfig->getM2N(nameParticipant0, nameParticipant1);
606
607 // some dummy mesh
608 meshConfig->meshes().at(0)->createVertex(Eigen::Vector2d(1.0, 1.0));
609 meshConfig->meshes().at(0)->createVertex(Eigen::Vector2d(2.0, -1.0));
610 meshConfig->meshes().at(0)->createVertex(Eigen::Vector2d(3.0, 1.0));
611 meshConfig->meshes().at(0)->createVertex(Eigen::Vector2d(4.0, -1.0));
612 meshConfig->meshes().at(0)->allocateDataValues();
613
614 connect(nameParticipant0, nameParticipant1, context.name, m2n);
615 CouplingScheme &cplScheme = *cplSchemeConfig.getCouplingScheme(context.name);
616 BOOST_TEST(cplScheme.isActionRequired(CouplingScheme::Action::InitializeData));
617
618 BOOST_TEST(meshConfig->meshes().size() == 1);
619 mesh::PtrMesh mesh = meshConfig->meshes().at(0);
620 BOOST_TEST(mesh->data().size() == 3);
621 auto &dataValues0 = mesh->data(0)->values();
622 auto &dataValues1 = mesh->data(1)->values();
623 auto &dataValues2 = mesh->data(2)->values();
624
625 BOOST_TEST(mesh->data(0)->getName() == "Data0");
626 BOOST_TEST(mesh->data(1)->getName() == "Data1");
627 BOOST_TEST(mesh->data(2)->getName() == "Data2");
628
629 if (context.isNamed(nameParticipant0)) {
630 BOOST_TEST(cplScheme.isActionRequired(CouplingScheme::Action::InitializeData));
631 dataValues2(0) = 3.0;
632 cplScheme.markActionFulfilled(CouplingScheme::Action::InitializeData);
633 BOOST_TEST(not cplScheme.hasDataBeenReceived());
634 mesh->data(2)->setSampleAtTime(0, time::Sample{mesh->data(2)->getDimensions(), mesh->data(2)->values()});
635 cplScheme.initialize(0.0, 1);
636 BOOST_TEST(cplScheme.hasDataBeenReceived()); // receives initial data
637 // 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
638 BOOST_TEST(testing::equals(dataValues0(0), 5.0)); // @todo Incorrect due to bug. See https://github.com/precice/precice/issues/1693
639 BOOST_TEST(testing::equals(dataValues1(0), 1.0));
640 dataValues2(0) = 2.0;
641 cplScheme.addComputedTime(cplScheme.getNextTimeStepMaxSize());
642 mesh->data(2)->setSampleAtTime(cplScheme.getTime(), time::Sample{mesh->data(2)->getDimensions(), mesh->data(2)->values()});
643 cplScheme.firstSynchronization({});
644 cplScheme.firstExchange();
645 cplScheme.secondSynchronization();
646 cplScheme.secondExchange();
647 BOOST_TEST(cplScheme.hasDataBeenReceived());
648 BOOST_TEST(testing::equals(dataValues0(0), 4.0));
649 BOOST_TEST(not cplScheme.isCouplingOngoing());
650 cplScheme.finalize();
651 } else {
652 BOOST_TEST(context.isNamed(nameParticipant1));
653 BOOST_TEST(cplScheme.isActionRequired(CouplingScheme::Action::InitializeData));
654 dataValues0(0) = 5.0; // Data0 is written, but initialization is turned off.
655 dataValues1(0) = 1.0;
656 cplScheme.markActionFulfilled(CouplingScheme::Action::InitializeData);
657 mesh->data(0)->setSampleAtTime(0, time::Sample{mesh->data(0)->getDimensions(), mesh->data(0)->values()});
658 mesh->data(1)->setSampleAtTime(0, time::Sample{mesh->data(1)->getDimensions(), mesh->data(1)->values()});
659 cplScheme.initialize(0.0, 1);
660 BOOST_TEST(cplScheme.hasDataBeenReceived()); // receives initial data
661 BOOST_TEST(testing::equals(dataValues2(0), 3.0));
662 dataValues0(0) = 4.0;
663 cplScheme.addComputedTime(cplScheme.getNextTimeStepMaxSize());
664 mesh->data(0)->setSampleAtTime(cplScheme.getTime(), time::Sample{mesh->data(0)->getDimensions(), mesh->data(0)->values()});
665 mesh->data(1)->setSampleAtTime(cplScheme.getTime(), time::Sample{mesh->data(1)->getDimensions(), mesh->data(1)->values()});
666 cplScheme.firstSynchronization({});
667 cplScheme.firstExchange();
668 cplScheme.secondSynchronization();
669 cplScheme.secondExchange();
670 BOOST_TEST(cplScheme.hasDataBeenReceived());
671 BOOST_TEST(testing::equals(dataValues2(0), 2.0));
672 BOOST_TEST(not cplScheme.isCouplingOngoing());
673 cplScheme.finalize();
674 }
675}
676
678BOOST_AUTO_TEST_CASE(testExplicitCouplingWithSubcycling)
679{
680 PRECICE_TEST("Participant0"_on(1_rank), "Participant1"_on(1_rank), Require::Events);
682 options.useOnlyPrimaryCom = true;
683 auto m2n = context.connectPrimaryRanks("Participant0", "Participant1", options);
684
687 dataConfig->addData("Data0", mesh::Data::typeName::SCALAR);
688 dataConfig->addData("Data1", mesh::Data::typeName::VECTOR);
689 mesh::MeshConfiguration meshConfig(root, dataConfig);
690 mesh::PtrMesh mesh(new mesh::Mesh("Mesh", 3, testing::nextMeshID()));
691 mesh->createData("Data0", 1, 0_dataID);
692 mesh->createData("Data1", 3, 1_dataID);
693 mesh->createVertex(Eigen::Vector3d::Zero());
694 mesh->allocateDataValues();
695 meshConfig.insertMeshToMeshDimensionsMap(mesh->getName(), mesh->getDimensions());
696 meshConfig.addMesh(mesh);
697
698 const double maxTime = 1.0;
699 const int maxTimeWindows = 10;
700 const double timeWindowSize = 0.1;
701 const double timeStepSize = timeWindowSize; // solver is not subcycling
702 std::string nameParticipant0("Participant0");
703 std::string nameParticipant1("Participant1");
704 int sendDataIndex = -1;
705 int receiveDataIndex = -1;
706 if (context.isNamed(nameParticipant0)) {
707 sendDataIndex = 0;
708 receiveDataIndex = 1;
709 } else {
710 sendDataIndex = 1;
711 receiveDataIndex = 0;
712 }
713 cplscheme::SerialCouplingScheme cplScheme(maxTime, maxTimeWindows, timeWindowSize, nameParticipant0, nameParticipant1, context.name, m2n, constants::FIXED_TIME_WINDOW_SIZE, BaseCouplingScheme::Explicit);
714 cplScheme.addDataToSend(mesh->data(sendDataIndex), mesh, false, true);
715 cplScheme.addDataToReceive(mesh->data(receiveDataIndex), mesh, false, true);
717 runExplicitCouplingWithSubcycling(cplScheme, context.name, meshConfig);
718}
719
721BOOST_AUTO_TEST_CASE(testConfiguredExplicitCouplingWithSubcycling)
722{
723 PRECICE_TEST("Participant0"_on(1_rank), "Participant1"_on(1_rank), Require::Events);
724
725 using namespace mesh;
726
727 std::string configurationPath(_pathToTests + "explicit-coupling-scheme-1.xml");
728 std::string nameParticipant0("Participant0");
729 std::string nameParticipant1("Participant1");
730
732 PtrDataConfiguration dataConfig(new DataConfiguration(root));
733 PtrMeshConfiguration meshConfig(new MeshConfiguration(root, dataConfig));
736 CouplingSchemeConfiguration cplSchemeConfig(root, meshConfig, m2nConfig, participantConfig);
737
738 xml::ConfigurationContext ccontext{context.name, 0, 1};
739 xml::configure(root, ccontext, configurationPath);
740 m2n::PtrM2N m2n = m2nConfig->getM2N(nameParticipant0, nameParticipant1);
741 // some dummy mesh
742 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(1.0, 1.0, 1.0));
743 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(2.0, -1.0, 1.0));
744 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(3.0, 1.0, 1.0));
745 meshConfig->meshes().at(0)->createVertex(Eigen::Vector3d(4.0, -1.0, 1.0));
746 meshConfig->meshes().at(0)->allocateDataValues();
747
748 connect(nameParticipant0, nameParticipant1, context.name, m2n);
750 *cplSchemeConfig.getCouplingScheme(context.name), context.name,
751 *meshConfig);
752}
753
756
757#endif // not PRECICE_NO_MPI
void runSimpleExplicitCoupling(CouplingScheme &cplScheme, const std::string &participantName, const mesh::MeshConfiguration &meshConfig)
BOOST_AUTO_TEST_CASE(testSimpleExplicitCoupling)
Test that runs on 2 processors.
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:27
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.
const PtrCouplingScheme & getCouplingScheme(const std::string &participantName) const
Returns the configured coupling scheme.
Interface for all coupling schemes.
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 void initialize(double startTime, int startTimeWindow)=0
Initializes the coupling scheme and establishes a communication connection to the coupling partner....
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:39
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:111
Represents an XML tag to be configured automatically.
Definition XMLTag.hpp:31
T min(T... args)
contains implementations of coupling schemes for coupled simulations.
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:65
std::string getPathToSources()
Returns the base path to the sources.
Definition Testing.cpp:31
XMLTag getRootTag()
Returns an XMLTag::Listener that does nothing on callbacks.
Definition XMLTag.cpp:389
void configure(XMLTag &tag, const precice::xml::ConfigurationContext &context, std::string_view configurationFilename)
Configures the given configuration from file configurationFilename.
Definition XMLTag.cpp:395
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:256
static auto useOnlyPrimaryCom(PtrM2N m2n) -> typename std::add_lvalue_reference< decltype(m2n->_useOnlyPrimaryCom)>::type
Definition M2N.hpp:257
Tightly coupled to the parameters of Participant()
Definition XMLTag.hpp:24