preCICE v3.1.1
Loading...
Searching...
No Matches
PointToPointCommunication.cpp
Go to the documentation of this file.
1#include <algorithm>
2#include <boost/container/flat_map.hpp>
3#include <boost/io/ios_state.hpp>
4#include <functional>
5#include <iomanip>
6#include <iostream>
7#include <limits>
8#include <map>
9#include <set>
10#include <thread>
11#include <utility>
12#include <vector>
13
15#include "com/Communication.hpp"
17#include "com/Extra.hpp"
18#include "com/Request.hpp"
19#include "logging/LogMacros.hpp"
21#include "mesh/Mesh.hpp"
23#include "profiling/Event.hpp"
24#include "utils/IntraComm.hpp"
25#include "utils/algorithm.hpp"
26#include "utils/assertion.hpp"
27
29
30namespace precice::m2n {
31
33 int rankReceiver,
34 const com::PtrCommunication & communication)
35{
36 communication->send(static_cast<int>(m.size()), rankReceiver);
37
38 for (auto const &i : m) {
39 auto const &rank = i.first;
40 auto const &indices = i.second;
41 communication->send(rank, rankReceiver);
42 communication->sendRange(indices, rankReceiver);
43 }
44}
45
47 int rankSender,
48 const com::PtrCommunication & communication)
49{
51 m.clear();
52 int size = 0;
53 communication->receive(size, rankSender);
54
55 while (size--) {
56 Rank rank = -1;
57 communication->receive(rank, rankSender);
58 m[rank] = communication->receiveRange(rankSender, AsVectorTag<int>{});
59 }
60}
61
64{
65 communication->broadcast(static_cast<int>(m.size()));
66
67 for (auto const &i : m) {
68 auto const &rank = i.first;
69 auto const &indices = i.second;
70 communication->broadcast(rank);
71 communication->broadcast(indices);
72 }
73}
74
76 int rankBroadcaster,
78{
79 m.clear();
80 int size = 0;
81 communication->broadcast(size, rankBroadcaster);
82
83 while (size--) {
84 Rank rank = -1;
85 communication->broadcast(rank, rankBroadcaster);
86 communication->broadcast(m[rank], rankBroadcaster);
87 }
88}
89
91{
93 // Broadcast (send) vertex distributions.
95 } else if (utils::IntraComm::isSecondary()) {
96 // Broadcast (receive) vertex distributions.
98 }
99}
100
101void print(std::map<int, std::vector<int>> const &m)
102{
104
105 oss << "rank: " << utils::IntraComm::getRank() << "\n";
106
107 for (auto &i : m) {
108 for (auto &j : i.second) {
109 oss << i.first << ":" << j << '\n'; // prints rank:index
110 }
111 }
112
114 utils::IntraComm::getCommunication()->send(oss.str(), 0);
115 } else {
116
117 std::string s;
118
120 utils::IntraComm::getCommunication()->receive(s, rank);
121
122 oss << s;
123 }
124
125 std::cout << oss.str();
126 }
127}
128
130{
131 int size = m.size();
132
134 size_t count = 0;
135 size_t maximum = std::numeric_limits<size_t>::min();
136 size_t minimum = std::numeric_limits<size_t>::max();
137 size_t total = size;
138
139 if (size) {
140 maximum = std::max(maximum, static_cast<size_t>(size));
141 minimum = std::min(minimum, static_cast<size_t>(size));
142 count++;
143 }
144
146 utils::IntraComm::getCommunication()->receive(size, rank);
147
148 total += size;
149
150 if (size) {
151 maximum = std::max(maximum, static_cast<size_t>(size));
152 minimum = std::min(minimum, static_cast<size_t>(size));
153 count++;
154 }
155 }
156
157 if (minimum > maximum)
158 minimum = maximum;
159
160 auto average = static_cast<double>(total);
161 if (count != 0) {
162 average /= count;
163 }
164
165 boost::io::ios_all_saver ias{std::cout};
167 << "Number of Communication Partners per Interface Process:"
168 << "\n"
169 << " Total: " << total << "\n"
170 << " Maximum: " << maximum << "\n"
171 << " Minimum: " << minimum << "\n"
172 << " Average: " << average << "\n"
173 << "Number of Interface Processes: " << count << "\n"
174 << '\n';
175 } else {
177 utils::IntraComm::getCommunication()->send(size, 0);
178 }
179}
180
182{
183 int size = 0;
184
185 for (auto &i : m) {
186 size += i.second.size();
187 }
188
190 size_t count = 0;
191 size_t maximum = std::numeric_limits<size_t>::min();
192 size_t minimum = std::numeric_limits<size_t>::max();
193 size_t total = size;
194
195 if (size) {
196 maximum = std::max(maximum, static_cast<size_t>(size));
197 minimum = std::min(minimum, static_cast<size_t>(size));
198
199 count++;
200 }
201
203 utils::IntraComm::getCommunication()->receive(size, rank);
204
205 total += size;
206
207 if (size) {
208 maximum = std::max(maximum, static_cast<size_t>(size));
209 minimum = std::min(minimum, static_cast<size_t>(size));
210
211 count++;
212 }
213 }
214
215 if (minimum > maximum)
216 minimum = maximum;
217
218 auto average = static_cast<double>(total);
219 if (count != 0) {
220 average /= count;
221 }
222
223 boost::io::ios_all_saver ias{std::cout};
225 << "Number of LVDIs per Interface Process:"
226 << "\n"
227 << " Total: " << total << '\n'
228 << " Maximum: " << maximum << '\n'
229 << " Minimum: " << minimum << '\n'
230 << " Average: " << average << '\n'
231 << "Number of Interface Processes: " << count << '\n'
232 << '\n';
233 } else {
235
236 utils::IntraComm::getCommunication()->send(size, 0);
237 }
238}
239
263 // `thisVertexDistribution' is input vertex distribution from this participant.
264 mesh::Mesh::VertexDistribution const &thisVertexDistribution,
265 // `otherVertexDistribution' is input vertex distribution from other participant.
266 mesh::Mesh::VertexDistribution const &otherVertexDistribution,
267 int thisRank = utils::IntraComm::getRank())
268{
269 auto iterator = thisVertexDistribution.find(thisRank);
270 if (iterator == thisVertexDistribution.end()) {
271 return {};
272 }
273
274 std::map<int, std::vector<int>> communicationMap;
275 // first a safety check, that we are actually sorted, as the function below operates
276 // on sorted data sets
277 PRECICE_ASSERT(std::is_sorted(iterator->second.begin(), iterator->second.end()));
278
279 // now we iterate over all other vertex distributions to compute the intersection
280 for (const auto &[rank, vertices] : otherVertexDistribution) {
281 // first a safety check, that we are actually sorted, as the function below operates
282 // on sorted data sets
283 PRECICE_ASSERT(std::is_sorted(vertices.begin(), vertices.end()));
284
285 // before starting to compute an actual intersection, we first check if elements can
286 // possibly be in both data sets by comparing upper and lower index bounds of both
287 // data sets. For typical partitioning schemes, each rank only exchanges data with
288 // a few neighbors such that this check already filters out a significant amount of
289 // computations
290 if (iterator->second.empty() || vertices.empty() || (vertices.back() < iterator->second.at(0)) || (vertices.at(0) > iterator->second.back())) {
291 // in this case there is nothing to be done
292 continue;
293 }
294 // we have an intersection, let's compute it
295 std::vector<int> inters;
296 // the actual worker function, which gives us the indices of intersecting elements
297 // have a look at the documentation of the function for more details
298 precice::utils::set_intersection_indices(iterator->second.begin(), iterator->second.begin(), iterator->second.end(),
299 vertices.begin(), vertices.end(),
300 std::back_inserter(inters));
301 // we have the results, now commit it into the final map
302 if (!inters.empty()) {
303 communicationMap.insert({rank, std::move(inters)});
304 }
305 }
306 return communicationMap;
307}
308
310 com::PtrCommunicationFactory communicationFactory,
311 mesh::PtrMesh mesh)
312 : DistributedCommunication(std::move(mesh)),
313 _communicationFactory(std::move(communicationFactory))
314{
315}
316
322
324{
325 return _isConnected;
326}
327
329 std::string const &requesterName)
330{
331 PRECICE_TRACE(acceptorName, requesterName);
332 PRECICE_ASSERT(not isConnected(), "Already connected.");
333
334 mesh::Mesh::VertexDistribution vertexDistribution = _mesh->getVertexDistribution();
335 mesh::Mesh::VertexDistribution requesterVertexDistribution;
336
338 PRECICE_DEBUG("Exchange vertex distribution between both primary ranks");
339 Event e0("m2n.exchangeVertexDistribution");
340 // Establish connection between participants' primary processes.
341 auto c = _communicationFactory->newCommunication();
342
343 c->acceptConnection(acceptorName, requesterName, "TMP-PRIMARYCOM-" + _mesh->getName(), utils::IntraComm::getRank());
344
345 // Exchange vertex distributions.
346 m2n::send(vertexDistribution, 0, c);
347 m2n::receive(requesterVertexDistribution, 0, c);
348 }
349
350 PRECICE_DEBUG("Broadcast vertex distributions");
351 Event e1("m2n.broadcastVertexDistributions", profiling::Synchronize);
352 m2n::broadcast(vertexDistribution);
354 _mesh->setVertexDistribution(vertexDistribution);
355 }
356 m2n::broadcast(requesterVertexDistribution);
357 e1.stop();
358
359 // Local (for process rank in the current participant) communication map that
360 // defines a mapping from a process rank in the remote participant to an array
361 // of local data indices, which define a subset of local (for process rank in
362 // the current participant) data to be communicated between the current
363 // process rank and the remote process rank.
364 //
365 // Example. Assume that the current process rank is 3. Assume that its
366 // `communicationMap' is
367 //
368 // 1 -> {1, 3}
369 // 4 -> {0, 2}
370 //
371 // then it means that the current process (with rank 3)
372 // - has to communicate (send/receive) data with local indices 1 and 3 with
373 // the remote process with rank 1;
374 // - has to communicate (send/receive) data with local indices 0 and 2 with
375 // the remote process with rank 4.
376 Event e2("m2n.buildCommunicationMap", profiling::Synchronize);
378 vertexDistribution, requesterVertexDistribution);
379 e2.stop();
380
381// Print `communicationMap'.
382#ifdef P2P_LCM_PRINT
383 PRECICE_DEBUG("Print communication map");
384 print(communicationMap);
385#endif
386
387// Print statistics of `communicationMap'.
388#ifdef P2P_LCM_PRINT_STATS
389 PRECICE_DEBUG("Print communication map statistics");
390 printCommunicationPartnerCountStats(communicationMap);
391 printLocalIndexCountStats(communicationMap);
392#endif
393
394 Event e4("m2n.createCommunications");
395 e4.addData("Connections", communicationMap.size());
396 if (communicationMap.empty()) {
397 _isConnected = true;
398 return;
399 }
400
401 PRECICE_DEBUG("Create and connect communication");
402 _communication = _communicationFactory->newCommunication();
403
404 // Accept point-to-point connections (as server) between the current acceptor
405 // process (in the current participant) with rank `utils::IntraComm::getRank()'
406 // and (multiple) requester processes (in the requester participant).
407 _communication->acceptConnectionAsServer(acceptorName,
408 requesterName,
409 _mesh->getName(),
411 communicationMap.size());
412
413 PRECICE_DEBUG("Store communication map");
414 for (auto const &comMap : communicationMap) {
415 int globalRequesterRank = comMap.first;
416 auto indices = std::move(communicationMap[globalRequesterRank]);
417
418 _mappings.push_back({globalRequesterRank, std::move(indices), com::PtrRequest(), {}});
419 }
420 e4.stop();
421 _isConnected = true;
422}
423
425 std::string const &requesterName)
426{
427 PRECICE_TRACE(acceptorName, requesterName);
428 PRECICE_ASSERT(not isConnected(), "Already connected.");
429
430 const std::vector<int> &localConnectedRanks = _mesh->getConnectedRanks();
431
432 if (localConnectedRanks.empty()) {
433 _isConnected = true;
434 return;
435 }
436
437 _communication = _communicationFactory->newCommunication();
438
439 _communication->acceptConnectionAsServer(
440 acceptorName,
441 requesterName,
442 _mesh->getName(),
444 localConnectedRanks.size());
445
446 _connectionDataVector.reserve(localConnectedRanks.size());
447
448 for (int connectedRank : localConnectedRanks) {
449 _connectionDataVector.push_back({connectedRank, com::PtrRequest()});
450 }
451
452 _isConnected = true;
453}
454
456 std::string const &requesterName)
457{
458 PRECICE_TRACE(acceptorName, requesterName);
459 PRECICE_ASSERT(not isConnected(), "Already connected.");
460
461 mesh::Mesh::VertexDistribution vertexDistribution = _mesh->getVertexDistribution();
462 mesh::Mesh::VertexDistribution acceptorVertexDistribution;
463
465 PRECICE_DEBUG("Exchange vertex distribution between both primary ranks");
466 Event e0("m2n.exchangeVertexDistribution");
467 // Establish connection between participants' primary processes.
468 auto c = _communicationFactory->newCommunication();
469 c->requestConnection(acceptorName, requesterName,
470 "TMP-PRIMARYCOM-" + _mesh->getName(),
471 0, 1);
472
473 // Exchange vertex distributions.
474 m2n::receive(acceptorVertexDistribution, 0, c);
475 m2n::send(vertexDistribution, 0, c);
476 }
477
478 PRECICE_DEBUG("Broadcast vertex distributions");
479 Event e1("m2n.broadcastVertexDistributions", profiling::Synchronize);
480 m2n::broadcast(vertexDistribution);
482 _mesh->setVertexDistribution(vertexDistribution);
483 }
484 m2n::broadcast(acceptorVertexDistribution);
485 e1.stop();
486
487 // Local (for process rank in the current participant) communication map that
488 // defines a mapping from a process rank in the remote participant to an array
489 // of local data indices, which define a subset of local (for process rank in
490 // the current participant) data to be communicated between the current
491 // process rank and the remote process rank.
492 //
493 // Example. Assume that the current process rank is 3. Assume that its
494 // `communicationMap' is
495 //
496 // 1 -> {1, 3}
497 // 4 -> {0, 2}
498 //
499 // then it means that the current process (with rank 3)
500 // - has to communicate (send/receive) data with local indices 1 and 3 with
501 // the remote process with rank 1;
502 // - has to communicate (send/receive) data with local indices 0 and 2 with
503 // the remote process with rank 4.
504 Event e2("m2n.buildCommunicationMap", profiling::Synchronize);
506 vertexDistribution, acceptorVertexDistribution);
507 e2.stop();
508
509// Print `communicationMap'.
510#ifdef P2P_LCM_PRINT
511 PRECICE_DEBUG("Print communication map");
512 print(communicationMap);
513#endif
514
515// Print statistics of `communicationMap'.
516#ifdef P2P_LCM_PRINT_STATS
517 PRECICE_DEBUG("Print communication map statistics");
518 printCommunicationPartnerCountStats(communicationMap);
519 printLocalIndexCountStats(communicationMap);
520#endif
521
522 Event e4("m2n.createCommunications");
523 e4.addData("Connections", communicationMap.size());
524 if (communicationMap.empty()) {
525 _isConnected = true;
526 return;
527 }
528
530 requests.reserve(communicationMap.size());
531
532 std::set<int> acceptingRanks;
533 for (auto &i : communicationMap)
534 acceptingRanks.emplace(i.first);
535
536 PRECICE_DEBUG("Create and connect communication");
537 _communication = _communicationFactory->newCommunication();
538 // Request point-to-point connections (as client) between the current
539 // requester process (in the current participant) and (multiple) acceptor
540 // processes (in the acceptor participant) to ranks `accceptingRanks'
541 // according to `communicationMap`.
542 _communication->requestConnectionAsClient(acceptorName, requesterName,
543 _mesh->getName(),
544 acceptingRanks, utils::IntraComm::getRank());
545
546 PRECICE_DEBUG("Store communication map");
547 for (auto &i : communicationMap) {
548 auto globalAcceptorRank = i.first;
549 auto indices = std::move(i.second);
550
551 _mappings.push_back({globalAcceptorRank, std::move(indices), com::PtrRequest(), {}});
552 }
553 e4.stop();
554 _isConnected = true;
555}
556
558 std::string const &requesterName)
559{
560 PRECICE_TRACE(acceptorName, requesterName);
561 PRECICE_ASSERT(not isConnected(), "Already connected.");
562
563 std::vector<int> localConnectedRanks = _mesh->getConnectedRanks();
564
565 if (localConnectedRanks.empty()) {
566 _isConnected = true;
567 return;
568 }
569
571 requests.reserve(localConnectedRanks.size());
572 _connectionDataVector.reserve(localConnectedRanks.size());
573
574 std::set<int> acceptingRanks(localConnectedRanks.begin(), localConnectedRanks.end());
575
576 _communication = _communicationFactory->newCommunication();
577 _communication->requestConnectionAsClient(acceptorName, requesterName,
578 _mesh->getName(),
579 acceptingRanks, utils::IntraComm::getRank());
580
581 for (auto &connectedRank : localConnectedRanks) {
582 _connectionDataVector.push_back({connectedRank, com::PtrRequest()});
583 }
584 _isConnected = true;
585}
586
588{
589 mesh::Mesh::CommunicationMap localCommunicationMap = _mesh->getCommunicationMap();
590
591 for (auto &i : _connectionDataVector) {
592 _mappings.push_back({i.remoteRank, std::move(localCommunicationMap[i.remoteRank]), i.request, {}});
593 }
594}
595
597{
599
600 if (not isConnected())
601 return;
602
604
606 _mappings.clear();
607 _connectionDataVector.clear();
608 _isConnected = false;
609}
610
612{
613
614 if (_mappings.empty() || itemsToSend.empty()) {
615 return;
616 }
617
618 for (auto &mapping : _mappings) {
619 auto buffer = std::make_shared<std::vector<double>>();
620 buffer->reserve(mapping.indices.size() * valueDimension);
621 for (auto index : mapping.indices) {
622 for (int d = 0; d < valueDimension; ++d) {
623 buffer->push_back(itemsToSend[index * valueDimension + d]);
624 }
625 }
626 auto request = _communication->aSend(span<const double>{*buffer}, mapping.remoteRank);
627 bufferedRequests.emplace_back(request, buffer);
628 }
630}
631
632void PointToPointCommunication::receive(precice::span<double> itemsToReceive, int valueDimension)
633{
634 if (_mappings.empty() || itemsToReceive.empty()) {
635 return;
636 }
637
638 std::fill(itemsToReceive.begin(), itemsToReceive.end(), 0.0);
639
640 for (auto &mapping : _mappings) {
641 mapping.recvBuffer.resize(mapping.indices.size() * valueDimension);
642 mapping.request = _communication->aReceive(span<double>{mapping.recvBuffer}, mapping.remoteRank);
643 }
644
645 for (auto &mapping : _mappings) {
646 mapping.request->wait();
647
648 int i = 0;
649 for (auto index : mapping.indices) {
650 for (int d = 0; d < valueDimension; ++d) {
651 itemsToReceive[index * valueDimension + d] += mapping.recvBuffer[i * valueDimension + d];
652 }
653 i++;
654 }
655 }
656}
657
659{
660 for (auto &connectionData : _connectionDataVector) {
661 _communication->send(itemToSend, connectionData.remoteRank);
662 }
663}
664
666
667{
668 int data = 0;
669 for (auto &connectionData : _connectionDataVector) {
670 _communication->receive(data, connectionData.remoteRank);
671 itemToReceive.push_back(data);
672 }
673}
674
676{
677 for (auto &connectionData : _connectionDataVector) {
678 com::sendMesh(*_communication, connectionData.remoteRank, *_mesh);
679 }
680}
681
683{
684 for (auto &connectionData : _connectionDataVector) {
685 com::receiveMesh(*_communication, connectionData.remoteRank, *_mesh);
686 }
687}
688
690{
691 for (auto &connectionData : _connectionDataVector) {
692 _communication->sendRange(localCommunicationMap[connectionData.remoteRank], connectionData.remoteRank);
693 }
694}
695
697{
699 for (auto &connectionData : _connectionDataVector) {
700 localCommunicationMap[connectionData.remoteRank] = _communication->receiveRange(connectionData.remoteRank, AsVectorTag<int>{});
701 }
702}
703
704void PointToPointCommunication::checkBufferedRequests(bool blocking)
705{
706 PRECICE_TRACE(bufferedRequests.size());
707 do {
708 for (auto it = bufferedRequests.begin(); it != bufferedRequests.end();) {
709 if (it->first->test())
710 it = bufferedRequests.erase(it);
711 else
712 ++it;
713 }
714 if (bufferedRequests.empty())
715 return;
716 if (blocking)
717 std::this_thread::yield(); // give up our time slice, so MPI may work
718 } while (blocking);
719}
720
721} // namespace precice::m2n
#define PRECICE_DEBUG(...)
Definition LogMacros.hpp:64
#define PRECICE_TRACE(...)
Definition LogMacros.hpp:95
unsigned int index
#define PRECICE_ASSERT(...)
Definition assertion.hpp:87
T back_inserter(T... args)
T begin(T... args)
Interface for all distributed solver to solver communication classes.
mesh::PtrMesh _mesh
mesh that dictates the distribution of this mapping
void scatterAllCommunicationMap(CommunicationMap &localCommunicationMap) override
Scatters a communication map over connected ranks on remote participant.
PointToPointCommunication(com::PtrCommunicationFactory communicationFactory, mesh::PtrMesh mesh)
void broadcastSendMesh() override
Broadcasts a mesh to connected ranks on remote participant.
void gatherAllCommunicationMap(CommunicationMap &localCommunicationMap) override
Gathers a communication maps from connected ranks on remote participant.
void broadcastSend(int itemToSend) override
Broadcasts an int to connected ranks on remote participant.
bool isConnected() const override
Returns true, if a connection to a remote participant has been established.
std::vector< Mapping > _mappings
Local (for process rank in the current participant) vector of mappings (one to service each point-to-...
std::vector< ConnectionData > _connectionDataVector
Local (for process rank in the current participant) vector of ConnectionData (one to service each poi...
void acceptPreConnection(std::string const &acceptorName, std::string const &requesterName) override
Accepts connection from participant, which has to call requestPreConnection(). Only initial connectio...
void receive(precice::span< double > itemsToReceive, int valueDimension=1) override
Receives a subset of local double values corresponding to local indices deduced from the current and ...
std::list< std::pair< std::shared_ptr< com::Request >, std::shared_ptr< std::vector< double > > > > bufferedRequests
void broadcastReceiveAll(std::vector< int > &itemToReceive) override
Receives an int per connected rank on remote participant @para[out] itemToReceive received ints from ...
void requestPreConnection(std::string const &acceptorName, std::string const &requesterName) override
Requests connection from participant, which has to call acceptConnection(). Only initial connection i...
void completeSecondaryRanksConnection() override
Completes the secondary connections for both acceptor and requester by updating the vertex list in _m...
void checkBufferedRequests(bool blocking)
Checks all stored requests for completion and removes associated buffers.
void acceptConnection(std::string const &acceptorName, std::string const &requesterName) override
Accepts connection from participant, which has to call requestConnection().
void requestConnection(std::string const &acceptorName, std::string const &requesterName) override
Requests connection from participant, which has to call acceptConnection().
com::PtrCommunication _communication
Communication class used for this PointToPointCommunication.
void closeConnection() override
Disconnects from communication space, i.e. participant.
void broadcastReceiveAllMesh() override
Receive mesh partitions per connected rank on remote participant.
void send(precice::span< double const > itemsToSend, int valueDimension=1) override
Sends a subset of local double values corresponding to local indices deduced from the current and rem...
void stop()
Stops a running event.
Definition Event.cpp:37
void addData(std::string_view key, int value)
Adds named integer data, associated to an event.
Definition Event.cpp:48
A C++ 11 implementation of the non-owning C++20 std::span type.
Definition span.hpp:284
PRECICE_SPAN_NODISCARD constexpr bool empty() const noexcept
Definition span.hpp:476
constexpr iterator begin() const noexcept
Definition span.hpp:503
constexpr iterator end() const noexcept
Definition span.hpp:505
static Rank getRank()
Current rank.
Definition IntraComm.cpp:42
static bool isPrimary()
True if this process is running the primary rank.
Definition IntraComm.cpp:52
static auto allSecondaryRanks()
Returns an iterable range over salve ranks [1, _size)
Definition IntraComm.hpp:37
static bool isSecondary()
True if this process is running a secondary rank.
Definition IntraComm.cpp:57
static com::PtrCommunication & getCommunication()
Intra-participant communication.
Definition IntraComm.hpp:31
T clear(T... args)
T emplace(T... args)
T empty(T... args)
T end(T... args)
T fill(T... args)
T find(T... args)
T fixed(T... args)
T insert(T... args)
T is_sorted(T... args)
T max(T... args)
T min(T... args)
void sendMesh(Communication &communication, int rankReceiver, const mesh::Mesh &mesh)
Definition Extra.cpp:8
std::shared_ptr< Request > PtrRequest
void receiveMesh(Communication &communication, int rankSender, mesh::Mesh &mesh)
Definition Extra.cpp:13
contains the logic of the parallel communication between participants.
Definition BoundM2N.cpp:12
std::map< int, std::vector< int > > buildCommunicationMap(mesh::Mesh::VertexDistribution const &thisVertexDistribution, mesh::Mesh::VertexDistribution const &otherVertexDistribution, int thisRank=utils::IntraComm::getRank())
void print(std::map< int, std::vector< int > > const &m)
void broadcastReceive(mesh::Mesh::VertexDistribution &m, int rankBroadcaster, const com::PtrCommunication &communication=utils::IntraComm::getCommunication())
void printCommunicationPartnerCountStats(std::map< int, std::vector< int > > const &m)
void printLocalIndexCountStats(std::map< int, std::vector< int > > const &m)
void receive(mesh::Mesh::VertexDistribution &m, int rankSender, const com::PtrCommunication &communication)
void broadcast(mesh::Mesh::VertexDistribution &m)
void send(mesh::Mesh::VertexDistribution const &m, int rankReceiver, const com::PtrCommunication &communication)
void broadcastSend(mesh::Mesh::VertexDistribution const &m, const com::PtrCommunication &communication=utils::IntraComm::getCommunication())
static constexpr SynchronizeTag Synchronize
Convenience instance of the SynchronizeTag.
Definition Event.hpp:21
void set_intersection_indices(InputIt1 ref1, InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first)
This function is by and large the same as std::set_intersection(). The only difference is that we don...
Definition algorithm.hpp:34
int Rank
Definition Types.hpp:37
STL namespace.
T push_back(T... args)
T reserve(T... args)
T reset(T... args)
T setprecision(T... args)
T size(T... args)
T str(T... args)
T yield(T... args)