Loading...
Searching...
No Matches
UPstreamTraits.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) 2025 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26Description
27 A set of traits associated with UPstream communication
28
29 \par Front-facing traits
30
31 - \c UPstream_basic_dataType trait :<br>
32 The main entry point for reduction operations
33 (requires fundamental types).<br>
34 Checks against fundamental/aliased (excludes user-defined),
35 or is a component-wise aggregate of the same.
36
37 - \c UPstream_dataType trait :<br>
38 The main entry point for transmission (broadcast, send/recv, ...).<br>
39 Checks against fundamental/aliased/user-defined,
40 or is a component-wise aggregate of the same.
41
42 - \c UPstream_opType trait :<br>
43 Mapping of OpenFOAM ops to their MPI equivalent.
44 The \c opcode_id is the corresponding internal representation.
45
46 - \c UPstream_data_opType trait :<br>
47 Combination of UPstream_opType and UPstream_basic_dataType.
48 .
49
50 \par Additional helper traits (not normally used directly):
51
52 - \c UPstream_mpi_dataType trait :<br>
53 Tests true and provides valid \c datatype_id for MPI fundamental
54 data types. This trait will should not normally be used directly:
55 use UPstream_alias_dataType for 'low-level' purposes (see below).
56
57 - \c UPstream_user_dataType trait :<br>
58 Tests true and provides valid \c datatype_id for user-defined
59 data types.
60
61 - \c UPstream_alias_dataType trait :<br>
62 Use this in preference to UPstream_mpi_dataType.<br>
63 A pass-through to UPstream_mpi_dataType, but provides additional
64 mappings for <int/long/long long,...> to the fundamental
65 32/64 bit integrals, since <int/long/long long,...> may not otherwise
66 map directly on all systems.
67
68 - \c UPstream_any_dataType trait :<br>
69 Used as a building block for uniform aggregate types.<br>
70 Combines UPstream_user_dataType and UPstream_alias_dataType into a
71 single trait.
72 .
73
74\*---------------------------------------------------------------------------*/
75
76#ifndef Foam_UPstreamTraits_H
77#define Foam_UPstreamTraits_H
78
79#include "UPstream.H"
80#include <cstdint>
81#include <ios> // For streamsize
82#include <type_traits>
83
84// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
85
86namespace Foam
87{
88
89// Forward Declarations
90
91// Some vector-space types
92// -----------------------
94template<class T> class Vector;
95template<class T> class SymmTensor;
96template<class T> class Tensor;
98
99// -------------------------
100// Some binary operators (as per ops.H), but since ListOps.H is included
101// by UPstream.H, don't need to forward declare
102// -------------------------
103// template<class T> struct minOp;
104// template<class T> struct maxOp;
105// template<class T> struct plusOp;
106// template<class T> struct sumOp;
107// template<class T> struct multiplyOp;
108// template<class T> struct bitAndOp;
109// template<class T> struct bitOrOp;
110// template<class T> struct bitXorOp;
111
113template<class T> struct UPstream_basic_dataType;
114template<class T> struct UPstream_dataType;
116
117
118// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
119
120//- UPstream data type corresponding to a fundamental (MPI) type
121template<class T>
122struct UPstream_mpi_dataType : std::false_type
123{
124 static constexpr auto datatype_id = UPstream::dataTypes::invalid;
125};
127//- Disallow \c void
128template<> struct UPstream_mpi_dataType<void> : std::false_type
129{
130 static constexpr auto datatype_id = UPstream::dataTypes::invalid;
131};
132
133//- UPstream data type corresponding to user-defined type
134template<class T>
135struct UPstream_user_dataType : std::false_type
136{
138};
139
140//- Disallow \c void
141template<> struct UPstream_user_dataType<void> : std::false_type
142{
144};
146
147// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
148
149// Trait specializations (data types)
150
151// Specializations to match elements of UPstream::dataTypes.
152
153#undef defineUPstreamDataTraits
154#define defineUPstreamDataTraits(TypeId, Type) \
155 \
157 template<> struct UPstream_mpi_dataType<Type> : std::true_type \
158 { \
159 static constexpr auto datatype_id = UPstream::dataTypes::TypeId; \
160 }; \
161 \
162 template<> struct UPstream_mpi_dataType<const Type> : std::true_type \
163 { \
164 static constexpr auto datatype_id = UPstream::dataTypes::TypeId; \
165 };
166
167// Fundamental Types [10]:
168// Note: uses 'int32_t,int64_t,...' instead of 'int,long,...' to minimize
169// the possibility of duplicate types. However, 'int8_t,uint8_t' are treated
170// as aliases (char,unsigned char) to avoid possible compilation issues.
171//
172// OpenFOAM defines Foam::label as either int32_t,int64_t (not int,long) too.
173defineUPstreamDataTraits(type_byte, char);
174defineUPstreamDataTraits(type_byte, unsigned char);
175defineUPstreamDataTraits(type_int16, int16_t);
176defineUPstreamDataTraits(type_int32, int32_t);
177defineUPstreamDataTraits(type_int64, int64_t);
178defineUPstreamDataTraits(type_uint16, uint16_t);
179defineUPstreamDataTraits(type_uint32, uint32_t);
180defineUPstreamDataTraits(type_uint64, uint64_t);
181defineUPstreamDataTraits(type_float, float);
182defineUPstreamDataTraits(type_double, double);
183defineUPstreamDataTraits(type_long_double, long double);
185#undef defineUPstreamDataTraits
186
187// ------------------------------------------------------------------------- //
188
189#undef defineUPstreamDataTraits
190#define defineUPstreamDataTraits(TypeId, Type) \
191 \
192 \
193 template<> struct UPstream_user_dataType<Type> : std::true_type \
194 { \
195 static constexpr auto datatype_id = UPstream::dataTypes::TypeId; \
196 }; \
197 \
198 template<> struct UPstream_user_dataType<const Type> : std::true_type \
199 { \
200 static constexpr auto datatype_id = UPstream::dataTypes::TypeId; \
201 };
202
203
204// User Types [6]:
212#undef defineUPstreamDataTraits
213
214
215// ------------------------------------------------------------------------- //
216
217//- Explicit handling of data type aliases. This is necessary since
218//- different systems map things like 'unsigned long' differently but we
219//- restrict ourselves to int32/int64 types.
220//
221// Note that this trait serves as the single pass-through point when needing
222// to reference UPstream_mpi_dataType elsewhere
223template<class T>
225:
226 std::bool_constant
227 <
228 // Basic MPI type
229 UPstream_mpi_dataType<std::remove_cv_t<T>>::value ||
230 (
231 // Or some int 32/64 type to re-map
232 std::is_integral_v<T>
233 && (sizeof(T) == sizeof(int32_t) || sizeof(T) == sizeof(int64_t))
234 )
235 >
236{
237 using base = std::conditional_t
238 <
240 std::remove_cv_t<T>, // <- using mpi type (no alias)
241 std::conditional_t // <- using alias
243 (
244 std::is_integral_v<T>
245 && (sizeof(T) == sizeof(int32_t) || sizeof(T) == sizeof(int64_t))
246 ),
247 std::conditional_t
248 <
249 (sizeof(T) == sizeof(int32_t)),
250 std::conditional_t<std::is_signed_v<T>, int32_t, uint32_t>,
251 std::conditional_t<std::is_signed_v<T>, int64_t, uint64_t>
252 >,
253 char // Fallback is a byte (eg, arbitrary contiguous data)
254 >
255 >;
256
257 static constexpr auto datatype_id =
259};
260
261
262// Handle int8_t/uint8_t as aliases since 'signed char' etc may be
263// ambiguous
264
265//- Map \c int8_t to UPstream::dataTypes::type_byte
266template<>
267struct UPstream_alias_dataType<int8_t> : std::true_type
268{
269 using base = char;
270 static constexpr auto datatype_id = UPstream::dataTypes::type_byte;
271};
272
273//- Map \c uint8_t to UPstream::dataTypes::type_byte
274template<>
275struct UPstream_alias_dataType<uint8_t> : std::true_type
277 using base = unsigned char;
278 static constexpr auto datatype_id = UPstream::dataTypes::type_byte;
279};
280
281// ------------------------------------------------------------------------- //
282
283//- UPstream data type (fundamental or user-defined),
284//- after resolving any aliases
285template<class T>
288 std::bool_constant
289 <
290 UPstream_user_dataType<std::remove_cv_t<T>>::value
291 || UPstream_alias_dataType<T>::value
292 >
293{
294 using base = std::conditional_t
295 <
297 std::remove_cv_t<T>,
299 >;
300
301 //- The corresponding UPstream::dataTypes enumeration
302 static constexpr auto datatype_id = []() constexpr noexcept
303 {
304 if constexpr (UPstream_user_dataType<std::remove_cv_t<T>>::value)
306 // A user-defined type
308 }
309 else if constexpr (UPstream_alias_dataType<T>::value)
310 {
311 // Fundamental type or alias to a fundamental type
313 }
314 else
317 }
318 }();
319};
320
321
322// ------------------------------------------------------------------------- //
323
324//- UPstream fundamental/aliased (excludes user-defined) data type
325//- or a component aggregate of the same.
326//
327// True for the following conditions:
328// - The \c Type is directly supported
329// - The \c cmptType (eg, from VectorSpace) exists and is directly supported
330// - Fallback to byte-wise representation (ie, for contiguous)
331// .
332template<class T>
334:
335 std::bool_constant
336 <
337 // non-aggregate type
338 UPstream_alias_dataType<T>::value
339 // aggregate type
340 || UPstream_alias_dataType<typename pTraits_cmptType<T>::type>::value
341 >
342{
343 //- The underlying data type (if supported) or byte
344 using base = std::conditional_t
345 <
346 UPstream_alias_dataType<T>::value,
347 typename UPstream_alias_dataType<T>::base, // <- non-aggregate
348 typename UPstream_alias_dataType
349 <typename pTraits_cmptType<T>::type>::base // <- aggregate
350 >;
351
352 //- The corresponding UPstream::dataTypes enumeration
353 static constexpr auto datatype_id =
355
356 //- The size in terms of the number of underlying data elements
357 static constexpr std::streamsize size(std::streamsize n) noexcept
358 {
360 {
361 // non-aggregate: no multiplier
362 return n;
363 }
364 else
365 {
366 // aggregate: with multiplier
367 return n*(sizeof(T)/sizeof(base));
368 }
369 }
370};
371
372//- Disallow \c void
373template<> struct UPstream_basic_dataType<void> : UPstream_mpi_dataType<void>
374{
375 using base = void;
376 static constexpr std::streamsize size(std::streamsize n) noexcept
377 {
378 return n;
380};
381
382
383// ------------------------------------------------------------------------- //
384
385//- UPstream fundamental/aliased/user-defined data type
386//- or a component aggregate of the same.
387//
388// True for the following conditions:
389// - The \c Type is directly supported
390// - The \c cmptType (eg, from VectorSpace) exists and is directly supported
391// - Fallback to byte-wise representation (ie, for contiguous)
392// .
393template<class T>
394struct UPstream_dataType
395:
396 std::bool_constant
398 UPstream_any_dataType<T>::value
399 || UPstream_any_dataType<typename pTraits_cmptType<T>::type>::value
401{
402 //- The underlying data type (if supported) or byte
403 using base = std::conditional_t
404 <
406 typename UPstream_any_dataType<T>::base, // <- non-aggregate
407 typename UPstream_any_dataType
408 <typename pTraits_cmptType<T>::type>::base // <- aggregate
409 >;
410
411 //- The corresponding UPstream::dataTypes enumeration
412 static constexpr auto datatype_id =
414
415 //- The size in terms of the number of base data elements
416 static constexpr std::streamsize size(std::streamsize n) noexcept
417 {
419 {
420 // non-aggregate: no multiplier
421 return n;
422 }
423 else
424 {
425 // aggregate: with multiplier
426 return n*(sizeof(T)/sizeof(base));
427 }
428 }
429};
430
431//- Disallow \c void
432template<> struct UPstream_dataType<void> : UPstream_basic_dataType<void> {};
433
434
435// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
436
437// Reduction op-codes
438
439//- A supported UPstream (MPI) reduce/window operation type
440template<class BinaryOp>
441struct UPstream_opType : std::false_type
442{
443 static constexpr auto opcode_id = UPstream::opCodes::invalid;
444};
445
446//- Disallow \c void
447template<> struct UPstream_opType<void> : std::false_type
448{
449 static constexpr auto opcode_id = UPstream::opCodes::invalid;
450};
451
452//- Map minOp<T> to \c UPstream::opCodes::op_min
453template<class T>
454struct UPstream_opType<Foam::minOp<T>> : std::true_type
455{
456 static constexpr auto opcode_id = UPstream::opCodes::op_min;
457};
458
459//- Map maxOp<T> to \c UPstream::opCodes::op_max
460template<class T>
461struct UPstream_opType<Foam::maxOp<T>> : std::true_type
462{
463 static constexpr auto opcode_id = UPstream::opCodes::op_max;
464};
465
466//- Map sumOp<T> to \c UPstream::opCodes::op_sum
467template<class T>
468struct UPstream_opType<Foam::sumOp<T>> : std::true_type
469{
470 static constexpr auto opcode_id = UPstream::opCodes::op_sum;
471};
472
473//- Map plusOp<T> (same as sumOp<T>) to \c UPstream::opCodes::op_sum
474template<class T>
475struct UPstream_opType<Foam::plusOp<T>> : std::true_type
476{
477 static constexpr auto opcode_id = UPstream::opCodes::op_sum;
479
480//- Map multiplyOp<T> to \c UPstream::opCodes::op_prod
481template<class T>
482struct UPstream_opType<Foam::multiplyOp<T>> : std::true_type
483{
484 static constexpr auto opcode_id = UPstream::opCodes::op_prod;
485};
487// NOTE (2025-02):
488// currently no mappings provided for
489// (op_bool_and, op_bool_or, op_bool_xor) until the calling semantics
490// have been properly defined
491
492
493// These are only viable for unsigned integral types,
494// probably not for signed integral types.
495// Be extra restrictive for now
496
497//- Map bitAndOp<T> to \c UPstream::opCodes::op_bit_and
498//- for integrals (signed or unsigned), but also allow void as "generic"
499template<class T>
500struct UPstream_opType<Foam::bitAndOp<T>>
501:
502 std::bool_constant<std::is_integral_v<T> || std::is_void_v<T>>
503{
504 static constexpr auto opcode_id = []() constexpr noexcept
505 {
506 if constexpr (std::is_integral_v<T> || std::is_void_v<T>)
508 else
510 }();
511};
512
513//- Map bitOrOp<T> to \c UPstream::opCodes::op_bit_or
514//- for integrals (signed or unsigned), but also allow void as "generic"
515template<class T>
516struct UPstream_opType<Foam::bitOrOp<T>>
517:
518 std::bool_constant<std::is_integral_v<T> || std::is_void_v<T>>
519{
520 static constexpr auto opcode_id = []() constexpr noexcept
521 {
522 if constexpr (std::is_integral_v<T> || std::is_void_v<T>)
524 else
526 }();
527};
528
529//- Map bitXorOp<T> to \c UPstream::opCodes::op_bit_xor
530//- for integrals (signed or unsigned), but also allow void as "generic"
531template<class T>
532struct UPstream_opType<Foam::bitXorOp<T>>
534 std::bool_constant<std::is_integral_v<T> || std::is_void_v<T>>
535{
536 static constexpr auto opcode_id = []() constexpr noexcept
537 {
538 if constexpr (std::is_integral_v<T> || std::is_void_v<T>)
540 else
542 }();
543};
544
545
546//- Combined query of opType and the underlying basic data type
547// This handling may be simplified in the future...
548template<class BinaryOp, class T>
550:
551 std::bool_constant
552 <
553 UPstream_opType<BinaryOp>::value
554 && UPstream_basic_dataType<T>::value
556{
557 static constexpr auto opcode_id = []() constexpr noexcept
558 {
559 if constexpr
560 (
563 )
565 else
567 }();
568};
570
571// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
572
573// Convenience Functions (FUTURE?)
574
575// inline bool is_UPstream_mpi_dataTypeCode(UPstream::dataTypes id) noexcept
576// {
577// return
578// (
579// int(id) >= int(UPstream::opCodes::Basic_begin)
580// && int(id) < int(UPstream::opCodes::Basic_end)
581// );
582// }
583//
584// inline bool is_UPstream_reduceOpCode(UPstream::opCodes id) noexcept
585// {
586// return
587// (
588// int(id) >= int(UPstream::opCodes::Basic_begin)
589// && int(id) < int(UPstream::opCodes::Basic_end)
590// );
591// }
592
593
594// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
595
596} // End namespace Foam
597
598// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
599
600#endif
601
602// ************************************************************************* //
label n
#define defineUPstreamDataTraits(TypeId, Type)
A templated (3 x 3) symmetric tensor of objects of <T>, effectively containing 6 elements,...
Definition SymmTensor.H:53
A templated (3 x 3) tensor of objects of <T> derived from MatrixSpace.
Definition Tensor.H:60
@ op_bit_xor
Bit-wise xor for (unsigned) integral types.
Definition UPstream.H:165
@ op_bit_or
Bit-wise or for (unsigned) integral types.
Definition UPstream.H:164
@ op_bit_and
Bit-wise and for (unsigned) integral types.
Definition UPstream.H:163
@ type_byte
byte, char, unsigned char, ...
Definition UPstream.H:113
Templated 3D Vector derived from VectorSpace adding construction from 3 components,...
Definition Vector.H:61
Namespace for OpenFOAM.
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
Explicit handling of data type aliases. This is necessary since different systems map things like 'un...
std::conditional_t< UPstream_mpi_dataType< std::remove_cv_t< T > >::value, std::remove_cv_t< T >, std::conditional_t<( std::is_integral_v< T > &&(sizeof(T)==sizeof(int32_t)||sizeof(T)==sizeof(int64_t))), std::conditional_t<(sizeof(T)==sizeof(int32_t)), std::conditional_t< std::is_signed_v< T >, int32_t, uint32_t >, std::conditional_t< std::is_signed_v< T >, int64_t, uint64_t > >, char > > base
static constexpr auto datatype_id
UPstream data type (fundamental or user-defined), after resolving any aliases.
std::conditional_t< UPstream_user_dataType< std::remove_cv_t< T > >::value, std::remove_cv_t< T >, typename UPstream_alias_dataType< T >::base > base
static constexpr auto datatype_id
The corresponding UPstream::dataTypes enumeration.
static constexpr std::streamsize size(std::streamsize n) noexcept
UPstream fundamental/aliased (excludes user-defined) data type or a component aggregate of the same.
static constexpr std::streamsize size(std::streamsize n) noexcept
The size in terms of the number of underlying data elements.
std::conditional_t< UPstream_alias_dataType< T >::value, typename UPstream_alias_dataType< T >::base, typename UPstream_alias_dataType< typename pTraits_cmptType< T >::type >::base > base
The underlying data type (if supported) or byte.
static constexpr auto datatype_id
The corresponding UPstream::dataTypes enumeration.
UPstream fundamental/aliased/user-defined data type or a component aggregate of the same.
static constexpr std::streamsize size(std::streamsize n) noexcept
The size in terms of the number of base data elements.
std::conditional_t< UPstream_any_dataType< T >::value, typename UPstream_any_dataType< T >::base, typename UPstream_any_dataType< typename pTraits_cmptType< T >::type >::base > base
The underlying data type (if supported) or byte.
static constexpr auto datatype_id
The corresponding UPstream::dataTypes enumeration.
Combined query of opType and the underlying basic data type.
static constexpr auto opcode_id
UPstream data type corresponding to a fundamental (MPI) type.
static constexpr auto datatype_id
static constexpr auto opcode_id
A supported UPstream (MPI) reduce/window operation type.
static constexpr auto opcode_id
UPstream data type corresponding to user-defined type.
static constexpr auto datatype_id