preCICE v3.2.0
Loading...
Searching...
No Matches
M2N.cpp
Go to the documentation of this file.
1#include <utility>
2
5#include "M2N.hpp"
9#include "mesh/Mesh.hpp"
11#include "precice/impl/versions.hpp"
12#include "profiling/Event.hpp"
13#include "utils/IntraComm.hpp"
14#include "utils/assertion.hpp"
15
17
18namespace precice {
19extern bool syncMode;
20
21namespace m2n {
22
23M2N::M2N(com::PtrCommunication interComm, DistributedComFactory::SharedPointer distrFactory, bool useOnlyPrimaryCom, bool useTwoLevelInit)
24 : _interComm(std::move(interComm)),
25 _distrFactory(std::move(distrFactory)),
26 _useOnlyPrimaryCom(useOnlyPrimaryCom),
27 _useTwoLevelInit(useTwoLevelInit)
28{
29}
30
32{
33 if (isConnected()) {
35 }
36}
37
39{
41}
42
43namespace {
44std::string makeLocalInfo(std::string_view configHash)
45{
46 std::string info = PRECICE_VERSION;
47 info += ";";
48 info += configHash;
49 return info;
50}
51
52} // namespace
53
55 std::string_view remoteParticipant,
56 std::string_view localConfigHash,
57 std::string_view remoteInfo)
58{
59 auto sep = remoteInfo.find(";");
60 PRECICE_CHECK(sep != std::string::npos, "The received information string from participant {} is damaged. \"{}\"");
61
62 auto remoteVersion = remoteInfo.substr(0, sep);
63 PRECICE_CHECK(remoteVersion == PRECICE_VERSION,
64 "This participant {} uses preCICE version {} but the requester participant {} uses preCICE version {}. Mixing preCICE versions can lead to undefined behavior and is, thus, forbidden.",
65 localParticipant, PRECICE_VERSION, remoteParticipant, remoteVersion);
66
67 auto remoteConfigHash = remoteInfo.substr(sep + 1);
68 PRECICE_CHECK(remoteConfigHash == localConfigHash,
69 "This participant {} uses a different configuration file than the remote participant {}. Hashes differ {} != {}.",
70 localParticipant, remoteParticipant, localConfigHash, remoteConfigHash);
71}
72
74 const std::string &acceptorName,
75 const std::string &requesterName,
76 std::string_view configHash)
77{
78 PRECICE_TRACE(acceptorName, requesterName);
79
80 Event e("m2n.acceptPrimaryRankConnection." + requesterName, profiling::Fundamental, profiling::Synchronize);
81
83 PRECICE_DEBUG("Accept primary connection");
85 _interComm->acceptConnection(acceptorName, requesterName, "PRIMARYCOM", utils::IntraComm::getRank());
86 _isPrimaryRankConnected = _interComm->isConnected();
87
88 std::string localInfo = makeLocalInfo(configHash);
89 _interComm->send(localInfo, 0);
90 std::string remoteInfo;
91 _interComm->receive(remoteInfo, 0);
92
93 checkRemoteInfo(acceptorName,
94 requesterName,
95 configHash,
96 remoteInfo);
97 }
98
100}
101
103 const std::string &acceptorName,
104 const std::string &requesterName,
105 std::string_view configHash)
106{
107 PRECICE_TRACE(acceptorName, requesterName);
108
109 Event e("m2n.requestPrimaryRankConnection." + acceptorName, profiling::Fundamental, profiling::Synchronize);
110
113 PRECICE_DEBUG("Request primary connection");
114 _interComm->requestConnection(acceptorName, requesterName, "PRIMARYCOM", 0, 1);
115 _isPrimaryRankConnected = _interComm->isConnected();
116
117 // check that local and remote have the same precice version
118 std::string remoteInfo;
119 _interComm->receive(remoteInfo, 0);
120 std::string localInfo = makeLocalInfo(configHash);
121 _interComm->send(localInfo, 0);
122
123 checkRemoteInfo(requesterName,
124 acceptorName,
125 configHash,
126 remoteInfo);
127 }
128
130}
131
133 const std::string &acceptorName,
134 const std::string &requesterName)
135{
136 PRECICE_TRACE(acceptorName, requesterName);
138 Event e("m2n.acceptSecondaryRanksConnection", profiling::Synchronize);
139
141 for (const auto &pair : _distComs) {
142 PRECICE_DEBUG("Accept secondary connections");
143 pair.second->acceptConnection(acceptorName, requesterName);
144 _areSecondaryRanksConnected = _areSecondaryRanksConnected && pair.second->isConnected();
145 }
147}
148
150 const std::string &acceptorName,
151 const std::string &requesterName)
152{
153 PRECICE_TRACE(acceptorName, requesterName);
155 Event e("m2n.requestSecondaryRanksConnection", profiling::Synchronize);
156
158 for (const auto &pair : _distComs) {
159 PRECICE_DEBUG("Request secondary connections");
160 pair.second->requestConnection(acceptorName, requesterName);
161 _areSecondaryRanksConnected = _areSecondaryRanksConnected && pair.second->isConnected();
162 }
164}
165
166void M2N::prepareEstablishment(const std::string &acceptorName,
167 const std::string &requesterName)
168{
170 _interComm->prepareEstablishment(acceptorName, requesterName);
171}
172
173void M2N::cleanupEstablishment(const std::string &acceptorName,
174 const std::string &requesterName)
175{
177 _interComm->cleanupEstablishment(acceptorName, requesterName);
178}
179
181 const std::string &acceptorName,
182 const std::string &requesterName)
183{
184 PRECICE_TRACE(acceptorName, requesterName);
187 for (const auto &pair : _distComs) {
188 pair.second->acceptPreConnection(acceptorName, requesterName);
189 _areSecondaryRanksConnected = _areSecondaryRanksConnected && pair.second->isConnected();
190 }
192}
193
195 const std::string &acceptorName,
196 const std::string &requesterName)
197{
198 PRECICE_TRACE(acceptorName, requesterName);
201 for (const auto &pair : _distComs) {
202 pair.second->requestPreConnection(acceptorName, requesterName);
203 _areSecondaryRanksConnected = _areSecondaryRanksConnected && pair.second->isConnected();
204 }
206}
207
209{
211 for (const auto &pair : _distComs) {
212 pair.second->completeSecondaryRanksConnection();
213 }
214}
215
222
234
236{
238 if (_useOnlyPrimaryCom) {
239 return;
240 }
241
243 for (const auto &pair : _distComs) {
244 pair.second->closeConnection();
245 _areSecondaryRanksConnected |= pair.second->isConnected();
246 }
248}
249
255
257{
260 _distComs[mesh->getID()] = _distrFactory->newDistributedCommunication(mesh);
261}
262
264 precice::span<double const> itemsToSend,
265 int meshID,
266 int valueDimension)
267{
268 if (not _useOnlyPrimaryCom) {
270 PRECICE_ASSERT(_distComs.find(meshID) != _distComs.end());
271 PRECICE_ASSERT(_distComs[meshID].get() != nullptr);
272
274 Event es("mn2.sendData.interSync");
275 bool ack = true;
276 _interComm->send(ack, 0);
277 _interComm->receive(ack, 0);
278 _interComm->send(ack, 0);
279 }
280
281 Event e("m2n.sendData", profiling::Synchronize);
282
283 _distComs[meshID]->send(itemsToSend, valueDimension);
284 } else {
286 _interComm->send(itemsToSend, 0);
287 }
288}
289
290void M2N::send(bool itemToSend)
291{
294 _interComm->send(itemToSend, 0);
295 }
296}
297
298void M2N::send(double itemToSend)
299{
302 _interComm->send(itemToSend, 0);
303 }
304}
305
307{
310 _interComm->send(itemsToSend, 0);
311 }
312}
313
314void M2N::send(int itemToSend)
315{
318 _interComm->send(itemToSend, 0);
319 }
320}
321
323{
324 MeshID meshID = mesh.getID();
326 "This method can only be used for parallel participants");
328 PRECICE_ASSERT(_distComs.find(meshID) != _distComs.end());
329 PRECICE_ASSERT(_distComs[meshID].get() != nullptr);
330 _distComs[meshID]->broadcastSendMesh();
331}
332
335{
337 "This method can only be used for parallel participants");
338 MeshID meshID = mesh.getID();
340 _distComs[meshID]->scatterAllCommunicationMap(localCommunicationMap);
341}
342
343void M2N::broadcastSend(int itemToSend, mesh::Mesh &mesh)
344{
346 "This method can only be used for parallel participants");
347 MeshID meshID = mesh.getID();
349 _distComs[meshID]->broadcastSend(itemToSend);
350}
351
353 int meshID,
354 int valueDimension)
355{
356 if (not _useOnlyPrimaryCom) {
358 PRECICE_ASSERT(_distComs.find(meshID) != _distComs.end());
359 PRECICE_ASSERT(_distComs[meshID].get() != nullptr);
360
362 Event es("m2n.receiveData.interSync");
363 bool ack;
364 _interComm->receive(ack, 0);
365 _interComm->send(ack, 0);
366 _interComm->receive(ack, 0);
367 }
368
369 Event e("m2n.receiveData", profiling::Synchronize);
370
371 _distComs[meshID]->receive(itemsToReceive, valueDimension);
372 } else {
374 _interComm->receive(itemsToReceive, 0);
375 }
376}
377
378void M2N::receive(bool &itemToReceive)
379{
382 _interComm->receive(itemToReceive, 0);
383 }
384
385 utils::IntraComm::broadcast(itemToReceive);
386
387 PRECICE_DEBUG("receive(bool): {}", itemToReceive);
388}
389
390void M2N::receive(double &itemToReceive)
391{
394 _interComm->receive(itemToReceive, 0);
395 }
396
397 utils::IntraComm::broadcast(itemToReceive);
398
399 PRECICE_DEBUG("receive(double): {}", itemToReceive);
400}
401
403{
406 _interComm->receive(itemsToReceive, 0);
407 }
408
409 utils::IntraComm::broadcast(itemsToReceive);
410
411 PRECICE_DEBUG("receive(span<double>) .size() = {}", itemsToReceive.size());
412}
413
414void M2N::receive(int &itemToReceive)
415{
418 _interComm->receive(itemToReceive, 0);
419 }
420
421 utils::IntraComm::broadcast(itemToReceive);
422}
423
425{
427 "This method can only be used for parallel participants");
428 MeshID meshID = mesh.getID();
430 _distComs[meshID]->broadcastReceiveAll(itemToReceive);
431}
432
434{
436 "This method can only be used for parallel participants");
437 MeshID meshID = mesh.getID();
439 PRECICE_ASSERT(_distComs.find(meshID) != _distComs.end());
440 PRECICE_ASSERT(_distComs[meshID].get() != nullptr);
441 _distComs[meshID]->broadcastReceiveAllMesh();
442}
443
445{
447 "This method can only be used for parallel participants");
448 MeshID meshID = mesh.getID();
450 _distComs[meshID]->gatherAllCommunicationMap(localCommunicationMap);
451}
452
453} // namespace m2n
454} // namespace precice
#define PRECICE_DEBUG(...)
Definition LogMacros.hpp:61
#define PRECICE_TRACE(...)
Definition LogMacros.hpp:92
#define PRECICE_CHECK(check,...)
Definition LogMacros.hpp:32
#define PRECICE_ASSERT(...)
Definition assertion.hpp:85
std::shared_ptr< DistributedComFactory > SharedPointer
void scatterAllCommunicationMap(std::map< int, std::vector< int > > &localCommunicationMap, mesh::Mesh &mesh)
Scatters a communication map over connected ranks on remote participant (concerning the given mesh)
Definition M2N.cpp:333
void broadcastReceiveAll(std::vector< int > &itemToReceive, mesh::Mesh &mesh)
Receives an int per connected rank on remote participant (concerning the given mesh) @para[out] itemT...
Definition M2N.cpp:424
bool _isPrimaryRankConnected
Definition M2N.hpp:238
void closeDistributedConnections()
Disconnects all connections of the DistributedCommunication.
Definition M2N.cpp:235
void createDistributedCommunication(const mesh::PtrMesh &mesh)
Creates a new distributes communication for that mesh, stores the pointer in _distComs.
Definition M2N.cpp:256
void closePrimaryRankConnection()
Disconnects the primary connection.
Definition M2N.cpp:223
std::map< int, DistributedCommunication::SharedPointer > _distComs
mesh::getID() -> Pointer to distributed communication
Definition M2N.hpp:231
com::PtrCommunication _interComm
connection between the primary ranks of the connected participants
Definition M2N.hpp:234
void acceptPrimaryRankConnection(const std::string &acceptorName, const std::string &requesterName, std::string_view configHash)
Connects to another participant, which has to call requestConnection().
Definition M2N.cpp:73
void cleanupEstablishment(const std::string &acceptorName, const std::string &requesterName)
cleans-up to establish the connections
Definition M2N.cpp:173
void gatherAllCommunicationMap(std::map< int, std::vector< int > > &localCommunicationMap, mesh::Mesh &mesh)
Gathers a communication maps from connected ranks on remote participant (concerning the given mesh)
Definition M2N.cpp:444
void broadcastSendMesh(mesh::Mesh &mesh)
Broadcasts a mesh to connected ranks on remote participant (concerning the given mesh)
Definition M2N.cpp:322
void closeConnection()
Disconnects from communication space, i.e. participant.
Definition M2N.cpp:216
com::PtrCommunication getPrimaryRankCommunication()
Get the basic communication between the 2 primary ranks.
Definition M2N.cpp:250
void checkRemoteInfo(std::string_view localParticipant, std::string_view remoteParticipant, std::string_view localConfigHash, std::string_view remoteInfo)
checks the info of the remote participant against the version and config hash of the local participan...
Definition M2N.cpp:54
void acceptSecondaryRanksPreConnection(const std::string &acceptorName, const std::string &requesterName)
Definition M2N.cpp:180
bool _useOnlyPrimaryCom
between two serial participants, only use the primary com and no secondary com
Definition M2N.hpp:251
void acceptSecondaryRanksConnection(const std::string &acceptorName, const std::string &requesterName)
Connects to another participant, which has to call requestConnection().
Definition M2N.cpp:132
void requestSecondaryRanksConnection(const std::string &acceptorName, const std::string &requesterName)
Connects to another participant, which has to call acceptConnection().
Definition M2N.cpp:149
bool _areSecondaryRanksConnected
Definition M2N.hpp:240
void broadcastReceiveAllMesh(mesh::Mesh &mesh)
Receive mesh partitions per connected rank on remote participant (concerning the given mesh)
Definition M2N.cpp:433
void requestSecondaryRanksPreConnection(const std::string &acceptorName, const std::string &requesterName)
Definition M2N.cpp:194
DistributedComFactory::SharedPointer _distrFactory
Definition M2N.hpp:236
M2N(com::PtrCommunication intraComm, DistributedComFactory::SharedPointer distrFactory, bool useOnlyPrimaryCom=false, bool useTwoLevelInit=false)
Definition M2N.cpp:23
bool isConnected()
Returns true, if a connection to a remote participant has been setup.
Definition M2N.cpp:38
void requestPrimaryRankConnection(const std::string &acceptorName, const std::string &requesterName, std::string_view configHash)
Connects to another participant, which has to call acceptConnection().
Definition M2N.cpp:102
void broadcastSend(int itemToSend, mesh::Mesh &mesh)
Broadcasts an int to connected ranks on remote participant (concerning the given mesh)
Definition M2N.cpp:343
void completeSecondaryRanksConnection()
Definition M2N.cpp:208
bool _useTwoLevelInit
use the two-level initialization concept
Definition M2N.hpp:254
void prepareEstablishment(const std::string &acceptorName, const std::string &requesterName)
prepares to establish the connections
Definition M2N.cpp:166
~M2N()
Destructor, empty.
Definition M2N.cpp:31
void send(precice::span< double const > itemsToSend, int meshID, int valueDimension)
Sends an array of double values from all ranks (different for each rank).
Definition M2N.cpp:263
void receive(precice::span< double > itemsToReceive, int meshID, int valueDimension)
Definition M2N.cpp:352
Container and creator for meshes.
Definition Mesh.hpp:38
A C++ 11 implementation of the non-owning C++20 std::span type.
Definition span.hpp:284
constexpr size_type size() const noexcept
Definition span.hpp:469
static Rank getRank()
Current rank.
Definition IntraComm.cpp:42
static void broadcast(bool &value)
static bool isParallel()
True if this process is running in parallel.
Definition IntraComm.cpp:62
static bool isSecondary()
True if this process is running a secondary rank.
Definition IntraComm.cpp:57
T find(T... args)
std::shared_ptr< Communication > PtrCommunication
contains the logic of the parallel communication between participants.
Definition BoundM2N.cpp:12
provides Mesh, Data and primitives.
std::shared_ptr< Mesh > PtrMesh
static constexpr FundamentalTag Fundamental
Convenience instance of the FundamentalTag.
Definition Event.hpp:19
static constexpr SynchronizeTag Synchronize
Convenience instance of the SynchronizeTag.
Definition Event.hpp:21
Main namespace of the precice library.
int MeshID
Definition Types.hpp:30
constexpr auto get(span< E, S > s) -> decltype(s[N])
Definition span.hpp:602
bool syncMode
Enabled further inter- and intra-solver synchronisation.
STL namespace.
T substr(T... args)