preCICE v3.2.0
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{
50 m.clear();
51 int size = 0;
52 communication->receive(size, rankSender);
53
54 while (size--) {
55 Rank rank = -1;
56 communication->receive(rank, rankSender);
57 m[rank] = communication->receiveRange(rankSender, com::asVector<int>);
58 }
59}
60
63{
64 communication->broadcast(static_cast<int>(m.size()));
65
66 for (auto const &i : m) {
67 auto const &rank = i.first;
68 auto const &indices = i.second;
69 communication->broadcast(rank);
70 communication->broadcast(indices);
71 }
72}
73
75 int rankBroadcaster,
77{
78 m.clear();
79 int size = 0;
80 communication->broadcast(size, rankBroadcaster);
81
82 while (size--) {
83 Rank rank = -1;
84 communication->broadcast(rank, rankBroadcaster);
85 communication->broadcast(m[rank], rankBroadcaster);
86 }
87}
88
90{
92 // Broadcast (send) vertex distributions.
94 } else if (utils::IntraComm::isSecondary()) {
95 // Broadcast (receive) vertex distributions.
97 }
98}
99
100void print(std::map<int, std::vector<int>> const &m)
101{
103
104 oss << "rank: " << utils::IntraComm::getRank() << "\n";
105
106 for (auto &i : m) {
107 for (auto &j : i.second) {
108 oss << i.first << ":" << j << '\n'; // prints rank:index
109 }
110 }
111
113 utils::IntraComm::getCommunication()->send(oss.str(), 0);
114 } else {
115
116 std::string s;
117
119 utils::IntraComm::getCommunication()->receive(s, rank);
120
121 oss << s;
122 }
123
124 std::cout << oss.str();
125 }
126}
127
129{
130 int size = m.size();
131
133 size_t count = 0;
134 size_t maximum = std::numeric_limits<size_t>::min();
135 size_t minimum = std::numeric_limits<size_t>::max();
136 size_t total = size;
137
138 if (size) {
139 maximum = std::max(maximum, static_cast<size_t>(size));
140 minimum = std::min(minimum, static_cast<size_t>(size));
141 count++;
142 }
143
145 utils::IntraComm::getCommunication()->receive(size, rank);
146
147 total += size;
148
149 if (size) {
150 maximum = std::max(maximum, static_cast<size_t>(size));
151 minimum = std::min(minimum, static_cast<size_t>(size));
152 count++;
153 }
154 }
155
156 if (minimum > maximum)
157 minimum = maximum;
158
159 auto average = static_cast<double>(total);
160 if (count != 0) {
161 average /= count;
162 }
163
164 boost::io::ios_all_saver ias{std::cout};
166 << "Number of Communication Partners per Interface Process:"
167 << "\n"
168 << " Total: " << total << "\n"
169 << " Maximum: " << maximum << "\n"
170 << " Minimum: " << minimum << "\n"
171 << " Average: " << average << "\n"
172 << "Number of Interface Processes: " << count << "\n"
173 << '\n';
174 } else {
176 utils::IntraComm::getCommunication()->send(size, 0);
177 }
178}
179
181{
182 int size = 0;
183
184 for (auto &i : m) {
185 size += i.second.size();
186 }
187
189 size_t count = 0;
190 size_t maximum = std::numeric_limits<size_t>::min();
191 size_t minimum = std::numeric_limits<size_t>::max();
192 size_t total = size;
193
194 if (size) {
195 maximum = std::max(maximum, static_cast<size_t>(size));
196 minimum = std::min(minimum, static_cast<size_t>(size));
197
198 count++;
199 }
200
202 utils::IntraComm::getCommunication()->receive(size, rank);
203
204 total += size;
205
206 if (size) {
207 maximum = std::max(maximum, static_cast<size_t>(size));
208 minimum = std::min(minimum, static_cast<size_t>(size));
209
210 count++;
211 }
212 }
213
214 if (minimum > maximum)
215 minimum = maximum;
216
217 auto average = static_cast<double>(total);
218 if (count != 0) {
219 average /= count;
220 }
221
222 boost::io::ios_all_saver ias{std::cout};
224 << "Number of LVDIs per Interface Process:"
225 << "\n"
226 << " Total: " << total << '\n'
227 << " Maximum: " << maximum << '\n'
228 << " Minimum: " << minimum << '\n'
229 << " Average: " << average << '\n'
230 << "Number of Interface Processes: " << count << '\n'
231 << '\n';
232 } else {
234
235 utils::IntraComm::getCommunication()->send(size, 0);
236 }
237}
238
262 // `thisVertexDistribution' is input vertex distribution from this participant.
263 mesh::Mesh::VertexDistribution const &thisVertexDistribution,
264 // `otherVertexDistribution' is input vertex distribution from other participant.
265 mesh::Mesh::VertexDistribution const &otherVertexDistribution,
266 int thisRank = utils::IntraComm::getRank())
267{
268 auto iterator = thisVertexDistribution.find(thisRank);
269 if (iterator == thisVertexDistribution.end()) {
270 return {};
271 }
272
273 std::map<int, std::vector<int>> communicationMap;
274 // first a safety check, that we are actually sorted, as the function below operates
275 // on sorted data sets
276 PRECICE_ASSERT(std::is_sorted(iterator->second.begin(), iterator->second.end()));
277
278 // now we iterate over all other vertex distributions to compute the intersection
279 for (const auto &[rank, vertices] : otherVertexDistribution) {
280 // first a safety check, that we are actually sorted, as the function below operates
281 // on sorted data sets
282 PRECICE_ASSERT(std::is_sorted(vertices.begin(), vertices.end()));
283
284 // before starting to compute an actual intersection, we first check if elements can
285 // possibly be in both data sets by comparing upper and lower index bounds of both
286 // data sets. For typical partitioning schemes, each rank only exchanges data with
287 // a few neighbors such that this check already filters out a significant amount of
288 // computations
289 if (iterator->second.empty() || vertices.empty() || (vertices.back() < iterator->second.at(0)) || (vertices.at(0) > iterator->second.back())) {
290 // in this case there is nothing to be done
291 continue;
292 }
293 // we have an intersection, let's compute it
294 std::vector<int> inters;
295 // the actual worker function, which gives us the indices of intersecting elements
296 // have a look at the documentation of the function for more details
297 precice::utils::set_intersection_indices(iterator->second.begin(), iterator->second.begin(), iterator->second.end(),
298 vertices.begin(), vertices.end(),
299 std::back_inserter(inters));
300 // we have the results, now commit it into the final map
301 if (!inters.empty()) {
302 communicationMap.insert({rank, std::move(inters)});
303 }
304 }
305 return communicationMap;
306}
307
315
321
323{
324 return _isConnected;
325}
326
328 std::string const &requesterName)
329{
330 PRECICE_TRACE(acceptorName, requesterName);
331 PRECICE_ASSERT(not isConnected(), "Already connected.");
332
333 mesh::Mesh::VertexDistribution vertexDistribution = _mesh->getVertexDistribution();
334 mesh::Mesh::VertexDistribution requesterVertexDistribution;
335
337 PRECICE_DEBUG("Exchange vertex distribution between both primary ranks");
338 Event e0("m2n.exchangeVertexDistribution");
339 // Establish connection between participants' primary processes.
340 auto c = _communicationFactory->newCommunication();
341
342 c->acceptConnection(acceptorName, requesterName, "TMP-PRIMARYCOM-" + _mesh->getName(), utils::IntraComm::getRank());
343
344 // Exchange vertex distributions.
345 m2n::send(vertexDistribution, 0, c);
346 m2n::receive(requesterVertexDistribution, 0, c);
347 }
348
349 PRECICE_DEBUG("Broadcast vertex distributions");
350 Event e1("m2n.broadcastVertexDistributions", profiling::Synchronize);
351 m2n::broadcast(vertexDistribution);
353 _mesh->setVertexDistribution(vertexDistribution);
354 }
355 m2n::broadcast(requesterVertexDistribution);
356 e1.stop();
357
358 // Local (for process rank in the current participant) communication map that
359 // defines a mapping from a process rank in the remote participant to an array
360 // of local data indices, which define a subset of local (for process rank in
361 // the current participant) data to be communicated between the current
362 // process rank and the remote process rank.
363 //
364 // Example. Assume that the current process rank is 3. Assume that its
365 // `communicationMap' is
366 //
367 // 1 -> {1, 3}
368 // 4 -> {0, 2}
369 //
370 // then it means that the current process (with rank 3)
371 // - has to communicate (send/receive) data with local indices 1 and 3 with
372 // the remote process with rank 1;
373 // - has to communicate (send/receive) data with local indices 0 and 2 with
374 // the remote process with rank 4.
375 Event e2("m2n.buildCommunicationMap", profiling::Synchronize);
377 vertexDistribution, requesterVertexDistribution);
378 e2.stop();
379
380// Print `communicationMap'.
381#ifdef P2P_LCM_PRINT
382 PRECICE_DEBUG("Print communication map");
383 print(communicationMap);
384#endif
385
386// Print statistics of `communicationMap'.
387#ifdef P2P_LCM_PRINT_STATS
388 PRECICE_DEBUG("Print communication map statistics");
389 printCommunicationPartnerCountStats(communicationMap);
390 printLocalIndexCountStats(communicationMap);
391#endif
392
393 Event e4("m2n.createCommunications");
394 e4.addData("Connections", communicationMap.size());
395 if (communicationMap.empty()) {
396 _isConnected = true;
397 return;
398 }
399
400 PRECICE_DEBUG("Create and connect communication");
401 _communication = _communicationFactory->newCommunication();
402
403 // Accept point-to-point connections (as server) between the current acceptor
404 // process (in the current participant) with rank `utils::IntraComm::getRank()'
405 // and (multiple) requester processes (in the requester participant).
406 _communication->acceptConnectionAsServer(acceptorName,
407 requesterName,
408 _mesh->getName(),
410 communicationMap.size());
411
412 PRECICE_DEBUG("Store communication map");
413 for (auto const &comMap : communicationMap) {
414 int globalRequesterRank = comMap.first;
415 auto indices = std::move(communicationMap[globalRequesterRank]);
416
417 _mappings.push_back({globalRequesterRank, std::move(indices), com::PtrRequest(), {}});
418 }
419 e4.stop();
420 _isConnected = true;
421}
422
424 std::string const &requesterName)
425{
426 PRECICE_TRACE(acceptorName, requesterName);
427 PRECICE_ASSERT(not isConnected(), "Already connected.");
428
429 const std::vector<int> &localConnectedRanks = _mesh->getConnectedRanks();
430
431 if (localConnectedRanks.empty()) {
432 _isConnected = true;
433 return;
434 }
435
436 _communication = _communicationFactory->newCommunication();
437
438 _communication->acceptConnectionAsServer(
439 acceptorName,
440 requesterName,
441 _mesh->getName(),
443 localConnectedRanks.size());
444
445 _connectionDataVector.reserve(localConnectedRanks.size());
446
447 for (int connectedRank : localConnectedRanks) {
448 _connectionDataVector.push_back({connectedRank, com::PtrRequest()});
449 }
450
451 _isConnected = true;
452}
453
455 std::string const &requesterName)
456{
457 PRECICE_TRACE(acceptorName, requesterName);
458 PRECICE_ASSERT(not isConnected(), "Already connected.");
459
460 mesh::Mesh::VertexDistribution vertexDistribution = _mesh->getVertexDistribution();
461 mesh::Mesh::VertexDistribution acceptorVertexDistribution;
462
464 PRECICE_DEBUG("Exchange vertex distribution between both primary ranks");
465 Event e0("m2n.exchangeVertexDistribution");
466 // Establish connection between participants' primary processes.
467 auto c = _communicationFactory->newCommunication();
468 c->requestConnection(acceptorName, requesterName,
469 "TMP-PRIMARYCOM-" + _mesh->getName(),
470 0, 1);
471
472 // Exchange vertex distributions.
473 m2n::receive(acceptorVertexDistribution, 0, c);
474 m2n::send(vertexDistribution, 0, c);
475 }
476
477 PRECICE_DEBUG("Broadcast vertex distributions");
478 Event e1("m2n.broadcastVertexDistributions", profiling::Synchronize);
479 m2n::broadcast(vertexDistribution);
481 _mesh->setVertexDistribution(vertexDistribution);
482 }
483 m2n::broadcast(acceptorVertexDistribution);
484 e1.stop();
485
486 // Local (for process rank in the current participant) communication map that
487 // defines a mapping from a process rank in the remote participant to an array
488 // of local data indices, which define a subset of local (for process rank in
489 // the current participant) data to be communicated between the current
490 // process rank and the remote process rank.
491 //
492 // Example. Assume that the current process rank is 3. Assume that its
493 // `communicationMap' is
494 //
495 // 1 -> {1, 3}
496 // 4 -> {0, 2}
497 //
498 // then it means that the current process (with rank 3)
499 // - has to communicate (send/receive) data with local indices 1 and 3 with
500 // the remote process with rank 1;
501 // - has to communicate (send/receive) data with local indices 0 and 2 with
502 // the remote process with rank 4.
503 Event e2("m2n.buildCommunicationMap", profiling::Synchronize);
505 vertexDistribution, acceptorVertexDistribution);
506 e2.stop();
507
508// Print `communicationMap'.
509#ifdef P2P_LCM_PRINT
510 PRECICE_DEBUG("Print communication map");
511 print(communicationMap);
512#endif
513
514// Print statistics of `communicationMap'.
515#ifdef P2P_LCM_PRINT_STATS
516 PRECICE_DEBUG("Print communication map statistics");
517 printCommunicationPartnerCountStats(communicationMap);
518 printLocalIndexCountStats(communicationMap);
519#endif
520
521 Event e4("m2n.createCommunications");
522 e4.addData("Connections", communicationMap.size());
523 if (communicationMap.empty()) {
524 _isConnected = true;
525 return;
526 }
527
529 requests.reserve(communicationMap.size());
530
531 std::set<int> acceptingRanks;
532 for (auto &i : communicationMap)
533 acceptingRanks.emplace(i.first);
534
535 PRECICE_DEBUG("Create and connect communication");
536 _communication = _communicationFactory->newCommunication();
537 // Request point-to-point connections (as client) between the current
538 // requester process (in the current participant) and (multiple) acceptor
539 // processes (in the acceptor participant) to ranks `accceptingRanks'
540 // according to `communicationMap`.
541 _communication->requestConnectionAsClient(acceptorName, requesterName,
542 _mesh->getName(),
543 acceptingRanks, utils::IntraComm::getRank());
544
545 PRECICE_DEBUG("Store communication map");
546 for (auto &i : communicationMap) {
547 auto globalAcceptorRank = i.first;
548 auto indices = std::move(i.second);
549
550 _mappings.push_back({globalAcceptorRank, std::move(indices), com::PtrRequest(), {}});
551 }
552 e4.stop();
553 _isConnected = true;
554}
555
557 std::string const &requesterName)
558{
559 PRECICE_TRACE(acceptorName, requesterName);
560 PRECICE_ASSERT(not isConnected(), "Already connected.");
561
562 std::vector<int> localConnectedRanks = _mesh->getConnectedRanks();
563
564 if (localConnectedRanks.empty()) {
565 _isConnected = true;
566 return;
567 }
568
570 requests.reserve(localConnectedRanks.size());
571 _connectionDataVector.reserve(localConnectedRanks.size());
572
573 std::set<int> acceptingRanks(localConnectedRanks.begin(), localConnectedRanks.end());
574
575 _communication = _communicationFactory->newCommunication();
576 _communication->requestConnectionAsClient(acceptorName, requesterName,
577 _mesh->getName(),
578 acceptingRanks, utils::IntraComm::getRank());
579
580 for (auto &connectedRank : localConnectedRanks) {
581 _connectionDataVector.push_back({connectedRank, com::PtrRequest()});
582 }
583 _isConnected = true;
584}
585
587{
588 mesh::Mesh::CommunicationMap localCommunicationMap = _mesh->getCommunicationMap();
589
590 for (auto &i : _connectionDataVector) {
591 _mappings.push_back({i.remoteRank, std::move(localCommunicationMap[i.remoteRank]), i.request, {}});
592 }
593}
594
596{
598
599 if (not isConnected())
600 return;
601
603
604 _communication.reset();
605 _mappings.clear();
606 _connectionDataVector.clear();
607 _isConnected = false;
608}
609
611{
612
613 if (_mappings.empty() || itemsToSend.empty()) {
614 return;
615 }
616
617 for (auto &mapping : _mappings) {
619 buffer->reserve(mapping.indices.size() * valueDimension);
620 for (auto index : mapping.indices) {
621 for (int d = 0; d < valueDimension; ++d) {
622 buffer->push_back(itemsToSend[index * valueDimension + d]);
623 }
624 }
625 auto request = _communication->aSend(span<const double>{*buffer}, mapping.remoteRank);
626 bufferedRequests.emplace_back(request, buffer);
627 }
629}
630
631void PointToPointCommunication::receive(precice::span<double> itemsToReceive, int valueDimension)
632{
633 if (_mappings.empty() || itemsToReceive.empty()) {
634 return;
635 }
636
637 std::fill(itemsToReceive.begin(), itemsToReceive.end(), 0.0);
638
639 for (auto &mapping : _mappings) {
640 mapping.recvBuffer.resize(mapping.indices.size() * valueDimension);
641 mapping.request = _communication->aReceive(span<double>{mapping.recvBuffer}, mapping.remoteRank);
642 }
643
644 for (auto &mapping : _mappings) {
645 mapping.request->wait();
646
647 int i = 0;
648 for (auto index : mapping.indices) {
649 for (int d = 0; d < valueDimension; ++d) {
650 itemsToReceive[index * valueDimension + d] += mapping.recvBuffer[i * valueDimension + d];
651 }
652 i++;
653 }
654 }
655}
656
658{
659 for (auto &connectionData : _connectionDataVector) {
660 _communication->send(itemToSend, connectionData.remoteRank);
661 }
662}
663
665
666{
667 int data = 0;
668 for (auto &connectionData : _connectionDataVector) {
669 _communication->receive(data, connectionData.remoteRank);
670 itemToReceive.push_back(data);
671 }
672}
673
675{
676 for (auto &connectionData : _connectionDataVector) {
677 com::sendMesh(*_communication, connectionData.remoteRank, *_mesh);
678 }
679}
680
682{
683 for (auto &connectionData : _connectionDataVector) {
684 com::receiveMesh(*_communication, connectionData.remoteRank, *_mesh);
685 }
686}
687
689{
690 for (auto &connectionData : _connectionDataVector) {
691 _communication->sendRange(localCommunicationMap[connectionData.remoteRank], connectionData.remoteRank);
692 }
693}
694
696{
697 for (auto &connectionData : _connectionDataVector) {
698 localCommunicationMap[connectionData.remoteRank] = _communication->receiveRange(connectionData.remoteRank, com::asVector<int>);
699 }
700}
701
703{
705 do {
706 for (auto it = bufferedRequests.begin(); it != bufferedRequests.end();) {
707 if (it->first->test())
708 it = bufferedRequests.erase(it);
709 else
710 ++it;
711 }
712 if (bufferedRequests.empty())
713 return;
714 if (blocking)
715 std::this_thread::yield(); // give up our time slice, so MPI may work
716 } while (blocking);
717}
718
719} // namespace precice::m2n
#define PRECICE_DEBUG(...)
Definition LogMacros.hpp:61
#define PRECICE_TRACE(...)
Definition LogMacros.hpp:92
#define PRECICE_ASSERT(...)
Definition assertion.hpp:85
T back_inserter(T... args)
T begin(T... args)
std::map< int, std::vector< int > > CommunicationMap
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...
std::map< Rank, std::vector< VertexID > > CommunicationMap
A mapping from remote local ranks to the IDs that must be communicated.
Definition Mesh.hpp:51
std::map< Rank, std::vector< VertexID > > VertexDistribution
A mapping from rank to used (not necessarily owned) vertex IDs.
Definition Mesh.hpp:48
void stop()
Stops a running event.
Definition Event.cpp:51
void addData(std::string_view key, int value)
Adds named integer data, associated to an event.
Definition Event.cpp:62
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 make_shared(T... args)
T max(T... args)
T min(T... args)
void sendMesh(Communication &communication, int rankReceiver, const mesh::Mesh &mesh)
Definition Extra.cpp:8
constexpr auto asVector
Allows to use Communication::AsVectorTag in a less verbose way.
std::shared_ptr< Request > PtrRequest
void receiveMesh(Communication &communication, int rankSender, mesh::Mesh &mesh)
Definition Extra.cpp:13
std::shared_ptr< CommunicationFactory > PtrCommunicationFactory
std::shared_ptr< Communication > PtrCommunication
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())
contains data mapping from points to meshes.
provides Mesh, Data and primitives.
std::shared_ptr< Mesh > PtrMesh
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:33
int Rank
Definition Types.hpp:37
STL namespace.
T push_back(T... args)
T reserve(T... args)
T setprecision(T... args)
T size(T... args)
T str(T... args)
T yield(T... args)