Loading...
Searching...
No Matches
PstreamReduceOps.H
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2016 OpenFOAM Foundation
9 Copyright (C) 2016-2025 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27InNamespace
28 Foam
29
30Description
31 Inter-processor communication reduction functions.
32
33\*---------------------------------------------------------------------------*/
34
35#ifndef Foam_PstreamReduceOps_H
36#define Foam_PstreamReduceOps_H
37
38#include "Pstream.H"
39#include "FixedList.H"
40#include "ops.H"
41#include "VectorSpaceOps.H"
42
43// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
44
45namespace Foam
46{
47
48// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
49
50// Single value: mpiAllReduce or manual
51
52//- Reduce inplace (cf. MPI Allreduce)
53template<class T, class BinaryOp>
54void reduce
55(
56 T& value,
57 [[maybe_unused]] BinaryOp bop,
58 [[maybe_unused]] const int tag = UPstream::msgType(),
59 const int communicator = UPstream::worldComm
60)
61{
62 if (!UPstream::is_parallel(communicator))
63 {
64 // Nothing to do
65 return;
66 }
68 {
69 // Valid opcode and (directly/indirectly) uses basic dataType
71 (
72 &value,
73 1,
75 communicator
76 );
77 }
78 else
79 {
80 if (UPstream::warnComm >= 0 && communicator != UPstream::warnComm)
81 {
82 Perr<< "** reducing:" << value << " comm:" << communicator << endl;
84 }
85 Pstream::gather(value, bop, tag, communicator);
86 Pstream::broadcast(value, communicator);
87 }
88}
89
90
91// Multiple values: mpiAllReduce only!
92
93//- Reduce inplace (cf. MPI Allreduce)
94//- multiple values (same size on all ranks!)
95template<class T, class BinaryOp>
96void reduce
97(
98 T values[],
99 const int count,
100 [[maybe_unused]] BinaryOp bop,
101 [[maybe_unused]] const int tag,
102 const int communicator = UPstream::worldComm
103)
104{
105 if (!UPstream::is_parallel(communicator))
106 {
107 // Nothing to do
108 return;
109 }
111 {
112 // Valid opcode and (directly/indirectly) uses basic dataType
114 (
115 values,
116 count,
118 communicator
119 );
120 }
121 else
122 {
123 // static_assert(false, "unsupported data type");
124 static_assert
125 (
127 "only for specific, contiguous, known data types"
128 );
129 }
130}
131
132
133//- Reduce multiple values
134// Multiple values: mpiAllReduce only!
135template<class T, unsigned N, class BinaryOp>
136inline void reduce
138 FixedList<T, N>& values,
139 BinaryOp bop,
140 const int tag = UPstream::msgType(),
141 const int communicator = UPstream::worldComm
142)
143{
144 reduce(values.data(), int(values.size()), bop, tag, communicator);
145}
146
147
148//- Non-blocking reduce inplace (cf. MPI Iallreduce)
149//- multiple values. Sets request.
150template<class T, class BinaryOp>
151void reduce
152(
153 T values[],
154 int count,
155 [[maybe_unused]] BinaryOp bop,
156 [[maybe_unused]] const int tag,
157 const int communicator,
159)
160{
161 if (!UPstream::is_parallel(communicator))
162 {
163 // Nothing to do
164 return;
165 }
167 {
168 // Valid opcode and (directly/indirectly) uses basic dataType
170 (
171 values,
172 count,
174 communicator,
175 req
176 );
177 }
178 else
179 {
180 // static_assert(false, "unsupported data type");
181 static_assert
182 (
184 "only for specific, contiguous, known data types"
185 );
186 }
187}
188
189
190//- Non-blocking reduce inplace (cf. MPI Iallreduce)
191//- single value. Sets request.
192template<class T, class BinaryOp>
193void reduce
194(
195 T& value,
196 BinaryOp bop,
197 const int tag,
198 const int communicator,
200)
201{
202 // single value
203 reduce(&value, 1, tag, communicator, req);
204}
205
206
207// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
208
209// Special reductions for bool
210
211//- Logical (and) inplace reduction. Uses UPstream::reduceAnd
212void reduce
213(
214 bool& value,
216 [[maybe_unused]] const int tag = UPstream::msgType(),
217 const int communicator = UPstream::worldComm
218);
219// UPstream::reduceAnd(value, communicator);
220
221
222//- Logical (or) inplace reduction. Uses UPstream::reduceOr
223void reduce
224(
225 bool& value,
227 [[maybe_unused]] const int tag = UPstream::msgType(),
228 const int communicator = UPstream::worldComm
229);
230// UPstream::reduceOr(value, communicator);
231
232
233// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
234
235//- Reduce inplace (cf. MPI Allreduce)
236//- the sum of value and counter (eg, for averaging)
237// \note the summed counter value may lose some precision if components
238// of the main value are narrower. This is usually not the case.
239template<class T, class CountType = int>
240void sumReduce
241(
243 T& value,
245 CountType& count,
246 [[maybe_unused]] const int tag = UPstream::msgType(),
247 const int communicator = UPstream::worldComm
248)
249{
250 static_assert(std::is_arithmetic_v<CountType>, "Counter not arithmetic");
251
252 if (!UPstream::is_parallel(communicator))
253 {
254 // Nothing to do
255 return;
256 }
257 else if constexpr (std::is_floating_point_v<T>)
258 {
259 // Bundle value and count together
260 T work[2];
261 work[0] = value;
262 work[1] = static_cast<T>(count);
263
265 (
266 work,
267 2,
269 communicator
270 );
271
272 // Unbundle
273 value = work[0];
274 count = static_cast<CountType>(work[1]);
275 }
276 else if constexpr
277 (
279 && std::is_floating_point_v<typename pTraits_cmptType<T>::type>
280 )
281 {
282 constexpr auto nCmpts = pTraits_nComponents<T>::value;
283 using cmpt = typename pTraits_cmptType<T>::type;
284
285 // Bundle all components and count together
286 cmpt work[nCmpts+1];
287 VectorSpaceOps<nCmpts>::copy_n(value.begin(), work);
288 work[nCmpts] = static_cast<cmpt>(count);
289
291 (
292 work,
293 nCmpts+1,
295 communicator
296 );
297
298 // Unbundle
299 VectorSpaceOps<nCmpts>::copy_n(work, value.begin());
300 count = static_cast<CountType>(work[nCmpts]);
301 }
302 else
303 {
304 Foam::reduce(value, sumOp<T>(), tag, communicator);
305 Foam::reduce(count, sumOp<CountType>(), tag, communicator);
306 }
307}
308
309
310// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
311
312// Convenience wrappers - defined after all specialisations are known
313
314//- Perform reduction on a copy, using specified binary operation
315// \return the resulting value
316template<class T, class BinaryOp>
318(
319 const T& value,
320 BinaryOp bop,
321 const int tag = UPstream::msgType(),
322 const int communicator = UPstream::worldComm
323)
324{
325 T work(value);
326 Foam::reduce(work, bop, tag, communicator);
327 return work;
328}
329
330
331//- Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd
332// \return the resulting value
333inline bool returnReduceAnd
334(
335 const bool value,
336 const int communicator = UPstream::worldComm
337)
338{
339 bool work(value);
340 UPstream::reduceAnd(work, communicator);
341 return work;
342}
343
344
345//- Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr
346// \return the resulting value
347inline bool returnReduceOr
348(
349 const bool value,
350 const int communicator = UPstream::worldComm
352{
353 bool work(value);
354 UPstream::reduceOr(work, communicator);
355 return work;
356}
357
358
359// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
360
361} // End namespace Foam
362
363// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
364
365#endif
366
367// ************************************************************************* //
A 1D vector of objects of type <T> with a fixed length <N>.
Definition FixedList.H:73
An opaque wrapper for MPI_Request with a vendor-independent representation without any <mpi....
Definition UPstream.H:2919
static label warnComm
Debugging: warn for use of any communicator differing from warnComm.
Definition UPstream.H:1074
static int & msgType() noexcept
Message tag of standard messages.
Definition UPstream.H:1926
static void reduceAnd(bool &value, const int communicator=worldComm)
Logical (and) reduction (MPI_AllReduce).
static void mpiAllReduce(T values[], int count, const UPstream::opCodes opCodeId, const int communicator)
MPI_Allreduce (blocking) for known operators.
static void reduceOr(bool &value, const int communicator=worldComm)
Logical (or) reduction (MPI_AllReduce).
static bool is_parallel(const label communicator=worldComm)
True if parallel algorithm or exchange is required.
Definition UPstream.H:1743
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition UPstream.H:1069
@ gather
gather/all-gather [MPI]
Definition UPstream.H:191
@ broadcast
broadcast [MPI]
Definition UPstream.H:189
static void printStack(Ostream &os, int size=-1)
Helper function to print a stack, with optional upper limit.
const volScalarField & T
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of 'true' entries.
Definition BitOps.H:73
Namespace for OpenFOAM.
bool returnReduceOr(const bool value, const int communicator=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
prefixOSstream Perr
OSstream wrapped stderr (std::cerr) with parallel prefix.
T returnReduce(const T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
constexpr bool is_vectorspace_v
The is_vectorspace value of Type.
Definition pTraits.H:244
void reduce(T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce).
bool returnReduceAnd(const bool value, const int communicator=UPstream::worldComm)
Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd.
void sumReduce(T &value, CountType &count, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce) the sum of value and counter (eg, for averaging).
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
constexpr bool dependent_false_v
Map any dependent type to false (workaround before CWG2518).
Definition stdFoam.H:181
Various functors for unary and binary operations. Can be used for parallel combine-reduce operations ...
Combined query of opType and the underlying basic data type.
static constexpr auto opcode_id
static void copy_n(Input input, Output result)
Somewhat equivalent to std::copy_n() but with templated loops.
The vector-space number of components: default is 1.
Definition pTraits.H:140