preCICE v3.1.2
Loading...
Searching...
No Matches
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 double localSum2 = 0.0;
78 double globalSum2 = 0.0;
79
80 for (int i = 0; i < vec.size(); i++) {
81 localSum2 += vec(i) * vec(i);
82 }
83
84 // localSum is modified, do not use afterwards
85 allreduceSum(localSum2, globalSum2);
86 /* old loop over all secondary ranks solution
87 if(_isSecondaryRank){
88 _communication->send(localSum2, 0);
89 _communication->receive(globalSum2, 0);
90 }
91 if(_isPrimaryRank){
92 globalSum2 += localSum2;
93 for(Rank secondaryRank = 1; secondaryRank < _size; secondaryRank++){
94 _communication->receive(localSum2, secondaryRank);
95 globalSum2 += localSum2;
96 }
97 for(Rank secondaryRank = 1; secondaryRank < _size; secondaryRank++){
98 _communication->send(globalSum2, secondaryRank);
99 }
100 }
101 */
102 return sqrt(globalSum2);
103}
104
105double IntraComm::dot(const Eigen::VectorXd &vec1, const Eigen::VectorXd &vec2)
106{
108
109 if (not _isPrimaryRank && not _isSecondaryRank) { //old case
110 return vec1.dot(vec2);
111 }
112
113 PRECICE_ASSERT(_communication.get() != nullptr);
114 PRECICE_ASSERT(_communication->isConnected());
115 PRECICE_ASSERT(vec1.size() == vec2.size(), vec1.size(), vec2.size());
116 double localSum = 0.0;
117 double globalSum = 0.0;
118
119 for (int i = 0; i < vec1.size(); i++) {
120 localSum += vec1(i) * vec2(i);
121 }
122
123 // localSum is modified, do not use afterwards
124 allreduceSum(localSum, globalSum);
125
126 // old loop over all secondary ranks solution
127 /*
128 if(_isSecondaryRank){
129 _communication->send(localSum, 0);
130 _communication->receive(globalSum, 0);
131 }
132 if(_isPrimaryRank){
133 globalSum += localSum;
134 for(Rank secondaryRank = 1; secondaryRank < _size; secondaryRank++){
135 _communication->receive(localSum, secondaryRank);
136 globalSum += localSum;
137 }
138 for(Rank secondaryRank = 1; secondaryRank < _size; secondaryRank++){
139 _communication->send(globalSum, secondaryRank);
140 }
141 }
142 */
143 return globalSum;
144}
145
147{
149 _isPrimaryRank = false;
150 _isSecondaryRank = false;
151 _rank = -1;
152 _size = -1;
153}
154
156{
158
159 if (not _isPrimaryRank && not _isSecondaryRank) {
160 std::copy(sendData.begin(), sendData.end(), rcvData.begin());
161 return;
162 }
163
164 PRECICE_ASSERT(_communication.get() != nullptr);
165 PRECICE_ASSERT(_communication->isConnected());
166
167 if (_isSecondaryRank) {
168 // send local result to primary rank
169 _communication->reduceSum(sendData, rcvData, 0);
170 }
171
172 if (_isPrimaryRank) {
173 // receive local results from secondary ranks, apply SUM
174 _communication->reduceSum(sendData, rcvData);
175 }
176}
177
178void IntraComm::reduceSum(const double &sendData, double &rcvData)
179{
181 reduceSum(precice::refToSpan<const double>(sendData),
182 precice::refToSpan<double>(rcvData));
183}
184
185void IntraComm::reduceSum(const int &sendData, int &rcvData)
186{
188
189 if (not _isPrimaryRank && not _isSecondaryRank) {
190 rcvData = sendData;
191 return;
192 }
193
194 PRECICE_ASSERT(_communication.get() != nullptr);
195 PRECICE_ASSERT(_communication->isConnected());
196
197 if (_isSecondaryRank) {
198 // send local result to primary rank
199 _communication->reduceSum(sendData, rcvData, 0);
200 }
201
202 if (_isPrimaryRank) {
203 // receive local results from secondary ranks, apply SUM
204 _communication->reduceSum(sendData, rcvData);
205 }
206}
207
209{
211
212 if (not _isPrimaryRank && not _isSecondaryRank) {
213 std::copy(sendData.begin(), sendData.end(), rcvData.begin());
214 return;
215 }
216
217 PRECICE_ASSERT(_communication.get() != nullptr);
218 PRECICE_ASSERT(_communication->isConnected());
219
220 if (_isSecondaryRank) {
221 // send local result to primary rank, receive reduced result from primary rank
222 _communication->allreduceSum(sendData, rcvData, 0);
223 }
224
225 if (_isPrimaryRank) {
226 // receive local results from secondary ranks, apply SUM, send reduced result to secondary ranks
227 _communication->allreduceSum(sendData, rcvData);
228 }
229}
230
231void IntraComm::allreduceSum(double &sendData, double &rcvData)
232{
234
235 if (not _isPrimaryRank && not _isSecondaryRank) {
236 rcvData = sendData;
237 return;
238 }
239
240 PRECICE_ASSERT(_communication.get() != nullptr);
241 PRECICE_ASSERT(_communication->isConnected());
242
243 if (_isSecondaryRank) {
244 // send local result to primary rank, receive reduced result from primary rank
245 _communication->allreduceSum(sendData, rcvData, 0);
246 }
247
248 if (_isPrimaryRank) {
249 // receive local results from secondary ranks, apply SUM, send reduced result to secondary ranks
250 _communication->allreduceSum(sendData, rcvData);
251 }
252}
253
254void IntraComm::allreduceSum(int &sendData, int &rcvData)
255{
257
258 if (not _isPrimaryRank && not _isSecondaryRank) {
259 rcvData = sendData;
260 return;
261 }
262
263 PRECICE_ASSERT(_communication.get() != nullptr);
264 PRECICE_ASSERT(_communication->isConnected());
265
266 if (_isSecondaryRank) {
267 // send local result to primary rank, receive reduced result from primary rank
268 _communication->allreduceSum(sendData, rcvData, 0);
269 }
270
271 if (_isPrimaryRank) {
272 // receive local results from secondary ranks, apply SUM, send reduced result to secondary ranks
273 _communication->allreduceSum(sendData, rcvData);
274 }
275}
276
278{
280
281 if (not _isPrimaryRank && not _isSecondaryRank) {
282 return;
283 }
284
285 PRECICE_ASSERT(_communication.get() != nullptr);
286 PRECICE_ASSERT(_communication->isConnected());
287
288 if (_isPrimaryRank) {
289 // Broadcast (send) value.
290 _communication->broadcast(values);
291 }
292
293 if (_isSecondaryRank) {
294 // Broadcast (receive) value.
295 _communication->broadcast(values, 0);
296 }
297}
298
299void IntraComm::broadcast(bool &value)
300{
302
303 if (not _isPrimaryRank && not _isSecondaryRank) {
304 return;
305 }
306
307 PRECICE_ASSERT(_communication.get() != nullptr);
308 PRECICE_ASSERT(_communication->isConnected());
309
310 if (_isPrimaryRank) {
311 // Broadcast (send) value.
312 _communication->broadcast(value);
313 }
314
315 if (_isSecondaryRank) {
316 // Broadcast (receive) value.
317 _communication->broadcast(value, 0);
318 }
319}
320
321void IntraComm::broadcast(double &value)
322{
324
325 if (not _isPrimaryRank && not _isSecondaryRank) {
326 return;
327 }
328
329 PRECICE_ASSERT(_communication.get() != nullptr);
330 PRECICE_ASSERT(_communication->isConnected());
331
332 if (_isPrimaryRank) {
333 // Broadcast (send) value.
334 _communication->broadcast(value);
335 }
336
337 if (_isSecondaryRank) {
338 // Broadcast (receive) value.
339 _communication->broadcast(value, 0);
340 }
341}
342
343void IntraComm::broadcast(int &value)
344{
346
347 if (not _isPrimaryRank && not _isSecondaryRank) {
348 return;
349 }
350
351 PRECICE_ASSERT(_communication.get() != nullptr);
352 PRECICE_ASSERT(_communication->isConnected());
353
354 if (_isPrimaryRank) {
355 // Broadcast (send) value.
356 _communication->broadcast(value);
357 }
358
359 if (_isSecondaryRank) {
360 // Broadcast (receive) value.
361 _communication->broadcast(value, 0);
362 }
363}
364
366{
368
369 if (precice::syncMode) {
370 barrier();
371 }
372}
373
375{
377
378 if (!isParallel())
379 return;
380
381 int local = 1;
382 int sum = -1;
383 allreduceSum(local, sum);
384 PRECICE_ASSERT(sum == _size);
385}
386
387} // namespace utils
388} // namespace precice
#define PRECICE_DEBUG(...)
Definition LogMacros.hpp:64
#define PRECICE_TRACE(...)
Definition LogMacros.hpp:95
#define PRECICE_ASSERT(...)
Definition assertion.hpp:87
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 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.
Definition IntraComm.hpp:98
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
Definition IntraComm.hpp:95
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.