Loading...
Searching...
No Matches
PstreamGlobals.C
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) 2013-2015 OpenFOAM Foundation
9 Copyright (C) 2023-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/>.
27\*---------------------------------------------------------------------------*/
29#include "PstreamGlobals.H"
30
31// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
32
36
39
45
46
47// * * * * * * * * * * * * * * * Communicators * * * * * * * * * * * * * * * //
48
49void Foam::PstreamGlobals::initCommunicator(const label index)
50{
51 if (FOAM_UNLIKELY(index < 0 || index > MPICommunicators_.size()))
52 {
54 << "PstreamGlobals out of sync with UPstream data. Problem."
56 }
57 else if (index == MPICommunicators_.size())
58 {
59 // Extend storage with null values
60 pendingMPIFree_.emplace_back(false);
61 MPICommunicators_.emplace_back(MPI_COMM_NULL);
62 }
63 else
64 {
65 // Init with null values
66 pendingMPIFree_[index] = false;
67 MPICommunicators_[index] = MPI_COMM_NULL;
68 }
69}
70
71
72// * * * * * * * * * * * * * * * * Data Types * * * * * * * * * * * * * * * //
73
75{
76 static_assert
77 (
78 PstreamGlobals::DataTypeCountLookupTable::max_size()
79 == (int(UPstream::dataTypes::DataTypes_end)+1),
80 "Data count lookup table size != number of dataTypes enumerations"
81 );
82 static_assert
83 (
84 PstreamGlobals::DataTypeLookupTable::max_size()
85 == (int(UPstream::dataTypes::DataTypes_end)+1),
86 "Lookup table size != number of dataTypes enumerations"
87 );
88
89 // From enumeration to MPI datatype for fundamental types
90 // (count is always 1)
91 #undef defineType
92 #define defineType(Idx, BaseType) \
93 { \
94 dataTypesCount_[int(UPstream::dataTypes::Idx)] = 1; \
95 MPIdataTypes_[int(UPstream::dataTypes::Idx)] = BaseType; \
96 }
97
98 // Fundamental Types [10]:
99 defineType(type_byte, MPI_BYTE);
100 defineType(type_int16, MPI_INT16_T);
101 defineType(type_int32, MPI_INT32_T);
102 defineType(type_int64, MPI_INT64_T);
103 defineType(type_uint16, MPI_UINT16_T);
104 defineType(type_uint32, MPI_UINT32_T);
105 defineType(type_uint64, MPI_UINT64_T);
106 defineType(type_float, MPI_FLOAT);
107 defineType(type_double, MPI_DOUBLE);
108 defineType(type_long_double, MPI_LONG_DOUBLE);
109
110 #undef defineType
111
112 // User-define types
113 #undef defineUserType
114 #define defineUserType(Idx, Count, BaseType, Name) \
115 { \
116 dataTypesCount_[int(UPstream::dataTypes::Idx)] = Count; \
117 auto& dt = MPIdataTypes_[int(UPstream::dataTypes::Idx)]; \
118 MPI_Type_contiguous(Count, BaseType, &dt); \
119 MPI_Type_set_name(dt, Name); \
120 MPI_Type_commit(&dt); \
121 }
122
123 // User Types [6]:
124 defineUserType(type_3float, 3, MPI_FLOAT, "float[3]");
125 defineUserType(type_3double, 3, MPI_DOUBLE, "double[3]");
126 defineUserType(type_6float, 6, MPI_FLOAT, "float[6]");
127 defineUserType(type_6double, 6, MPI_DOUBLE, "double[6]");
128 defineUserType(type_9float, 9, MPI_FLOAT, "float[9]");
129 defineUserType(type_9double, 9, MPI_DOUBLE, "double[9]");
130
131 #undef defineUserType
132}
133
134
136{
137 // User types only
138 auto first =
139 (
140 MPIdataTypes_.begin() + int(UPstream::dataTypes::User_begin)
141 );
142 const auto last =
143 (
144 MPIdataTypes_.begin() + int(UPstream::dataTypes::User_end)
145 );
146
147 for (; first != last; ++first)
148 {
149 if (MPI_DATATYPE_NULL != *first)
150 {
151 MPI_Type_free(&(*first));
152 }
153 }
154}
155
156
157// Debugging
159{
160 // Check all types, not just user types
161 auto first =
162 (
164 );
165 const auto last =
166 (
167 MPIdataTypes_.begin() + int(UPstream::dataTypes::DataTypes_end)
168 );
169
170 for (; (first != last); ++first)
171 {
172 if (MPI_DATATYPE_NULL == *first)
173 {
174 return false;
175 }
177
178 return true;
179}
180
181
182// Debugging
184{
185 int rank = -1;
186 if
187 (
188 (MPI_SUCCESS != MPI_Comm_rank(MPI_COMM_WORLD, &rank))
189 || (rank != 0)
190 )
191 {
192 return;
193 }
194
195 const auto print = [&](auto firstIndex, auto lastIndex)
196 {
197 auto first =
198 (
199 PstreamGlobals::MPIdataTypes_.begin() + int(firstIndex)
200 );
201 const auto last =
202 (
203 PstreamGlobals::MPIdataTypes_.begin() + int(lastIndex)
204 );
205
206 for (; (first != last); ++first)
207 {
208 std::cerr
209 << " name = "
210 << PstreamGlobals::dataType_name(*first) << '\n';
211 }
212 };
213
214 if (all)
215 {
216 std::cerr << "enumerated data types:\n";
217 print
218 (
219 UPstream::dataTypes::Basic_begin,
220 UPstream::dataTypes::Basic_end
221 );
222 }
223 else
224 {
225 // User types only.
226 std::cerr << "enumerated user-defined data types:\n";
227 }
228 print
232 );
233}
234
235
236std::string Foam::PstreamGlobals::dataType_name(MPI_Datatype datatype)
237{
238 if (MPI_DATATYPE_NULL == datatype)
239 {
240 return std::string("(null)");
241 }
242
243 char buf[MPI_MAX_OBJECT_NAME];
244 int len;
245
246 if (MPI_SUCCESS == MPI_Type_get_name(datatype, buf, &len))
247 {
248 if (len > 0)
249 {
250 return std::string(buf, len);
251 }
252 else
253 {
254 return std::string("(anon)");
255 }
256 }
258 return std::string("???");
259}
260
261
262// * * * * * * * * * * * * * * * * Op Codes * * * * * * * * * * * * * * * * //
263
265{
266 static_assert
267 (
270 "Lookup table size != number of opCodes enumerations"
271 );
272
273 // From enumeration to MPI datatype
274 #undef defineCode
275 #define defineCode(Idx, CodeType) \
276 MPIopCodes_[int(UPstream::opCodes::Idx)] = CodeType;
277
278 defineCode(op_min, MPI_MIN);
279 defineCode(op_max, MPI_MAX);
280 defineCode(op_sum, MPI_SUM);
281 defineCode(op_prod, MPI_PROD);
282
283 // TBD: still need to sort out if they are MPI_C_BOOL or MPI_CXX_BOOL
284 // ...
285 defineCode(op_bool_and, MPI_LAND);
286 defineCode(op_bool_or, MPI_LOR);
287 defineCode(op_bool_xor, MPI_LXOR);
288
289 defineCode(op_bit_and, MPI_BAND);
290 defineCode(op_bit_or, MPI_BOR);
291 defineCode(op_bit_xor, MPI_BXOR);
292
293 // Do not include MPI_MINLOC, MPI_MAXLOC since they are tied to
294 // float_int, double_int and larger or other types
295
296 // window-only
297 defineCode(op_replace, MPI_REPLACE);
298 defineCode(op_no_op, MPI_NO_OP);
299
300 #undef defineCode
302
303
305{}
306
307
309{
310 auto first = MPIopCodes_.begin();
311 const auto last =
312 (
313 MPIopCodes_.begin() + int(UPstream::opCodes::OpCodes_end)
314 );
315
316 for (; (first != last); ++first)
317 {
318 if (MPI_OP_NULL == *first)
319 {
320 return false;
321 }
322 }
323
324 return true;
325}
326
327
328// ************************************************************************* //
#define defineType(Idx, BaseType)
#define defineCode(Idx, CodeType)
#define defineUserType(Idx, Count, BaseType, Name)
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
T & emplace_back(Args &&... args)
Construct an element at the end of the list, return reference to the new list element.
static constexpr unsigned max_size() noexcept
Definition FixedList.H:624
iterator begin() noexcept
Return an iterator to begin traversing the FixedList.
Definition FixedListI.H:478
@ OpCodes_end
(internal use) end marker [all types]
Definition UPstream.H:178
@ Basic_end
(internal use) end marker [basic types]
Definition UPstream.H:125
@ DataTypes_end
(internal use) end marker [all types]
Definition UPstream.H:139
@ User_begin
(internal use) begin marker [user types]
Definition UPstream.H:125
@ User_end
(internal use) end marker [user types]
Definition UPstream.H:139
@ Basic_begin
(internal use) begin marker [basic/all types]
Definition UPstream.H:112
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
Ostream & print(Ostream &os, UIntType value, char off='0', char on='1')
Print 0/1 bits in the (unsigned) integral type.
Definition BitOps.H:320
DynamicList< MPI_Request > outstandingRequests_
Outstanding non-blocking operations.
DataTypeCountLookupTable dataTypesCount_
Fundamental count for each valid UPstream::dataTypes entry Indexed by UPstream::dataTypes enum.
std::string dataType_name(MPI_Datatype datatype)
Return MPI internal name for specified MPI_Datatype.
bool checkOpCodes()
Debugging only: check if op code mappings are non-null.
DynamicList< bool > pendingMPIFree_
OpCodesLookupTable MPIopCodes_
MPI operation types, indexed by UPstream::opCodes enum.
DynamicList< MPI_Comm > MPICommunicators_
void initOpCodes()
Create mapping into MPIopCodes_.
void printDataTypes(bool all=false)
Debugging only: print data type names (all or just user-defined).
Foam::FixedList< MPI_Op, 13 > OpCodesLookupTable
void deinitOpCodes()
Free any user-defined op codes.
void deinitDataTypes()
Free any user data types.
Foam::FixedList< MPI_Datatype, 17 > DataTypeLookupTable
Foam::FixedList< int, 17 > DataTypeCountLookupTable
void initDataTypes()
Create mapping into MPIdataTypes_ and define user data types.
bool checkDataTypes()
Debugging only: check if data type mappings are non-null.
void initCommunicator(const label index)
Initialize bookkeeping for MPI communicator index.
DataTypeLookupTable MPIdataTypes_
MPI data types corresponding to fundamental and OpenFOAM types. Indexed by UPstream::dataTypes enum.
errorManip< error > abort(error &err)
Definition errorManip.H:139
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
#define FOAM_UNLIKELY(cond)
Definition stdFoam.H:64