preCICE v3.2.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
IntraComm.cpp
Go to the documentation of this file.
1// #ifndef PRECICE_NO_MPI
2
3#include <Eigen/Core>
4#include <cmath>
5#include <memory>
6#include <ostream>
7#include <string>
8
9#include "IntraComm.hpp"
10#include "com/Communication.hpp"
11#include "logging/LogMacros.hpp"
12#include "logging/Logger.hpp"
14#include "utils/assertion.hpp"
15#include "utils/span_tools.hpp"
16
17namespace precice {
18
19extern bool syncMode;
20
21namespace utils {
22
24int IntraComm::_size = -1;
25bool IntraComm::_isPrimaryRank = false;
28
29logging::Logger IntraComm::_log("utils::IntraComm");
30
31void IntraComm::configure(Rank rank, int size)
32{
33 PRECICE_TRACE(rank, size);
34 _rank = rank;
35 _size = size;
36 PRECICE_ASSERT(_rank != -1 && _size != -1);
37 _isPrimaryRank = (rank == 0) && _size != 1;
38 _isSecondaryRank = (rank != 0);
39 PRECICE_DEBUG("isSecondaryRank: {}, isPrimaryRank: {}", _isSecondaryRank, _isPrimaryRank);
40}
41
43{
44 return _rank;
45}
46
48{
49 return _size;
50}
51
53{
54 return _isPrimaryRank;
55}
56
58{
59 return _isSecondaryRank;
60}
61
66
67double IntraComm::l2norm(const Eigen::VectorXd &vec)
68{
70
71 if (not _isPrimaryRank && not _isSecondaryRank) { // old case
72 return vec.norm();
73 }
74
75 PRECICE_ASSERT(_communication.get() != nullptr);
76 PRECICE_ASSERT(_communication->isConnected());
77
78 double globalSum2 = 0.0;
79 double localSum2 = vec.squaredNorm();
80
81 // localSum is modified, do not use afterwards
82 allreduceSum(localSum2, globalSum2);
83 /* old loop over all secondary ranks solution
84 if(_isSecondaryRank){
85 _communication->send(localSum2, 0);
86 _communication->receive(globalSum2, 0);
87 }
88 if(_isPrimaryRank){
89 globalSum2 += localSum2;
90 for(Rank secondaryRank = 1; secondaryRank < _size; secondaryRank++){
91 _communication->receive(localSum2, secondaryRank);
92 globalSum2 += localSum2;
93 }
94 for(Rank secondaryRank = 1; secondaryRank < _size; secondaryRank++){
95 _communication->send(globalSum2, secondaryRank);
96 }
97 }
98 */
99 return sqrt(globalSum2);
100}
101
102double IntraComm::dot(const Eigen::VectorXd &vec1, const Eigen::VectorXd &vec2)
103{
105
106 if (not _isPrimaryRank && not _isSecondaryRank) { // old case
107 return vec1.dot(vec2);
108 }
109
110 PRECICE_ASSERT(_communication.get() != nullptr);
111 PRECICE_ASSERT(_communication->isConnected());
112 PRECICE_ASSERT(vec1.size() == vec2.size(), vec1.size(), vec2.size());
113
114 double globalSum = 0.0;
115 double localSum = vec1.dot(vec2);
116
117 // localSum is modified, do not use afterwards
118 allreduceSum(localSum, globalSum);
119
120 // old loop over all secondary ranks solution
121 /*
122 if(_isSecondaryRank){
123 _communication->send(localSum, 0);
124 _communication->receive(globalSum, 0);
125 }
126 if(_isPrimaryRank){
127 globalSum += localSum;
128 for(Rank secondaryRank = 1; secondaryRank < _size; secondaryRank++){
129 _communication->receive(localSum, secondaryRank);
130 globalSum += localSum;
131 }
132 for(Rank secondaryRank = 1; secondaryRank < _size; secondaryRank++){
133 _communication->send(globalSum, secondaryRank);
134 }
135 }
136 */
137 return globalSum;
138}
139
141{
143 _isPrimaryRank = false;
144 _isSecondaryRank = false;
145 _rank = -1;
146 _size = -1;
147}
148
150{
152
153 if (not _isPrimaryRank && not _isSecondaryRank) {
154 std::copy(sendData.begin(), sendData.end(), rcvData.begin());
155 return;
156 }
157
158 PRECICE_ASSERT(_communication.get() != nullptr);
159 PRECICE_ASSERT(_communication->isConnected());
160
161 if (_isSecondaryRank) {
162 // send local result to primary rank
163 _communication->reduceSum(sendData, rcvData, 0);
164 }
165
166 if (_isPrimaryRank) {
167 // receive local results from secondary ranks, apply SUM
168 _communication->reduceSum(sendData, rcvData);
169 }
170}
171
172void IntraComm::reduceSum(const double &sendData, double &rcvData)
173{
175 reduceSum(precice::refToSpan<const double>(sendData),
176 precice::refToSpan<double>(rcvData));
177}
178
179void IntraComm::reduceSum(const int &sendData, int &rcvData)
180{
182
183 if (not _isPrimaryRank && not _isSecondaryRank) {
184 rcvData = sendData;
185 return;
186 }
187
188 PRECICE_ASSERT(_communication.get() != nullptr);
189 PRECICE_ASSERT(_communication->isConnected());
190
191 if (_isSecondaryRank) {
192 // send local result to primary rank
193 _communication->reduceSum(sendData, rcvData, 0);
194 }
195
196 if (_isPrimaryRank) {
197 // receive local results from secondary ranks, apply SUM
198 _communication->reduceSum(sendData, rcvData);
199 }
200}
201
203{
205
206 if (not _isPrimaryRank && not _isSecondaryRank) {
207 std::copy(sendData.begin(), sendData.end(), rcvData.begin());
208 return;
209 }
210
211 PRECICE_ASSERT(_communication.get() != nullptr);
212 PRECICE_ASSERT(_communication->isConnected());
213
214 if (_isSecondaryRank) {
215 // send local result to primary rank, receive reduced result from primary rank
216 _communication->allreduceSum(sendData, rcvData, 0);
217 }
218
219 if (_isPrimaryRank) {
220 // receive local results from secondary ranks, apply SUM, send reduced result to secondary ranks
221 _communication->allreduceSum(sendData, rcvData);
222 }
223}
224
225void IntraComm::allreduceSum(double &sendData, double &rcvData)
226{
228
229 if (not _isPrimaryRank && not _isSecondaryRank) {
230 rcvData = sendData;
231 return;
232 }
233
234 PRECICE_ASSERT(_communication.get() != nullptr);
235 PRECICE_ASSERT(_communication->isConnected());
236
237 if (_isSecondaryRank) {
238 // send local result to primary rank, receive reduced result from primary rank
239 _communication->allreduceSum(sendData, rcvData, 0);
240 }
241
242 if (_isPrimaryRank) {
243 // receive local results from secondary ranks, apply SUM, send reduced result to secondary ranks
244 _communication->allreduceSum(sendData, rcvData);
245 }
246}
247
248void IntraComm::allreduceSum(int &sendData, int &rcvData)
249{
251
252 if (not _isPrimaryRank && not _isSecondaryRank) {
253 rcvData = sendData;
254 return;
255 }
256
257 PRECICE_ASSERT(_communication.get() != nullptr);
258 PRECICE_ASSERT(_communication->isConnected());
259
260 if (_isSecondaryRank) {
261 // send local result to primary rank, receive reduced result from primary rank
262 _communication->allreduceSum(sendData, rcvData, 0);
263 }
264
265 if (_isPrimaryRank) {
266 // receive local results from secondary ranks, apply SUM, send reduced result to secondary ranks
267 _communication->allreduceSum(sendData, rcvData);
268 }
269}
270
272{
274
275 if (not _isPrimaryRank && not _isSecondaryRank) {
276 return;
277 }
278
279 PRECICE_ASSERT(_communication.get() != nullptr);
280 PRECICE_ASSERT(_communication->isConnected());
281
282 if (_isPrimaryRank) {
283 // Broadcast (send) value.
284 _communication->broadcast(values);
285 }
286
287 if (_isSecondaryRank) {
288 // Broadcast (receive) value.
289 _communication->broadcast(values, 0);
290 }
291}
292
293void IntraComm::broadcast(bool &value)
294{
296
297 if (not _isPrimaryRank && not _isSecondaryRank) {
298 return;
299 }
300
301 PRECICE_ASSERT(_communication.get() != nullptr);
302 PRECICE_ASSERT(_communication->isConnected());
303
304 if (_isPrimaryRank) {
305 // Broadcast (send) value.
306 _communication->broadcast(value);
307 }
308
309 if (_isSecondaryRank) {
310 // Broadcast (receive) value.
311 _communication->broadcast(value, 0);
312 }
313}
314
315void IntraComm::broadcast(double &value)
316{
318
319 if (not _isPrimaryRank && not _isSecondaryRank) {
320 return;
321 }
322
323 PRECICE_ASSERT(_communication.get() != nullptr);
324 PRECICE_ASSERT(_communication->isConnected());
325
326 if (_isPrimaryRank) {
327 // Broadcast (send) value.
328 _communication->broadcast(value);
329 }
330
331 if (_isSecondaryRank) {
332 // Broadcast (receive) value.
333 _communication->broadcast(value, 0);
334 }
335}
336
337void IntraComm::broadcast(int &value)
338{
340
341 if (not _isPrimaryRank && not _isSecondaryRank) {
342 return;
343 }
344
345 PRECICE_ASSERT(_communication.get() != nullptr);
346 PRECICE_ASSERT(_communication->isConnected());
347
348 if (_isPrimaryRank) {
349 // Broadcast (send) value.
350 _communication->broadcast(value);
351 }
352
353 if (_isSecondaryRank) {
354 // Broadcast (receive) value.
355 _communication->broadcast(value, 0);
356 }
357}
358
360{
362
363 if (precice::syncMode) {
364 barrier();
365 }
366}
367
372
374{
376
377 if (!isParallel())
378 return;
379
380 int local = 1;
381 int sum = -1;
382 allreduceSum(local, sum);
383 PRECICE_ASSERT(sum == _size);
384}
385
386} // namespace utils
387} // namespace precice
#define PRECICE_DEBUG(...)
Definition LogMacros.hpp:61
#define PRECICE_TRACE(...)
Definition LogMacros.hpp:92
#define PRECICE_ASSERT(...)
Definition assertion.hpp:85
A C++ 11 implementation of the non-owning C++20 std::span type.
Definition span.hpp:284
constexpr iterator begin() const noexcept
Definition span.hpp:503
constexpr iterator end() const noexcept
Definition span.hpp:505
static bool _isPrimaryRank
True if this process is running the primary rank.
static void barrier()
Synchronizes all ranks.
static void allreduceSum(precice::span< const double > sendData, precice::span< double > rcvData)
static bool _isSecondaryRank
True if this process is running a secondary rank.
static int _size
Number of ranks. This includes ranks from both participants, e.g. minimal size is 2.
static int getSize()
Number of ranks. This includes ranks from both participants, e.g. minimal size is 2.
Definition IntraComm.cpp:47
static double l2norm(const Eigen::VectorXd &vec)
The l2 norm of a vector is calculated on distributed data.
Definition IntraComm.cpp:67
static Rank getRank()
Current rank.
Definition IntraComm.cpp:42
static bool willSynchronize()
static double dot(const Eigen::VectorXd &vec1, const Eigen::VectorXd &vec2)
static bool isPrimary()
True if this process is running the primary rank.
Definition IntraComm.cpp:52
static void broadcast(bool &value)
static com::PtrCommunication _communication
Intra-participant communication.
static Rank _rank
Current rank.
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
static logging::Logger _log
static void configure(Rank rank, int size)
Configures the intra-participant communication.
Definition IntraComm.cpp:31
static void reduceSum(precice::span< const double > sendData, precice::span< double > rcvData)
T copy(T... args)
T get(T... args)
std::shared_ptr< Communication > PtrCommunication
Main namespace of the precice library.
int Rank
Definition Types.hpp:37
bool syncMode
Enabled further inter- and intra-solver synchronisation.