diff --git a/applications/test/00-machine-sizes/Test-machine-sizes.cpp b/applications/test/00-machine-sizes/Test-machine-sizes.cpp index 917782dfde1f3f0228e9ebff3acf2ae632abea05..e66fa7e57c33fe0951f8a7d9abee80d96419f771 100644 --- a/applications/test/00-machine-sizes/Test-machine-sizes.cpp +++ b/applications/test/00-machine-sizes/Test-machine-sizes.cpp @@ -51,17 +51,20 @@ Description //- Mapping of some fundamental and aggregate types to MPI data types enum class dataTypes : int { - // Builtin Types [8]: - DataTypes_begin, //!< Begin builtin types (internal use) - type_byte = DataTypes_begin, // also for char, unsigned char + // Fundamental Types [10]: + Basic_begin, + type_byte = Basic_begin, + type_int16, type_int32, type_int64, + type_uint16, type_uint32, type_uint64, type_float, type_double, type_long_double, - invalid + invalid, + Basic_end = invalid }; @@ -69,20 +72,19 @@ enum class dataTypes : int // Partial copy from UPstreamTraits.H -//- A supported UPstream data type (intrinsic or user-defined) +//- UPstream data type corresponding to an intrinsic (MPI) type template<class T> -struct UPstream_base_dataType : std::false_type +struct UPstream_mpi_dataType : std::false_type { static constexpr auto datatype_id = dataTypes::invalid; }; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -// Specializations of the above, -// each to match the elements of UPstream::dataTypes +// Specializations to match elements of UPstream::dataTypes #undef defineUPstreamDataTraits #define defineUPstreamDataTraits(TypeId, Type) \ - template<> struct UPstream_base_dataType<Type> : std::true_type \ + template<> struct UPstream_mpi_dataType<Type> : std::true_type \ { \ static constexpr auto datatype_id = dataTypes::TypeId; \ }; @@ -90,8 +92,10 @@ struct UPstream_base_dataType : std::false_type defineUPstreamDataTraits(type_byte, char); defineUPstreamDataTraits(type_byte, unsigned char); +defineUPstreamDataTraits(type_int16, int16_t); defineUPstreamDataTraits(type_int32, int32_t); defineUPstreamDataTraits(type_int64, int64_t); +defineUPstreamDataTraits(type_uint16, uint16_t); defineUPstreamDataTraits(type_uint32, uint32_t); defineUPstreamDataTraits(type_uint64, uint64_t); defineUPstreamDataTraits(type_float, float); @@ -109,8 +113,8 @@ struct UPstream_alias_dataType : std::bool_constant < - // Base type (no alias needed) - UPstream_base_dataType<std::remove_cv_t<T>>::value || + // Basic MPI type + UPstream_mpi_dataType<std::remove_cv_t<T>>::value || ( // Or some int 32/64 type to re-map std::is_integral_v<T> @@ -118,15 +122,11 @@ struct UPstream_alias_dataType ) > { - // Is it using the base type? (no alias needed) - static constexpr bool is_base = - UPstream_base_dataType<std::remove_cv_t<T>>::value; - using base = std::conditional_t < - UPstream_base_dataType<std::remove_cv_t<T>>::value, // is_base - std::remove_cv_t<T>, - std::conditional_t + UPstream_mpi_dataType<std::remove_cv_t<T>>::value, + std::remove_cv_t<T>, // <- using mpi type (no alias) + std::conditional_t // <- using alias < ( std::is_integral_v<T> @@ -138,12 +138,32 @@ struct UPstream_alias_dataType 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 // Fallback value (assuming it is contiguous) + char // Fallback is a byte (eg, arbitrary contiguous data) > >; static constexpr auto datatype_id = - UPstream_base_dataType<base>::datatype_id; + UPstream_mpi_dataType<base>::datatype_id; +}; + + +// Handle int8_t/uint8_t as aliases since 'signed char' etc may be +// ambiguous + +//- Map \c int8_t to UPstream::dataTypes::type_byte +template<> +struct UPstream_alias_dataType<int8_t> : std::true_type +{ + using base = char; + static constexpr auto datatype_id = dataTypes::type_byte; +}; + +//- Map \c uint8_t to UPstream::dataTypes::type_byte +template<> +struct UPstream_alias_dataType<uint8_t> : std::true_type +{ + using base = unsigned char; + static constexpr auto datatype_id = dataTypes::type_byte; }; @@ -172,26 +192,31 @@ void print(const char* name, bool showLimits = true) } // A declared or deduced MPI type, or aliased - std::cout - << " is_mpi=" << UPstream_base_dataType<T>::value - << " (" << int(UPstream_base_dataType<T>::datatype_id) << ")"; + if constexpr (UPstream_mpi_dataType<T>::value) + { + std::cout + << " is_mpi=(" + << int(UPstream_mpi_dataType<T>::datatype_id) << ')'; + } + else + { + std::cout << " is_mpi=(null)"; + } - if (UPstream_alias_dataType<T>::value) + // Any aliases? + if constexpr (UPstream_alias_dataType<T>::value) { - if (UPstream_alias_dataType<T>::is_base) + if constexpr (UPstream_mpi_dataType<T>::value) { - std::cout<< " is_base"; + std::cout << " alias=base"; } else { - std::cout<< " is_alias (" - << int(UPstream_alias_dataType<T>::datatype_id) << ")"; + std::cout + << " alias=(" + << int(UPstream_alias_dataType<T>::datatype_id) << ')'; } } - else - { - std::cout<< " no_alias"; - } std::cout<< '\n'; } @@ -217,6 +242,7 @@ int main(int argc, char *argv[]) std::cout << '\n'; print<char>("char"); + print<signed char>("signed char"); print<unsigned char>("unsigned char"); print<short>("short"); print<int>("int"); diff --git a/applications/test/UPstreamTraits/Test-UPstreamTraits.cxx b/applications/test/UPstreamTraits/Test-UPstreamTraits.cxx index 9c747c61fa7fd2821a039ac161cda0875daaf75c..d8cb032749dabba3e6d0b56fdea9620e1a785313 100644 --- a/applications/test/UPstreamTraits/Test-UPstreamTraits.cxx +++ b/applications/test/UPstreamTraits/Test-UPstreamTraits.cxx @@ -37,35 +37,40 @@ Description #include "vector.H" #include "tensor.H" #include "uLabel.H" +#include "MinMax.H" #include "Switch.H" #include "IOstreams.H" #include "UPstream.H" +#include <functional> #include <type_traits> -using namespace Foam; +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -// Just for debugging -const List<std::string> dataType_names -({ - "byte", - "int32", - "int64", - "uint32", - "uint64", - "float", - "double", - "long_double", +namespace Foam +{ + +// Add in some extras from functional + +//- Map std::plus to \c UPstream::opCodes::op_sum +template<> +struct UPstream_opType<std::plus<void>> : std::true_type +{ + static constexpr auto opcode_id = UPstream::opCodes::op_sum; +}; + + +//- Map 'signed char' to UPstream::dataTypes::type_byte +// Caution with: may be identical to int8_t mapping!! +#if 0 +template<> +struct UPstream_alias_dataType<signed char> : std::true_type +{ + using base = char; + static constexpr auto datatype_id = UPstream::dataTypes::type_byte; +}; +#endif - "float(2)", - "double(2)", - "float(3)", - "double(3)", - "float(6)", - "double(6)", - "float(9)", - "double(9)" -}); //- Test for pTraits typeName member : default is false template<class T, class = void> @@ -82,24 +87,93 @@ struct check_has_typeName std::true_type {}; +} // End namespace Foam -// Possible future change... -// //- A supported UPstream data type (intrinsic or user-defined) -// template<> -// struct UPstream_base_dataType<complex> : std::true_type -// { -// static constexpr auto datatype_id = []() -// { -// if constexpr (sizeof(complex) == 2*sizeof(float)) -// return UPstream::dataTypes::type_2float; -// else -// return UPstream::dataTypes::type_2double; -// }(); -// }; +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -template<class T> -void printTypeName(const bool showSize = false) +// Just for debugging +static const Foam::List<std::string> dataType_names +({ + "byte", + "int16", + "int32", + "int64", + "uint16", + "uint32", + "uint64", + "float", + "double", + "long_double", + + "float[3]", + "double[3]", + "float[6]", + "double[6]", + "float[9]", + "double[9]" +}); + +// Just for debugging +static const Foam::List<std::string> opType_names +({ + "op_min", + "op_max", + "op_sum", + "op_prod", + "op_bool_and", + "op_bool_or", + "op_bool_xor", + "op_bit_and", + "op_bit_or", + "op_bit_xor", + "op_replace", + "op_no_op" +}); + + +using namespace Foam; + +void printDataTypeId(UPstream::dataTypes datatype_id) +{ + if (datatype_id != UPstream::dataTypes::invalid) + { + const int index = int(datatype_id); + if (index < dataType_names.size()) + { + Info<< dataType_names[index]; + } + else + { + Info<< '(' << index << ')'; + } + } +} + + +void printOpCodeId(UPstream::opCodes opcode_id) +{ + if (opcode_id != UPstream::opCodes::invalid) + { + const int index = int(opcode_id); + if (index < opType_names.size()) + { + Info<< ':' << opType_names[index].c_str(); + } + else + { + Info<< '(' << index << ')'; + } + } + else + { + Info<< "(null)"; + } +} + + +template<class T, bool showSize = false> +void printTypeName() { // Both float and double have pTraits typeName = "scalar"! if constexpr (std::is_same_v<float, std::remove_cv_t<T>>) @@ -118,12 +192,13 @@ void printTypeName(const bool showSize = false) { Info<< typeid(T).name(); } - if (showSize) + if constexpr (showSize) { Info<< " (" << sizeof(T) << " bytes)"; } } + template<class Type, bool UseTypeName = true> void printPstreamTraits(const std::string_view name = std::string_view()) { @@ -133,55 +208,111 @@ void printPstreamTraits(const std::string_view name = std::string_view()) { Info<< name << ' '; } + if constexpr (UseTypeName) { - printTypeName<Type>(true); + printTypeName<Type, true>(); } else { - Info<< typeid(Type).name(); - Info<< " (" << sizeof(Type) << " bytes)"; + Info<< typeid(Type).name() << " (" << sizeof(Type) << " bytes)"; + } + + { + using cmpt = typename Foam::pTraits_cmptType<Type>::type; + + if constexpr (!std::is_same_v<Type, cmpt>) + { + Info<< ", cmpt:"; + + if constexpr (UseTypeName) + { + printTypeName<cmpt, true>(); + } + else + { + Info<< typeid(cmpt).name() << " (" << sizeof(cmpt) << " bytes)"; + } + } } - Info<< ", cmpt:"; - printTypeName<typename Foam::pTraits_cmptType<Type>::type>(true); Info<< nl << " is_contiguous:" - << is_contiguous<Type>::value - << ", is base:" - << UPstream_base_dataType<Type>::value - << ", is cmpt:" - << UPstream_dataType<Type>::value << nl; - - Info<< "is base:" - << UPstream_base_dataType<Type>::value - << " (type:" << int(UPstream_base_dataType<Type>::datatype_id) - << ") is alias:" << UPstream_alias_dataType<Type>::value - << " (type:" << int(UPstream_alias_dataType<Type>::datatype_id) - << ")" << nl; + << is_contiguous<Type>::value; + if constexpr (UPstream_mpi_dataType<Type>::value) + { + Info<< ", is_mpi=(" + << int(UPstream_mpi_dataType<Type>::datatype_id) << ')'; + } + else + { + std::cout << ", is_mpi=(null)"; + } + if constexpr (UPstream_user_dataType<Type>::value) + { + Info<< ", is_user=(" + << int(UPstream_user_dataType<Type>::datatype_id) << ')'; + } + else + { + std::cout << ", is_user=(null)"; + } + if constexpr (UPstream_any_dataType<Type>::value) + { + Info<< ", is_any=(" + << int(UPstream_any_dataType<Type>::datatype_id) << ')'; + } + else + { + std::cout << ", is_any=(null)"; + } + // Any aliases? + if constexpr + ( + UPstream_alias_dataType<Type>::value + && !UPstream_mpi_dataType<Type>::value + ) { - int index = int(UPstream_base_dataType<Type>::datatype_id); - Info<< "datatype: " << index; + Info<< ", alias=(" + << int(UPstream_alias_dataType<Type>::datatype_id) << ')'; + } - if (index < dataType_names.size()) - { - Info<< ' ' << dataType_names[index]; - } - Info<< nl; + Info<< " base-type:" << int(UPstream_basic_dataType<Type>::datatype_id) + << " data-type:" << int(UPstream_dataType<Type>::datatype_id) + << nl; + + if constexpr (UPstream_basic_dataType<Type>::value) + { + Info<< " base-type="; + printDataTypeId(UPstream_basic_dataType<Type>::datatype_id); + } + else if constexpr (UPstream_dataType<Type>::value) + { + Info<< " data-type="; + printDataTypeId(UPstream_dataType<Type>::datatype_id); } { // Use element or component type (or byte-wise) for data type using base = typename UPstream_dataType<Type>::base; - constexpr auto datatype = UPstream_dataType<Type>::datatype_id; - Info<< "datatype => "; - printTypeName<base>(); - Info<< " (" << sizeof(Type)/sizeof(base) << " elems)" << nl - << "datatype: " << static_cast<int>(datatype) << nl; + Info<< " : "; + if constexpr (UseTypeName) + { + printTypeName<base, true>(); + } + else + { + Info<< typeid(base).name() << " (" << sizeof(base) << " bytes)"; + } + + Info<< " cmpt-type="; + printDataTypeId(UPstream_dataType<Type>::datatype_id); + Info<< " count=" << UPstream_dataType<Type>::size(1); + Info<< nl; } } @@ -190,15 +321,44 @@ template<class BinaryOp> void printOpCodeTraits(BinaryOp bop, std::string_view name) { Info<< "op: " << name << ' '; - if constexpr (UPstream_opType<BinaryOp>::value) - { - Info<< "supported"; - } - else + + printOpCodeId(UPstream_opType<BinaryOp>::opcode_id); + Info<< nl; +} + + +template<class DataType, class BinaryOp> +void printOpCodeTraits(BinaryOp bop, std::string_view name) +{ + Info<< "op: " << name << ' '; + + printOpCodeId(UPstream_opType<BinaryOp>::opcode_id); + + if constexpr (!std::is_void_v<DataType>) { - Info<< "unknown"; + if constexpr (UPstream_basic_dataType<DataType>::value) + { + Info<< " [supported type]"; + } + else + { + Info<< " [disabled]"; + } } - Info<< ": " << int(UPstream_opType<BinaryOp>::opcode_id) << nl; + Info<< nl; +} + + +template<class DataType, class BinaryOp> +void print_data_opType(BinaryOp bop, std::string_view name) +{ + Info<< "op: " << name << ' '; + + printOpCodeId(UPstream_data_opType<BinaryOp, DataType>::opcode_id); + + const bool ok = UPstream_data_opType<BinaryOp, DataType>::value; + + Info<< " okay=" << ok << nl; } @@ -210,6 +370,16 @@ int main() printPstreamTraits<bool>(); printPstreamTraits<label>(); + printPstreamTraits<char, false>("<char>"); + printPstreamTraits<signed char, false>("<signed char>"); + printPstreamTraits<unsigned char, false>("<unsigned char>"); + + printPstreamTraits<int8_t, false>("<int8_t>"); + printPstreamTraits<uint8_t, false>("<uint8_t>"); + + printPstreamTraits<int16_t, false>("<int16_t>"); + printPstreamTraits<uint16_t, false>("<uint16_t>"); + printPstreamTraits<int>("<int>"); printPstreamTraits<long>("<long>"); printPstreamTraits<unsigned>("<unsigned>"); @@ -258,6 +428,35 @@ int main() printOpCodeTraits(bitAndOp<unsigned>{}, "bitAnd<unsigned>"); printOpCodeTraits(bitOrOp<unsigned>{}, "bitOr<unsigned>"); + printOpCodeTraits<vector>(sumOp<vector>{}, "sum"); + printOpCodeTraits(sumOp<scalarMinMax>{}, "sum"); + + printOpCodeTraits(std::plus<>{}, "sum"); + printOpCodeTraits<bool>(std::plus<>{}, "sum"); + printOpCodeTraits<vector>(std::plus<>{}, "sum"); + + + // Expect success + Info<< nl << "expect success" << nl; + print_data_opType<vector>(maxOp<scalar>(), "maxOp(scalar)"); + print_data_opType<unsigned>(bitOrOp<unsigned>(), "bitOrOp(unsigned)"); + print_data_opType<uint8_t>(bitOrOp<uint8_t>(), "bitOrOp(uint8_t)"); + print_data_opType<uint16_t>(bitOrOp<uint16_t>(), "bitOrOp(uint16_t)"); + + // Even allow signed integrals + print_data_opType<int>(bitOrOp<int>(), "bitOrOp(int)"); + print_data_opType<int8_t>(bitOrOp<int8_t>(), "bitOrOp(int8_t)"); + + // Failure - supported op, unsupported data type. + Info<< nl << "expect failure" << nl; + print_data_opType<bool>(maxOp<scalar>(), "maxOp(scalar, bool)"); + print_data_opType<bool>(bitOrOp<unsigned>(), "bitOrOp(unsigned, bool)"); + + // False positives. Failure - supported op, unsupported data type. + Info<< nl << "false positives" << nl; + print_data_opType<void>(maxOp<bool>(), "maxOp(bool, void)"); + print_data_opType<float>(bitOrOp<unsigned>(), "bitOrOp(unsigned, float)"); + Info<< nl << "End\n" << endl; return 0; diff --git a/applications/test/globalIndex3/Test-globalIndex3.cxx b/applications/test/globalIndex3/Test-globalIndex3.cxx index 19a72499d3290652b284becd53b5dc6597523dfc..19beee62390423d68c0b9ac5855f97c7220bca52 100644 --- a/applications/test/globalIndex3/Test-globalIndex3.cxx +++ b/applications/test/globalIndex3/Test-globalIndex3.cxx @@ -345,8 +345,8 @@ static void reportOffsets(const globalIndex& gi) UPstream::broadcast ( - allOffsets.data_bytes(), - allOffsets.size_bytes(), + allOffsets.data(), + allOffsets.size(), interNodeComm ); } @@ -508,7 +508,7 @@ int main(int argc, char *argv[]) #include "setRootCase.H" - const bool useLocalComms = UPstream::usingNodeComms(); + const bool useLocalComms = UPstream::usingNodeComms(UPstream::worldComm); bool useWindow = args.found("window"); bool useBuiltin = args.found("builtin"); diff --git a/applications/test/nodeTopology/Test-nodeTopology.cxx b/applications/test/nodeTopology/Test-nodeTopology.cxx index 9909d51d4f51b7b0e8443cd86bd6e01adaee588b..58b3d56cde534bda035555cfe0e5eb88150d4fde 100644 --- a/applications/test/nodeTopology/Test-nodeTopology.cxx +++ b/applications/test/nodeTopology/Test-nodeTopology.cxx @@ -115,6 +115,13 @@ int main(int argc, char *argv[]) ); + if (UPstream::parRun()) + { + const auto& procs = UPstream::localNode_parentProcs(); + Perr<< "local processors: [" << procs.min() + << ".." << procs.max() << ']' << endl; + } + // Generate the graph if (UPstream::master(UPstream::worldComm)) { diff --git a/applications/test/vector/Make/files b/applications/test/vector/Make/files index 62f06825eaea118c5850244641d6f8c1fcbaa81b..68db4be0f7b8912c987016776f65d037f8a1486c 100644 --- a/applications/test/vector/Make/files +++ b/applications/test/vector/Make/files @@ -1,3 +1,3 @@ -Test-vector.C +Test-vector.cxx EXE = $(FOAM_USER_APPBIN)/Test-vector diff --git a/applications/test/vector/Test-vector.C b/applications/test/vector/Test-vector.cxx similarity index 84% rename from applications/test/vector/Test-vector.C rename to applications/test/vector/Test-vector.cxx index 582f8bf50490b3f9b9804a06a6ef3334940bc5fe..cc2ad57d36edb423193995a5d77898d530ddc84d 100644 --- a/applications/test/vector/Test-vector.C +++ b/applications/test/vector/Test-vector.cxx @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018-2023 OpenCFD Ltd. + Copyright (C) 2018-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -32,7 +32,10 @@ Description \*---------------------------------------------------------------------------*/ #include "vectorField.H" +#include "boolVector.H" +#include "labelVector.H" #include "IOstreams.H" +#include "FixedList.H" #include "Random.H" #include <algorithm> #include <random> @@ -125,6 +128,42 @@ void testNormalise(Field<Type>& fld) } +// Transcribe vectorspace information into a FixedList +template<class Type> +void testTranscribe(Type& input) +{ + if constexpr + ( + is_vectorspace_v<Type> + && std::is_floating_point_v<typename pTraits_cmptType<Type>::type> + ) + { + constexpr auto nCmpts = pTraits_nComponents<Type>::value; + using cmpt = typename pTraits_cmptType<Type>::type; + + FixedList<cmpt, nCmpts+1> values; + values.back() = 100; // some additional data + + VectorSpaceOps<nCmpts>::copy_n(input.cdata(), values.data()); + + Info<< "Transcribed " << input << " => " << values << nl; + + for (auto& val : values) + { + val *= -1; + } + + VectorSpaceOps<nCmpts>::copy_n(values.cdata(), input.data()); + Info<< " copied back (-1) as " << input + << " from " << values << nl; + } + else + { + Info<< "Did not transcribe " << input << nl; + } +} + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // Main program: @@ -240,6 +279,16 @@ int main(int argc, char *argv[]) testNormalise(vfld2); } + Info<< nl + << "Test transcribing components" << nl; + { + vector vec1(1.1, 2.2, 3.3); + testTranscribe(vec1); + + labelVector vec2(10, 20, 30); + testTranscribe(vec2); + } + Info<< "\nEnd\n" << nl; return 0; diff --git a/applications/test/vectorTools/Make/files b/applications/test/vectorTools/Make/files index 0b30b98f8f3b0c0c1048846c8e90a62733a12dda..6c1e81deb863913fc857364785ba4d096e5eaccd 100644 --- a/applications/test/vectorTools/Make/files +++ b/applications/test/vectorTools/Make/files @@ -1,3 +1,3 @@ -Test-vectorTools.C +Test-vectorTools.cxx EXE = $(FOAM_USER_APPBIN)/Test-vectorTools diff --git a/applications/test/vectorTools/Test-vectorTools.C b/applications/test/vectorTools/Test-vectorTools.cxx similarity index 100% rename from applications/test/vectorTools/Test-vectorTools.C rename to applications/test/vectorTools/Test-vectorTools.cxx diff --git a/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/extrudeToRegionMesh.C b/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/extrudeToRegionMesh.C index cf15e2f1a51391c64663279962d2fa6e0fc3b3ff..d1fb66a6056c4b48562672c70d9270bd2d116b9e 100644 --- a/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/extrudeToRegionMesh.C +++ b/applications/utilities/mesh/generation/extrude/extrudeToRegionMesh/extrudeToRegionMesh.C @@ -661,8 +661,8 @@ void countExtrudePatches } // Synchronise decision. Actual numbers are not important, just make // sure that they're > 0 on all processors. - Pstream::listCombineReduce(zoneSidePatch, plusEqOp<label>()); - Pstream::listCombineReduce(zoneZonePatch, plusEqOp<label>()); + Pstream::listReduce(zoneSidePatch, sumOp<label>()); + Pstream::listReduce(zoneZonePatch, sumOp<label>()); } diff --git a/applications/utilities/mesh/manipulation/splitMeshRegions/splitMeshRegions.C b/applications/utilities/mesh/manipulation/splitMeshRegions/splitMeshRegions.C index 64c0b0ef341c0acbadd2d3cf98b447c96ecdcf34..ae9d91f0b194b196630a4b467b9955b15393605d 100644 --- a/applications/utilities/mesh/manipulation/splitMeshRegions/splitMeshRegions.C +++ b/applications/utilities/mesh/manipulation/splitMeshRegions/splitMeshRegions.C @@ -1081,7 +1081,7 @@ label findCorrespondingRegion } } - Pstream::listCombineReduce(cellsInZone, plusEqOp<label>()); + Pstream::listReduce(cellsInZone, sumOp<label>()); // Pick region with largest overlap of zoneI label regionI = findMax(cellsInZone); diff --git a/applications/utilities/postProcessing/lagrangian/particleTracks/particleTracks.C b/applications/utilities/postProcessing/lagrangian/particleTracks/particleTracks.C index 754109e162ee10444458e529b1b8ccfa94dfbc50..2202574ad88b3d3a4a62fc229fc6ad026d806e50 100644 --- a/applications/utilities/postProcessing/lagrangian/particleTracks/particleTracks.C +++ b/applications/utilities/postProcessing/lagrangian/particleTracks/particleTracks.C @@ -186,7 +186,7 @@ int main(int argc, char *argv[]) const label maxNProcs = returnReduce(maxIds.size(), maxOp<label>()); maxIds.resize(maxNProcs, -1); - Pstream::listCombineReduce(maxIds, maxEqOp<label>()); + Pstream::listReduce(maxIds, maxOp<label>()); // From ids to count const labelList numIds = maxIds + 1; diff --git a/applications/utilities/postProcessing/miscellaneous/postChannel/channelIndexTemplates.C b/applications/utilities/postProcessing/miscellaneous/postChannel/channelIndexTemplates.C index e0ca2042b6252cec3094ac6cb7bae890e189258b..5668bcc3cb9ed62cd479f6c76fbbde0a38012b17 100644 --- a/applications/utilities/postProcessing/miscellaneous/postChannel/channelIndexTemplates.C +++ b/applications/utilities/postProcessing/miscellaneous/postChannel/channelIndexTemplates.C @@ -40,7 +40,7 @@ Foam::Field<T> Foam::channelIndex::regionSum(const Field<T>& cellField) const } // Global sum - Pstream::listCombineReduce(regionField, plusEqOp<T>()); + Pstream::listReduce(regionField, sumOp<T>()); return regionField; } diff --git a/applications/utilities/preProcessing/createViewFactors/viewFactorModels/raySearchEngine/raySearchEngine/raySearchEngine.C b/applications/utilities/preProcessing/createViewFactors/viewFactorModels/raySearchEngine/raySearchEngine/raySearchEngine.C index f1a37bbc5f389adc3274f29c3adf730e272c5d76..4f2699517d72c0a5cc6e36efa85c6b2478dcbd68 100644 --- a/applications/utilities/preProcessing/createViewFactors/viewFactorModels/raySearchEngine/raySearchEngine/raySearchEngine.C +++ b/applications/utilities/preProcessing/createViewFactors/viewFactorModels/raySearchEngine/raySearchEngine/raySearchEngine.C @@ -229,7 +229,7 @@ void Foam::VF::raySearchEngine::createAgglomeration(const IOobject& io) Pstream::allGatherList(allSf_); Pstream::allGatherList(allAgg_); - Pstream::listCombineGather(patchAreas_, plusEqOp<scalar>()); + Pstream::listGather(patchAreas_, sumOp<scalar>()); Pstream::broadcast(patchAreas_); globalNumbering_ = globalIndex(nCoarseFace_); @@ -262,8 +262,11 @@ void Foam::VF::raySearchEngine::createGeometry() Pstream::allGatherList(allCf_); Pstream::allGatherList(allSf_); - Pstream::listCombineGather(patchAreas_, plusEqOp<scalar>()); - Pstream::broadcast(patchAreas_); + // Pstream::listCombineGather(patchAreas_, plusEqOp<scalar>()); + // Pstream::broadcast(patchAreas_); + + // Basic type and op_sum, so can use listReduce (ie, mpiAllReduce) + Pstream::listReduce(patchAreas_, sumOp<scalar>()); globalNumbering_ = globalIndex(nFace_); } diff --git a/applications/utilities/preProcessing/setFields/setFields.C b/applications/utilities/preProcessing/setFields/setFields.C index 276b36c2f3d5d13b7a03745fefa75cc7f50f65a8..44778b680aea48ce52477d82f5bc579cc0738500 100644 --- a/applications/utilities/preProcessing/setFields/setFields.C +++ b/applications/utilities/preProcessing/setFields/setFields.C @@ -407,7 +407,7 @@ bool setFaceFieldType } } - Pstream::listCombineReduce(nChanged, plusEqOp<label>()); + Pstream::listReduce(nChanged, sumOp<label>()); auto& fieldBf = field.boundaryFieldRef(); diff --git a/src/OpenFOAM/containers/Lists/FixedList/FixedList.H b/src/OpenFOAM/containers/Lists/FixedList/FixedList.H index 5344e5b364254cf0502bbb0a7df44d61d6f0feb6..8a6abaa91f0d468bc121f0a762112a5014dfa061 100644 --- a/src/OpenFOAM/containers/Lists/FixedList/FixedList.H +++ b/src/OpenFOAM/containers/Lists/FixedList/FixedList.H @@ -384,6 +384,10 @@ public: //- Return an iterator to end traversing the FixedList inline iterator end() noexcept; + //- Return iterator at offset i from begin, + //- clamped to [0,N] range + inline iterator begin(const int i) noexcept; + // Random access iterator (const) @@ -399,6 +403,14 @@ public: //- Return const_iterator to end traversing the constant FixedList inline const_iterator end() const noexcept; + //- Return const_iterator at offset i from begin, + //- clamped to [0,N] range + inline const_iterator cbegin(const int i) const noexcept; + + //- Return const_iterator at offset i from begin, + //- clamped to [0,N] range + inline const_iterator begin(const int i) const noexcept; + // Reverse iterator (non-const) diff --git a/src/OpenFOAM/containers/Lists/FixedList/FixedListI.H b/src/OpenFOAM/containers/Lists/FixedList/FixedListI.H index 7d590c3799443d0a1867ae2ae5629671e84df3eb..61fe38572fb27fdb2fab76ef98c9b217cae3d553 100644 --- a/src/OpenFOAM/containers/Lists/FixedList/FixedListI.H +++ b/src/OpenFOAM/containers/Lists/FixedList/FixedListI.H @@ -499,6 +499,30 @@ Foam::FixedList<T, N>::cbegin() const noexcept } +template<class T, unsigned N> +inline typename Foam::FixedList<T, N>::iterator +Foam::FixedList<T, N>::begin(const int i) noexcept +{ + return (v_ + (i < 0 ? 0 : int(N) < i ? int(N) : i)); +} + + +template<class T, unsigned N> +inline typename Foam::FixedList<T, N>::const_iterator +Foam::FixedList<T, N>::begin(const int i) const noexcept +{ + return (v_ + (i < 0 ? 0 : int(N) < i ? int(N) : i)); +} + + +template<class T, unsigned N> +inline typename Foam::FixedList<T, N>::const_iterator +Foam::FixedList<T, N>::cbegin(const int i) const noexcept +{ + return (v_ + (i < 0 ? 0 : int(N) < i ? int(N) : i)); +} + + template<class T, unsigned N> inline typename Foam::FixedList<T, N>::iterator Foam::FixedList<T, N>::end() noexcept diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/IPBstreams.C b/src/OpenFOAM/db/IOstreams/Pstreams/IPBstreams.C index 54b1305f27ed6d378682f44c0de1aec9280e0cb4..43fcb428d73d062735bda45f412ac9431a743c91 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/IPBstreams.C +++ b/src/OpenFOAM/db/IOstreams/Pstreams/IPBstreams.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2022-2024 OpenCFD Ltd. + Copyright (C) 2022-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -33,24 +33,21 @@ License Foam::UIPBstream::UIPBstream ( - const UPstream::commsTypes commsType, - const int rootProcNo, DynamicList<char>& receiveBuf, label& receiveBufPosition, - const int tag, - const label comm, + const int communicator, const bool clearAtEnd, IOstreamOption::streamFormat fmt ) : UIPstreamBase ( - commsType, // irrelevant - rootProcNo, // normally UPstream::masterNo() + UPstream::commsTypes::scheduled, // irrelevant + UPstream::masterNo(), // irrelevant receiveBuf, receiveBufPosition, - tag, // irrelevant - comm, + UPstream::msgType(), // irrelevant + communicator, clearAtEnd, fmt ) @@ -61,64 +58,20 @@ Foam::UIPBstream::UIPBstream Foam::IPBstream::IPBstream ( - const UPstream::commsTypes commsType, - const int rootProcNo, - const label bufSize, - const int tag, - const label comm, + const int communicator, IOstreamOption::streamFormat fmt ) : - Pstream(commsType, bufSize), + Pstream(UPstream::commsTypes::scheduled), // type is irrelevant UIPBstream ( - commsType, // irrelevant - rootProcNo, // normally UPstream::masterNo() Pstream::transferBuf_, UIPstreamBase::storedRecvBufPos_, // Internal only - tag, // irrelevant - comm, + communicator, false, // Do not clear Pstream::transferBuf_ if at end fmt ) {} -Foam::IPBstream::IPBstream -( - const int rootProcNo, - const label comm, - IOstreamOption::streamFormat fmt -) -: - IPBstream - ( - UPstream::commsTypes::scheduled, // irrelevant - rootProcNo, - label(0), // bufSize - UPstream::msgType(), // irrelevant - comm, - fmt - ) -{} - - -Foam::IPBstream::IPBstream -( - const label comm, - IOstreamOption::streamFormat fmt -) -: - IPBstream - ( - UPstream::commsTypes::scheduled, // irrelevant - UPstream::masterNo(), // rootProcNo - label(0), // bufSize - UPstream::msgType(), // irrelevant - comm, - fmt - ) -{} - - // ************************************************************************* // diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/IPstream.H b/src/OpenFOAM/db/IOstreams/Pstreams/IPstream.H index e1304da88512322a2b7c3a1c5d150a4fc04445a8..056d3dd0fbafcccd321c06e9051749d535528385 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/IPstream.H +++ b/src/OpenFOAM/db/IOstreams/Pstreams/IPstream.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2013 OpenFOAM Foundation - Copyright (C) 2021-2024 OpenCFD Ltd. + Copyright (C) 2021-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -61,14 +61,13 @@ public: // Constructors //- Construct given process index to read from - //- and optional buffer size, read format IPstream ( const UPstream::commsTypes commsType, const int fromProcNo, - const label bufSize = 0, + const int bufferSize = 0, //!< optional buffer size const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, IOstreamOption::streamFormat fmt = IOstreamOption::BINARY ); @@ -83,7 +82,7 @@ public: Type& value, const int fromProcNo, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, IOstreamOption::streamFormat fmt = IOstreamOption::BINARY ) { @@ -91,9 +90,9 @@ public: ( UPstream::commsTypes::scheduled, // ie, MPI_Recv() fromProcNo, - 0, // bufSize + 0, // bufferSize tag, - comm, + communicator, fmt ); is >> value; @@ -116,31 +115,11 @@ public: // Constructors - //- Construct for broadcast root, optional buffer size, read format - IPBstream - ( - const UPstream::commsTypes, //!< ignored - const int rootProcNo, //!< normally UPstream::masterNo() - const label bufSize = 0, - const int tag = UPstream::msgType(), //!< ignored - const label comm = UPstream::worldComm, - IOstreamOption::streamFormat fmt = IOstreamOption::BINARY - ); - - //- Construct for broadcast root and communicator, - //- with optional read format - IPBstream - ( - const int rootProcNo, //!< normally UPstream::masterNo() - const label comm, - IOstreamOption::streamFormat fmt = IOstreamOption::BINARY - ); - //- Construct with optional communicator and read format. //- Uses UPstream::masterNo() root explicit IPBstream ( - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, IOstreamOption::streamFormat fmt = IOstreamOption::BINARY ); @@ -154,12 +133,33 @@ public: static void recv ( Type& value, - const label comm = UPstream::worldComm, - IOstreamOption::streamFormat fmt = IOstreamOption::BINARY + const int communicator = UPstream::worldComm ) { - IPBstream is(comm, fmt); - is >> value; + IPBstream is(communicator); + { + is >> value; + } + } + + //- Receive (from broadcast) a buffer and deserialize + //- multiple items. + //- Uses \c operator>> for de-serialization + template<class Type, class... Args> + static void recvs + ( + const int communicator, + Type& value, + Args&&... values + ) + { + IPBstream is(communicator); + { + Detail::inputLoop(is, value, std::forward<Args>(values)...); + // Depending on compiler support: + // Unpack via fold expression + // (((is >> value) >> std::forward<Args>(values)), ...); + } } }; diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/IPstreams.C b/src/OpenFOAM/db/IOstreams/Pstreams/IPstreams.C index 340f0a2f990813172778ad811721fc72e35fce46..667970803bcb344f4fafb983dfaa009e7715caeb 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/IPstreams.C +++ b/src/OpenFOAM/db/IOstreams/Pstreams/IPstreams.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2022-2023 OpenCFD Ltd. + Copyright (C) 2022-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -38,7 +38,7 @@ Foam::UIPstream::UIPstream DynamicList<char>& receiveBuf, label& receiveBufPosition, const int tag, - const label comm, + const int communicator, const bool clearAtEnd, IOstreamOption::streamFormat fmt ) @@ -50,7 +50,7 @@ Foam::UIPstream::UIPstream receiveBuf, receiveBufPosition, tag, - comm, + communicator, clearAtEnd, fmt ) @@ -105,13 +105,13 @@ Foam::IPstream::IPstream ( const UPstream::commsTypes commsType, const int fromProcNo, - const label bufSize, + const int bufferSize, const int tag, - const label comm, + const int communicator, IOstreamOption::streamFormat fmt ) : - Pstream(commsType, bufSize), + Pstream(commsType, bufferSize), UIPstream ( commsType, @@ -119,7 +119,7 @@ Foam::IPstream::IPstream Pstream::transferBuf_, UIPstreamBase::storedRecvBufPos_, // Internal only tag, - comm, + communicator, false, // Do not clear Pstream::transferBuf_ if at end fmt ) diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/OPBstreams.C b/src/OpenFOAM/db/IOstreams/Pstreams/OPBstreams.C index b68dc927a709dee58c924768adeb6291482be183..c5aed9a4252fdf4b0e0f0312eed1a2cfcd8e67d3 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/OPBstreams.C +++ b/src/OpenFOAM/db/IOstreams/Pstreams/OPBstreams.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2022-2024 OpenCFD Ltd. + Copyright (C) 2022-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -33,22 +33,19 @@ License Foam::UOPBstream::UOPBstream ( - const UPstream::commsTypes commsType, - const int rootProcNo, DynamicList<char>& sendBuf, - const int tag, - const label comm, + const int communicator, const bool sendAtDestruct, IOstreamOption::streamFormat fmt ) : UOPstreamBase ( - commsType, // irrelevant - rootProcNo, // normally UPstream::masterNo() + UPstream::commsTypes::scheduled, // irrelevant + UPstream::masterNo(), // irrelevant sendBuf, - tag, // irrelevant - comm, + UPstream::msgType(), // irrelevant + communicator, sendAtDestruct, fmt ) @@ -57,65 +54,21 @@ Foam::UOPBstream::UOPBstream Foam::OPBstream::OPBstream ( - const UPstream::commsTypes commsType, - const int rootProcNo, - const label bufSize, - const int tag, - const label comm, + const int communicator, IOstreamOption::streamFormat fmt ) : - Pstream(commsType, bufSize), + Pstream(UPstream::commsTypes::scheduled), // type is irrelevant UOPBstream ( - commsType, // irrelevant - rootProcNo, // normally UPstream::masterNo() Pstream::transferBuf_, - tag, // irrelevant - comm, + communicator, true, // sendAtDestruct fmt ) {} -Foam::OPBstream::OPBstream -( - const int rootProcNo, - const label comm, - IOstreamOption::streamFormat fmt -) -: - OPBstream - ( - UPstream::commsTypes::scheduled, // irrelevant - rootProcNo, - label(0), // bufSize - UPstream::msgType(), // irrelevant - comm, - fmt - ) -{} - - -Foam::OPBstream::OPBstream -( - const label comm, - IOstreamOption::streamFormat fmt -) -: - OPBstream - ( - UPstream::commsTypes::scheduled, // irrelevant - UPstream::masterNo(), // rootProcNo - label(0), // bufSize - UPstream::msgType(), // irrelevant - comm, - fmt - ) -{} - - // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // Foam::UOPBstream::~UOPBstream() @@ -125,8 +78,7 @@ Foam::UOPBstream::~UOPBstream() if (!bufferIPCsend()) { FatalErrorInFunction - << "Failed broadcast message of size " - << sendBuf_.size() << " root: " << toProcNo_ + << "Failed broadcast message of size " << sendBuf_.size() << Foam::abort(FatalError); } } diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/OPstream.H b/src/OpenFOAM/db/IOstreams/Pstreams/OPstream.H index 1b4414a4604a4e366726ab2397f5c0ee2e8469b0..8513b4fbf125b82f1e0b9912639ac85e50f90e4e 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/OPstream.H +++ b/src/OpenFOAM/db/IOstreams/Pstreams/OPstream.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2013 OpenFOAM Foundation - Copyright (C) 2021-2024 OpenCFD Ltd. + Copyright (C) 2021-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -61,14 +61,13 @@ public: // Constructors //- Construct for given process index to send to - //- and optional buffer size, write format OPstream ( const UPstream::commsTypes commsType, const int toProcNo, - const label bufSize = 0, + const int bufferSize = 0, //!< optional buffer size const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, IOstreamOption::streamFormat fmt = IOstreamOption::BINARY ); @@ -81,15 +80,15 @@ public: static void send ( const Type& value, - //! blocking or scheduled only! + //! buffered or scheduled only! const UPstream::commsTypes commsType, const int toProcNo, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, IOstreamOption::streamFormat fmt = IOstreamOption::BINARY ) { - OPstream os(commsType, toProcNo, 0, tag, comm, fmt); + OPstream os(commsType, toProcNo, 0, tag, communicator, fmt); os << value; } @@ -101,7 +100,7 @@ public: const Type& value, const int toProcNo, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, IOstreamOption::streamFormat fmt = IOstreamOption::BINARY ) { @@ -111,7 +110,7 @@ public: UPstream::commsTypes::scheduled, // ie, MPI_Send() toProcNo, tag, - comm, + communicator, fmt ); } @@ -133,49 +132,51 @@ public: // Constructors - //- Construct for broadcast root, optional buffer size, write format - OPBstream - ( - const UPstream::commsTypes, //!< ignored - const int rootProcNo, //!< normally UPstream::masterNo() - const label bufSize = 0, - const int tag = UPstream::msgType(), //!< ignored - const label comm = UPstream::worldComm, - IOstreamOption::streamFormat fmt = IOstreamOption::BINARY - ); - - //- Construct for broadcast root and communicator, - //- with optional write format - OPBstream - ( - const int rootProcNo, //!< normally UPstream::masterNo() - const label comm, - IOstreamOption::streamFormat fmt = IOstreamOption::BINARY - ); - //- Construct with optional communicator and write format. - //- Uses UPstream::masterNo() root explicit OPBstream ( - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, IOstreamOption::streamFormat fmt = IOstreamOption::BINARY ); // Static Functions + //- Use all send methods from base + using UOPBstream::send; + //- Serialize a value and broadcast (root == UPstream::masterNo()). //- Uses \c operator<< for serialization template<class Type> static void send ( const Type& value, - const label comm = UPstream::worldComm, - IOstreamOption::streamFormat fmt = IOstreamOption::BINARY + const int communicator = UPstream::worldComm ) { - OPBstream os(comm, fmt); - os << value; + OPBstream os(communicator); + { + os << value; + } + } + + //- Serialize multiple items and broadcast the buffer + //- Uses \c operator<< for serialization + template<class Type, class... Args> + static void sends + ( + const int communicator, + Type& value, + Args&&... values + ) + { + OPBstream os(communicator); + { + Detail::outputLoop(os, value, std::forward<Args>(values)...); + // Depending on compiler support: + // Pack via fold expression + // (((os << value) << std::forward<Args>(values)), ...); + } } }; diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/OPstreams.C b/src/OpenFOAM/db/IOstreams/Pstreams/OPstreams.C index fc8312f674923b47a0b6fcccd4ec742eb46585b7..281bc01a687a5cc90f4a247d115dad67deed32b2 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/OPstreams.C +++ b/src/OpenFOAM/db/IOstreams/Pstreams/OPstreams.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011 OpenFOAM Foundation - Copyright (C) 2022-2024 OpenCFD Ltd. + Copyright (C) 2022-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -37,7 +37,7 @@ Foam::UOPstream::UOPstream const int toProcNo, DynamicList<char>& sendBuf, const int tag, - const label comm, + const int comm, const bool sendAtDestruct, IOstreamOption::streamFormat fmt ) @@ -66,20 +66,20 @@ Foam::OPstream::OPstream ( const UPstream::commsTypes commsType, const int toProcNo, - const label bufSize, + const int bufferSize, const int tag, - const label comm, + const int communicator, IOstreamOption::streamFormat fmt ) : - Pstream(commsType, bufSize), + Pstream(commsType, bufferSize), UOPstream ( commsType, toProcNo, Pstream::transferBuf_, tag, - comm, + communicator, true, // sendAtDestruct fmt ) diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/Pstream.H b/src/OpenFOAM/db/IOstreams/Pstreams/Pstream.H index 0e26a4a3998035568ee44bcccf2001a3d87244b8..91329be13da8104fe0ddb8e8edcecfabe4f84834 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/Pstream.H +++ b/src/OpenFOAM/db/IOstreams/Pstreams/Pstream.H @@ -75,18 +75,20 @@ public: // Constructors - //- Construct for given communication type, with optional buffer size - explicit Pstream - ( - const UPstream::commsTypes commsType, - const label bufSize = 0 - ) + //- Construct for communication type with empty buffer + explicit Pstream(const UPstream::commsTypes commsType) noexcept + : + UPstream(commsType) + {} + + //- Construct for communication type with given buffer size + Pstream(const UPstream::commsTypes commsType, int bufferSize) : UPstream(commsType) { - if (bufSize > 0) + if (bufferSize > 0) { - transferBuf_.setCapacity(bufSize + 2*sizeof(scalar) + 1); + transferBuf_.setCapacity(bufferSize + 2*sizeof(scalar) + 1); } } @@ -104,13 +106,27 @@ public: static void broadcast ( Type& value, - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm + ); + + //- Broadcast fixed-list content (contiguous or non-contiguous) to all + //- communicator ranks. Does nothing in \b non-parallel. + template<class Type, unsigned N> + static void broadcast + ( + FixedList<Type, N>& list, + const int communicator = UPstream::worldComm ); //- Broadcast multiple items to all communicator ranks. //- Does nothing in \b non-parallel. template<class Type, class... Args> - static void broadcasts(const label comm, Type& arg1, Args&&... args); + static void broadcasts + ( + const int communicator, + Type& value, + Args&&... values + ); //- Broadcast list content (contiguous or non-contiguous) to all //- communicator ranks. Does nothing in \b non-parallel. @@ -120,7 +136,7 @@ public: static void broadcastList ( ListType& list, - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ); @@ -134,7 +150,7 @@ public: const UPstream::commsStructList& comms, //!< Communication order //! [in,out] T& value, - const BinaryOp& bop, + BinaryOp bop, const int tag, const int communicator ); @@ -150,9 +166,9 @@ public: ( //! [in,out] the result is only reliable on rank=0 T& value, - const BinaryOp& bop, + BinaryOp bop, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ); //- Gather individual values into list locations. @@ -164,7 +180,7 @@ public: static List<T> listGatherValues ( const T& localValue, - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, //! Only used for non-contiguous types const int tag = UPstream::msgType() ); @@ -178,7 +194,7 @@ public: static T listScatterValues ( const UList<T>& allValues, - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, //! Only used for non-contiguous types const int tag = UPstream::msgType() ); @@ -192,9 +208,9 @@ public: ( //! [in,out] the result is only reliable on rank=0 T& value, - const CombineOp& cop, + CombineOp cop, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ); //- Reduce inplace (cf. MPI Allreduce) @@ -205,9 +221,9 @@ public: ( //! [in,out] the result is consistent on all ranks T& value, - const CombineOp& cop, + CombineOp cop, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ); //- Same as Pstream::combineReduce @@ -216,12 +232,12 @@ public: ( //! [in,out] the result is consistent on all ranks T& value, - const CombineOp& cop, + CombineOp cop, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ) { - Pstream::combineReduce(value, cop, tag, comm); + Pstream::combineReduce(value, cop, tag, communicator); } @@ -235,7 +251,7 @@ public: const UPstream::commsStructList& comms, //!< Communication order //! [in,out] UList<T>& values, - const BinaryOp& bop, + BinaryOp bop, const int tag, const int communicator ); @@ -250,9 +266,9 @@ public: ( //! [in,out] the result is only reliable on rank=0 UList<T>& values, - const BinaryOp& bop, + BinaryOp bop, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ); //- Forwards to Pstream::listGather with an \em in-place \c cop @@ -261,9 +277,9 @@ public: ( //! [in,out] the result is only reliable on rank=0 UList<T>& values, - const CombineOp& cop, + CombineOp cop, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ); //- Reduce list elements (list must be equal size on all ranks), @@ -276,9 +292,9 @@ public: ( //! [in,out] the result is consistent on all ranks UList<T>& values, - const BinaryOp& bop, + BinaryOp bop, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ); //- Forwards to Pstream::listReduce with an \em in-place \c cop @@ -287,9 +303,9 @@ public: ( //! [in,out] the result is consistent on all ranks UList<T>& values, - const CombineOp& cop, + CombineOp cop, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ); //- Same as Pstream::listCombineReduce @@ -298,12 +314,12 @@ public: ( //! [in,out] the result is consistent on all ranks UList<T>& values, - const CombineOp& cop, + CombineOp cop, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ) { - Pstream::listCombineReduce(values, cop, tag, comm); + Pstream::listCombineReduce(values, cop, tag, communicator); } @@ -316,7 +332,7 @@ public: ( const UPstream::commsStructList& comms, //!< Communication order Container& values, - const BinaryOp& bop, + BinaryOp bop, const int tag, const int communicator ); @@ -331,9 +347,9 @@ public: ( //! [in,out] the result is only reliable on rank=0 Container& values, - const BinaryOp& bop, + BinaryOp bop, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ); //- Forwards to Pstream::mapGather with an \em in-place \c cop @@ -342,9 +358,9 @@ public: ( //! [in,out] the result is only reliable on rank=0 Container& values, - const CombineOp& cop, + CombineOp cop, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ); //- Reduce inplace (cf. MPI Allreduce) @@ -358,9 +374,9 @@ public: ( //! [in,out] the result is consistent on all ranks Container& values, - const BinaryOp& bop, + BinaryOp bop, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ); //- Forwards to Pstream::mapReduce with an \em in-place \c cop @@ -369,9 +385,9 @@ public: ( //! [in,out] the result is consistent on all ranks Container& values, - const CombineOp& cop, + CombineOp cop, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ); //- Same as Pstream::mapCombineReduce @@ -380,12 +396,12 @@ public: ( //! [in,out] the result is consistent on all ranks Container& values, - const CombineOp& cop, + CombineOp cop, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ) { - Pstream::mapCombineReduce(values, cop, tag, comm); + Pstream::mapCombineReduce(values, cop, tag, communicator); } @@ -423,7 +439,7 @@ public: //! [in,out] UList<T>& values, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ); //- Gather data, but keep individual values separate. @@ -436,7 +452,7 @@ public: //! [in,out] UList<T>& values, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ); @@ -449,7 +465,7 @@ public: //! [in,out] UList<T>& values, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ); @@ -640,7 +656,7 @@ public: ( T& value, const int tag = UPstream::msgType(), //!< ignored - const label comm = UPstream::worldComm + const int comm = UPstream::worldComm ) { Pstream::broadcast(value, comm); @@ -653,7 +669,7 @@ public: ( T& value, const int tag = UPstream::msgType(), //!< ignored - const label comm = UPstream::worldComm + const int comm = UPstream::worldComm ) { Pstream::broadcast(value, comm); @@ -666,7 +682,7 @@ public: ( List<T>& value, const int tag = UPstream::msgType(), //!< ignored - const label comm = UPstream::worldComm + const int comm = UPstream::worldComm ) { Pstream::broadcast(value, comm); @@ -679,7 +695,7 @@ public: ( Container& values, const int tag = UPstream::msgType(), //!< ignored - const label comm = UPstream::worldComm + const int comm = UPstream::worldComm ) { Pstream::broadcast(values, comm); diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/PstreamBroadcast.txx b/src/OpenFOAM/db/IOstreams/Pstreams/PstreamBroadcast.txx index 90c427ab506a83dfcddabe82ea86dd4c4e478fbf..447d2685447314565a2a1b968d9431cda79f10b1 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/PstreamBroadcast.txx +++ b/src/OpenFOAM/db/IOstreams/Pstreams/PstreamBroadcast.txx @@ -25,110 +25,181 @@ License \*---------------------------------------------------------------------------*/ -#include "OPstream.H" #include "IPstream.H" -#include "contiguous.H" +#include "OPstream.H" // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // template<class Type> -void Foam::Pstream::broadcast(Type& value, const label comm) +void Foam::Pstream::broadcast +( + Type& value, + const int communicator +) { - if constexpr (is_contiguous_v<Type>) + if (!UPstream::is_parallel(communicator)) + { + return; + } + else if constexpr (is_contiguous_v<Type>) { - // Note: contains parallel guard internally UPstream::broadcast ( reinterpret_cast<char*>(&value), sizeof(Type), - comm + communicator ); } - else if (UPstream::is_parallel(comm)) + else + { + if (UPstream::master(communicator)) + { + OPBstream::send(value, communicator); + } + else + { + IPBstream::recv(value, communicator); + } + } +} + + +template<class Type, unsigned N> +void Foam::Pstream::broadcast +( + FixedList<Type, N>& list, + const int communicator +) +{ + if (!UPstream::is_parallel(communicator)) + { + return; + } + else if constexpr (is_contiguous_v<Type>) + { + // Size is known and identical on all ranks + UPstream::broadcast(list.data(), list.size(), communicator); + } + else { - if (UPstream::master(comm)) + // Non-contiguous content - serialize it + if (UPstream::master(communicator)) { - OPBstream os(comm); - os << value; + OPBstream::send(list, communicator); } - else // UPstream::is_subrank(comm) + else { - IPBstream is(comm); - is >> value; + IPBstream::recv(list, communicator); } } } template<class Type, class... Args> -void Foam::Pstream::broadcasts(const label comm, Type& arg1, Args&&... args) +void Foam::Pstream::broadcasts +( + const int communicator, + Type& value, + Args&&... values +) { - if (UPstream::is_parallel(comm)) + if (!UPstream::is_parallel(communicator)) + { + return; + } + else if constexpr (!sizeof...(values) && is_contiguous_v<Type>) + { + // A single-value and contiguous + UPstream::broadcast(&value, 1, communicator); + } + else { - if (UPstream::master(comm)) + // Non-contiguous data, or multiple data - needs serialization + + if (UPstream::master(communicator)) { - OPBstream os(comm); - Detail::outputLoop(os, arg1, std::forward<Args>(args)...); + OPBstream::sends + ( + communicator, + value, + std::forward<Args>(values)... + ); } - else // UPstream::is_subrank(comm) + else { - IPBstream is(comm); - Detail::inputLoop(is, arg1, std::forward<Args>(args)...); + IPBstream::recvs + ( + communicator, + value, + std::forward<Args>(values)... + ); } } } template<class ListType> -void Foam::Pstream::broadcastList(ListType& list, const label comm) +void Foam::Pstream::broadcastList +( + ListType& list, + const int communicator +) { - if constexpr (is_contiguous_v<typename ListType::value_type>) + if (!UPstream::is_parallel(communicator)) + { + return; + } + else if constexpr (is_contiguous_v<typename ListType::value_type>) { // List data are contiguous // 1. broadcast the size // 2. resize for receiver list // 3. broadcast contiguous contents - if (UPstream::is_parallel(comm)) - { - label len(list.size()); + label len(list.size()); - UPstream::broadcast - ( - reinterpret_cast<char*>(&len), - sizeof(label), - comm - ); - - if (UPstream::is_subrank(comm)) - { - list.resize_nocopy(len); - } + UPstream::mpi_broadcast + ( + reinterpret_cast<char*>(&len), + sizeof(label), + UPstream::dataTypes::type_byte, + communicator + ); - if (len) - { - UPstream::broadcast - ( - list.data_bytes(), - list.size_bytes(), - comm - ); - } + if (len) + { + // Only broadcast non-empty content + UPstream::broadcast(list.data(), list.size(), communicator); } } - else if (UPstream::is_parallel(comm)) + else { // List data are non-contiguous - serialize/de-serialize - if (UPstream::master(comm)) + if (UPstream::master(communicator)) { - OPBstream os(comm); - os << list; + if (list.empty()) + { + // Do not serialize if empty. + // Just broadcast zero-size in a form that IPBstream can expect + OPBstream::send(Foam::zero{}, communicator); + } + else + { + OPBstream::send(list, communicator); + } } - else // UPstream::is_subrank(comm) + else { - IPBstream is(comm); - is >> list; + IPBstream is(communicator); + if (is.remaining() > 0) // Received a non-empty buffer + { + is >> list; + } + else + { + list.clear(); + } } } } @@ -148,11 +219,11 @@ template<class Type> Type returnBroadcast ( const Type& value, - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ) { Type work(value); - Pstream::broadcast(work, comm); + Pstream::broadcast(work, communicator); return work; } diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/PstreamBuffers.C b/src/OpenFOAM/db/IOstreams/Pstreams/PstreamBuffers.C index 391c094beace15fa281aef2584b4234df1a44691..5332f3cf895d099b73e758d36863ec0bc76f6901 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/PstreamBuffers.C +++ b/src/OpenFOAM/db/IOstreams/Pstreams/PstreamBuffers.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2021-2023 OpenCFD Ltd. + Copyright (C) 2021-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -300,7 +300,7 @@ Foam::PstreamBuffers::PstreamBuffers ( UPstream::commsTypes commsType, int tag, - label communicator, + int communicator, IOstreamOption::streamFormat fmt ) : @@ -313,7 +313,7 @@ Foam::PstreamBuffers::PstreamBuffers nProcs_(UPstream::nProcs(comm_)), sendBuffers_(nProcs_), recvBuffers_(nProcs_), - recvPositions_(nProcs_, Zero) + recvPositions_(nProcs_, Foam::zero{}) { DebugPoutInFunction << "tag:" << tag_ diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/PstreamBuffers.H b/src/OpenFOAM/db/IOstreams/Pstreams/PstreamBuffers.H index 97cb68fe9acb624bb1d0814520c64f39effc8a03..d80607d37996d8158c548aee22ee90502c9a7087 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/PstreamBuffers.H +++ b/src/OpenFOAM/db/IOstreams/Pstreams/PstreamBuffers.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2021-2023 OpenCFD Ltd. + Copyright (C) 2021-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -182,10 +182,10 @@ class PstreamBuffers const int tag_; //- Communicator - const label comm_; + const int comm_; //- Number of ranks associated with PstreamBuffers (at construction) - const label nProcs_; + const int nProcs_; // Buffer storage @@ -266,7 +266,7 @@ public: ( UPstream::commsTypes commsType = UPstream::commsTypes::nonBlocking, int tag = UPstream::msgType(), - label communicator = UPstream::worldComm, + int communicator = UPstream::worldComm, IOstreamOption::streamFormat fmt = IOstreamOption::BINARY ); @@ -274,7 +274,7 @@ public: //- (default: nonBlocking), message tag, IO format (default: binary) explicit PstreamBuffers ( - label communicator, + int communicator, UPstream::commsTypes commsType = UPstream::commsTypes::nonBlocking, int tag = UPstream::msgType(), IOstreamOption::streamFormat fmt = IOstreamOption::BINARY @@ -287,7 +287,7 @@ public: //- (default: nonBlocking), IO format (default: binary) PstreamBuffers ( - label communicator, + int communicator, int tag, UPstream::commsTypes commsType = UPstream::commsTypes::nonBlocking, IOstreamOption::streamFormat fmt = IOstreamOption::BINARY @@ -306,34 +306,19 @@ public: // Attributes //- The associated buffer format (ascii | binary) - IOstreamOption::streamFormat format() const noexcept - { - return format_; - } + IOstreamOption::streamFormat format() const noexcept { return format_; } //- The communications type of the stream - UPstream::commsTypes commsType() const noexcept - { - return commsType_; - } + UPstream::commsTypes commsType() const noexcept { return commsType_; } //- The transfer message tag - int tag() const noexcept - { - return tag_; - } + int tag() const noexcept { return tag_; } //- The communicator index - label comm() const noexcept - { - return comm_; - } + int comm() const noexcept { return comm_; } //- Number of ranks associated with PstreamBuffers - label nProcs() const noexcept - { - return nProcs_; - } + int nProcs() const noexcept { return nProcs_; } // Sizing diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/PstreamGather.txx b/src/OpenFOAM/db/IOstreams/Pstreams/PstreamGather.txx index 8aa66bb79511697ac7c33eb7c1422539e328782a..3b5e34c9739690489a92e56733048a444f67a254 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/PstreamGather.txx +++ b/src/OpenFOAM/db/IOstreams/Pstreams/PstreamGather.txx @@ -53,7 +53,7 @@ void Foam::Pstream::gather_algorithm ( const UPstream::commsStructList& comms, // Communication order T& value, - const BinaryOp& bop, + BinaryOp bop, const int tag, const int communicator ) @@ -151,9 +151,9 @@ template<class T, class BinaryOp, bool InplaceMode> void Foam::Pstream::gather ( T& value, - const BinaryOp& bop, - const int tag, - const label communicator + [[maybe_unused]] BinaryOp bop, + [[maybe_unused]] const int tag, + const int communicator ) { if (!UPstream::is_parallel(communicator)) @@ -161,6 +161,17 @@ void Foam::Pstream::gather // Nothing to do return; } + else if constexpr (!InplaceMode && UPstream_data_opType<BinaryOp, T>::value) + { + // Valid opcode and (directly/indirectly) uses basic dataType + UPstream::mpiReduce + ( + &value, + 1, + UPstream_opType<BinaryOp>::opcode_id, + communicator + ); + } else { // Communication order @@ -182,9 +193,9 @@ template<class T, class CombineOp> void Foam::Pstream::combineGather ( T& value, - const CombineOp& cop, + CombineOp cop, const int tag, - const label comm + const int comm ) { // In-place binary operation @@ -196,9 +207,9 @@ template<class T, class CombineOp> void Foam::Pstream::combineReduce ( T& value, - const CombineOp& cop, + CombineOp cop, const int tag, - const label comm + const int comm ) { if (UPstream::is_parallel(comm)) @@ -219,7 +230,7 @@ void Foam::Pstream::listGather_algorithm ( const UPstream::commsStructList& comms, // Communication order UList<T>& values, - const BinaryOp& bop, + BinaryOp bop, const int tag, const int communicator ) @@ -330,9 +341,9 @@ template<class T, class BinaryOp, bool InplaceMode> void Foam::Pstream::listGather ( UList<T>& values, - const BinaryOp& bop, - const int tag, - const label communicator + [[maybe_unused]] BinaryOp bop, + [[maybe_unused]] const int tag, + const int communicator ) { if (!UPstream::is_parallel(communicator) || values.empty()) @@ -340,6 +351,17 @@ void Foam::Pstream::listGather // Nothing to do return; } + else if constexpr (!InplaceMode && UPstream_data_opType<BinaryOp, T>::value) + { + // Valid opcode and (directly/indirectly) uses basic dataType + UPstream::mpiReduce + ( + values.data(), + values.size(), // Same length on all ranks + UPstream_opType<BinaryOp>::opcode_id, + communicator + ); + } else if (values.size() == 1) { // Single value - optimized version @@ -372,15 +394,26 @@ template<class T, class BinaryOp, bool InplaceMode> void Foam::Pstream::listReduce ( UList<T>& values, - const BinaryOp& bop, - const int tag, - const label comm + [[maybe_unused]] BinaryOp bop, + [[maybe_unused]] const int tag, + const int comm ) { if (!UPstream::is_parallel(comm) || values.empty()) { // Nothing to do } + else if constexpr (!InplaceMode && UPstream_data_opType<BinaryOp, T>::value) + { + // Valid opcode and (directly/indirectly) uses basic dataType + UPstream::mpiAllReduce + ( + values.data(), + values.size(), // Same length on all ranks + UPstream_opType<BinaryOp>::opcode_id, + comm + ); + } else if (values.size() == 1) { // Single value - optimized version @@ -400,9 +433,9 @@ template<class T, class CombineOp> void Foam::Pstream::listCombineGather ( UList<T>& values, - const CombineOp& cop, + CombineOp cop, const int tag, - const label comm + const int comm ) { // In-place binary operation @@ -414,9 +447,9 @@ template<class T, class CombineOp> void Foam::Pstream::listCombineReduce ( UList<T>& values, - const CombineOp& cop, + CombineOp cop, const int tag, - const label comm + const int comm ) { // In-place binary operation @@ -433,7 +466,7 @@ void Foam::Pstream::mapGather_algorithm ( const UPstream::commsStructList& comms, // Communication order Container& values, - const BinaryOp& bop, + BinaryOp bop, const int tag, const int communicator ) @@ -519,9 +552,9 @@ template<class Container, class BinaryOp, bool InplaceMode> void Foam::Pstream::mapGather ( Container& values, - const BinaryOp& bop, + BinaryOp bop, const int tag, - const label communicator + const int communicator ) { if (!UPstream::is_parallel(communicator)) @@ -550,9 +583,9 @@ template<class Container, class BinaryOp, bool InplaceMode> void Foam::Pstream::mapReduce ( Container& values, - const BinaryOp& bop, + BinaryOp bop, const int tag, - const label comm + const int comm ) { Pstream::mapGather<Container, BinaryOp, InplaceMode> @@ -567,9 +600,9 @@ template<class Container, class CombineOp> void Foam::Pstream::mapCombineGather ( Container& values, - const CombineOp& cop, + CombineOp cop, const int tag, - const label comm + const int comm ) { // In-place binary operation @@ -584,9 +617,9 @@ template<class Container, class CombineOp> void Foam::Pstream::mapCombineReduce ( Container& values, - const CombineOp& cop, + CombineOp cop, const int tag, - const label comm + const int comm ) { // In-place binary operation @@ -605,7 +638,7 @@ template<class T> Foam::List<T> Foam::Pstream::listGatherValues ( const T& localValue, - const label communicator, + const int communicator, [[maybe_unused]] const int tag ) { @@ -658,7 +691,7 @@ template<class T> T Foam::Pstream::listScatterValues ( const UList<T>& allValues, - const label communicator, + const int communicator, [[maybe_unused]] const int tag ) { diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/PstreamGatherList.txx b/src/OpenFOAM/db/IOstreams/Pstreams/PstreamGatherList.txx index a77c13bda68ccfe9094c9f66a320e5d81595750a..5a3de56ad5db344fba09a4a6a691cfa3a9c16294 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/PstreamGatherList.txx +++ b/src/OpenFOAM/db/IOstreams/Pstreams/PstreamGatherList.txx @@ -415,7 +415,7 @@ void Foam::Pstream::gatherList ( UList<T>& values, [[maybe_unused]] const int tag, - const label communicator + const int communicator ) { if (!UPstream::is_parallel(communicator)) @@ -433,14 +433,8 @@ void Foam::Pstream::gatherList << Foam::abort(FatalError); } - // In-place gather for contiguous types - UPstream::mpiGather - ( - nullptr, - values.data_bytes(), - sizeof(T), - communicator - ); + // In-place gather for contiguous types - one element per rank + UPstream::mpiGather(nullptr, values.data(), 1, communicator); } else { @@ -457,7 +451,7 @@ void Foam::Pstream::scatterList ( UList<T>& values, [[maybe_unused]] const int tag, - const label communicator + const int communicator ) { if (!UPstream::is_parallel(communicator)) @@ -467,14 +461,8 @@ void Foam::Pstream::scatterList } else if constexpr (is_contiguous_v<T>) { - // In-place scatter for contiguous types - UPstream::mpiScatter - ( - nullptr, - values.data_bytes(), - sizeof(T), - communicator - ); + // In-place scatter for contiguous types - one element per rank + UPstream::mpiScatter(nullptr, values.data(), 1, communicator); } else { @@ -491,33 +479,34 @@ void Foam::Pstream::allGatherList ( UList<T>& values, [[maybe_unused]] const int tag, - const label comm + const int communicator ) { - if (!UPstream::is_parallel(comm)) + if (!UPstream::is_parallel(communicator)) { // Nothing to do return; } else if constexpr (is_contiguous_v<T>) { - if (FOAM_UNLIKELY(values.size() < UPstream::nProcs(comm))) + if (FOAM_UNLIKELY(values.size() < UPstream::nProcs(communicator))) { FatalErrorInFunction << "List of values is too small:" << values.size() - << " vs numProcs:" << UPstream::nProcs(comm) << nl + << " vs numProcs:" << UPstream::nProcs(communicator) << nl << Foam::abort(FatalError); } - UPstream::mpiAllGather(values.data_bytes(), sizeof(T), comm); + // Allgather for contiguous types - one element per rank + UPstream::mpiAllGather(values.data(), 1, communicator); } else { // Communication order - const auto& commOrder = UPstream::whichCommunication(comm); + const auto& commOrder = UPstream::whichCommunication(communicator); - Pstream::gatherList_algorithm(commOrder, values, tag, comm); - Pstream::scatterList_algorithm(commOrder, values, tag, comm); + Pstream::gatherList_algorithm(commOrder, values, tag, communicator); + Pstream::scatterList_algorithm(commOrder, values, tag, communicator); } } diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/PstreamReduceOps.H b/src/OpenFOAM/db/IOstreams/Pstreams/PstreamReduceOps.H index 93a1e4b8e4b1743028728482606f6aca55df2f0c..c13757d3c30d58bcab745358b08ad3e4639bb0bd 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/PstreamReduceOps.H +++ b/src/OpenFOAM/db/IOstreams/Pstreams/PstreamReduceOps.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016-2024 OpenCFD Ltd. + Copyright (C) 2016-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -38,6 +38,7 @@ Description #include "Pstream.H" #include "FixedList.H" #include "ops.H" +#include "VectorSpaceOps.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -46,74 +47,160 @@ namespace Foam // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Single value: mpiAllReduce or manual + //- Reduce inplace (cf. MPI Allreduce) -//- using linear/tree communication schedule template<class T, class BinaryOp> void reduce ( T& value, - const BinaryOp& bop, - const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + [[maybe_unused]] BinaryOp bop, + [[maybe_unused]] const int tag = UPstream::msgType(), + const int communicator = UPstream::worldComm ) { - if (UPstream::is_parallel(comm)) + if (!UPstream::is_parallel(communicator)) + { + // Nothing to do + return; + } + else if constexpr (UPstream_data_opType<BinaryOp, T>::value) + { + // Valid opcode and (directly/indirectly) uses basic dataType + UPstream::mpiAllReduce + ( + &value, + 1, + UPstream_opType<BinaryOp>::opcode_id, + communicator + ); + } + else { - if (UPstream::warnComm >= 0 && comm != UPstream::warnComm) + if (UPstream::warnComm >= 0 && communicator != UPstream::warnComm) { - Perr<< "** reducing:" << value << " with comm:" << comm << endl; + Perr<< "** reducing:" << value << " comm:" << communicator << endl; error::printStack(Perr); } - Pstream::gather(value, bop, tag, comm); - Pstream::broadcast(value, comm); + Pstream::gather(value, bop, tag, communicator); + Pstream::broadcast(value, communicator); } } +// Multiple values: mpiAllReduce only! + //- Reduce inplace (cf. MPI Allreduce) //- multiple values (same size on all ranks!) template<class T, class BinaryOp> void reduce ( T values[], - const int size, - const BinaryOp&, - const int tag, - const label comm + const int count, + [[maybe_unused]] BinaryOp bop, + [[maybe_unused]] const int tag, + const int communicator = UPstream::worldComm +) +{ + if (!UPstream::is_parallel(communicator)) + { + // Nothing to do + return; + } + else if constexpr (UPstream_data_opType<BinaryOp, T>::value) + { + // Valid opcode and (directly/indirectly) uses basic dataType + UPstream::mpiAllReduce + ( + values, + count, + UPstream_opType<BinaryOp>::opcode_id, + communicator + ); + } + else + { + // static_assert(false, "unsupported data type"); + static_assert + ( + stdFoam::dependent_false_v<T>, + "only for specific, contiguous, known data types" + ); + } +} + + +//- Reduce multiple values +// Multiple values: mpiAllReduce only! +template<class T, unsigned N, class BinaryOp> +inline void reduce +( + FixedList<T, N>& values, + BinaryOp bop, + const int tag = UPstream::msgType(), + const int communicator = UPstream::worldComm ) { - NotImplemented; + reduce(values.data(), int(values.size()), bop, tag, communicator); } + //- Non-blocking reduce inplace (cf. MPI Iallreduce) -//- single value. Sets request. +//- multiple values. Sets request. template<class T, class BinaryOp> void reduce ( - T& Value, - const BinaryOp&, - const int tag, - const label comm, + T values[], + int count, + [[maybe_unused]] BinaryOp bop, + [[maybe_unused]] const int tag, + const int communicator, UPstream::Request& req ) { - NotImplemented; + if (!UPstream::is_parallel(communicator)) + { + // Nothing to do + return; + } + else if constexpr (UPstream_data_opType<BinaryOp, T>::value) + { + // Valid opcode and (directly/indirectly) uses basic dataType + UPstream::mpiAllReduce + ( + values, + count, + UPstream_opType<BinaryOp>::opcode_id, + communicator, + req + ); + } + else + { + // static_assert(false, "unsupported data type"); + static_assert + ( + stdFoam::dependent_false_v<T>, + "only for specific, contiguous, known data types" + ); + } } + //- Non-blocking reduce inplace (cf. MPI Iallreduce) -//- of multiple values (same size on all ranks!). Sets request. +//- single value. Sets request. template<class T, class BinaryOp> void reduce ( - T values[], - const int size, - const BinaryOp&, + T& value, + BinaryOp bop, const int tag, - const label comm, + const int communicator, UPstream::Request& req ) { - NotImplemented; + // single value + reduce(&value, 1, tag, communicator, req); } @@ -125,245 +212,97 @@ void reduce void reduce ( bool& value, - const andOp<bool>&, - const int tag = UPstream::msgType(), /*!< (ignored) */ - const label comm = UPstream::worldComm + Foam::andOp<bool>, + [[maybe_unused]] const int tag = UPstream::msgType(), /*!< (ignored) */ + const int communicator = UPstream::worldComm ); +// UPstream::reduceAnd(value, communicator); + //- Logical (or) inplace reduction. Uses UPstream::reduceOr void reduce ( bool& value, - const orOp<bool>&, - const int tag = UPstream::msgType(), /*!< (ignored) */ - const label comm = UPstream::worldComm + Foam::orOp<bool>, + [[maybe_unused]] const int tag = UPstream::msgType(), /*!< (ignored) */ + const int communicator = UPstream::worldComm ); - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -// Common reductions - -#undef Pstream_CommonReductions -#define Pstream_CommonReductions(Native) \ - \ -/*! \brief Reduce (min) multiple Native values (same size on all ranks!) */ \ -void reduce \ -( \ - Native values[], \ - const int size, \ - const minOp<Native>&, \ - const int tag = UPstream::msgType(), /*!< (ignored) */ \ - const label comm = UPstream::worldComm \ -); \ - \ -/*! \brief Reduce (min) single Native value */ \ -void reduce \ -( \ - Native& value, \ - const minOp<Native>&, \ - const int tag = UPstream::msgType(), /*!< (ignored) */ \ - const label comm = UPstream::worldComm \ -); \ - \ -/*! \brief Reduce (min) multiple Native values */ \ -template<unsigned N> \ -inline void reduce \ -( \ - FixedList<Native, N>& values, \ - const minOp<Native>&, \ - const int tag = UPstream::msgType(), /*!< (ignored) */ \ - const label comm = UPstream::worldComm \ -) \ -{ \ - reduce(values.data(), int(values.size()), minOp<Native>(), tag, comm); \ -} \ - \ -/*! \brief Reduce (max) multiple Native values (same size on all ranks!) */ \ -void reduce \ -( \ - Native values[], \ - const int size, \ - const maxOp<Native>&, \ - const int tag, /*!< (ignored) */ \ - const label comm \ -); \ - \ -/*! \brief Reduce (max) single Native value */ \ -void reduce \ -( \ - Native& value, \ - const maxOp<Native>&, \ - const int tag = UPstream::msgType(), /*!< (ignored) */ \ - const label comm = UPstream::worldComm \ -); \ - \ -/*! \brief Reduce (max) multiple Native values */ \ -template<unsigned N> \ -inline void reduce \ -( \ - FixedList<Native, N>& values, \ - const maxOp<Native>&, \ - const int tag = UPstream::msgType(), /*!< (ignored) */ \ - const label comm = UPstream::worldComm \ -) \ -{ \ - reduce(values.data(), int(values.size()), maxOp<Native>(), tag, comm); \ -} \ - \ -/*! \brief Reduce (sum) multiple Native values (same size on all ranks!) */ \ -void reduce \ -( \ - Native values[], \ - const int size, \ - const sumOp<Native>&, \ - const int tag, /*!< (ignored) */ \ - const label comm \ -); \ - \ -/*! \brief Reduce (sum) single Native value */ \ -void reduce \ -( \ - Native& value, \ - const sumOp<Native>&, \ - const int tag = UPstream::msgType(), /*!< (ignored) */ \ - const label comm = UPstream::worldComm \ -); \ - \ -/*! \brief Reduce (sum) multiple Native values */ \ -template<unsigned N> \ -inline void reduce \ -( \ - FixedList<Native, N>& values, \ - const sumOp<Native>&, \ - const int tag = UPstream::msgType(), /*!< (ignored) */ \ - const label comm = UPstream::worldComm \ -) \ -{ \ - reduce(values.data(), int(values.size()), sumOp<Native>(), tag, comm); \ -} - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -// Floating-point reductions - -#undef Pstream_FloatReductions -#define Pstream_FloatReductions(Native) \ - \ -Pstream_CommonReductions(Native); \ - \ -/*! \brief Non-blocking reduce (sum) multiple Native values. Sets request */ \ -void reduce \ -( \ - Native values[], \ - const int size, \ - const sumOp<Native>&, \ - const int tag, /*!< (ignored) */ \ - const label comm, \ - UPstream::Request& req /*!< [out] request information */ \ -); \ - \ -/*! \brief Non-blocking reduce (sum) single Native value. Sets request */ \ -void reduce \ -( \ - Native& value, \ - const sumOp<Native>&, \ - const int tag, /*!< (ignored) */ \ - const label comm, \ - UPstream::Request& req /*!< [out] request information */ \ -); - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -// Bitwise reductions - -#undef Pstream_BitwiseReductions -#define Pstream_BitwiseReductions(Native) \ - \ -/*! \brief Reduce (bit-or) multiple Native values (same size on all ranks!)*/ \ -void reduce \ -( \ - Native values[], \ - const int size, \ - const bitOrOp<Native>&, \ - const int tag = UPstream::msgType(), /*!< (ignored) */ \ - const label comm = UPstream::worldComm \ -); \ - \ -/*! \brief Reduce (bit-or) single Native value */ \ -void reduce \ -( \ - Native& value, \ - const bitOrOp<Native>&, \ - const int tag = UPstream::msgType(), /*!< (ignored) */ \ - const label comm = UPstream::worldComm \ -); - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -Pstream_CommonReductions(int32_t); -Pstream_CommonReductions(int64_t); -Pstream_CommonReductions(uint32_t); -Pstream_CommonReductions(uint64_t); - -Pstream_FloatReductions(float); -Pstream_FloatReductions(double); - -Pstream_BitwiseReductions(unsigned char); -Pstream_BitwiseReductions(unsigned int); - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -#undef Pstream_CommonReductions -#undef Pstream_FloatReductions -#undef Pstream_BitwiseReductions +// UPstream::reduceOr(value, communicator); // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // //- Reduce inplace (cf. MPI Allreduce) //- the sum of both value and count (for averaging) -template<class T> +template<class T, class IntType = int> void sumReduce ( T& value, - label& count, - const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + IntType& count, + [[maybe_unused]] const int tag = UPstream::msgType(), + const int communicator = UPstream::worldComm ) { - if (UPstream::is_parallel(comm)) + static_assert(std::is_arithmetic_v<IntType>, "Counter not arithmetic"); + + if (!UPstream::is_parallel(communicator)) + { + // Nothing to do + return; + } + else if constexpr (std::is_floating_point_v<T>) + { + // Bundle value and count together + T work[2]; + work[0] = value; + work[1] = static_cast<T>(count); + + UPstream::mpiAllReduce + ( + work, + 2, + UPstream::opCodes::op_sum, + communicator + ); + + // Unbundle + value = work[0]; + count = static_cast<IntType>(work[1]); + } + else if constexpr + ( + is_vectorspace_v<T> + && std::is_floating_point_v<typename pTraits_cmptType<T>::type> + ) { - Foam::reduce(value, sumOp<T>(), tag, comm); - Foam::reduce(count, sumOp<label>(), tag, comm); + constexpr auto nCmpts = pTraits_nComponents<T>::value; + using cmpt = typename pTraits_cmptType<T>::type; + + // Bundle all components and count together + cmpt work[nCmpts+1]; + VectorSpaceOps<nCmpts>::copy_n(value.begin(), work); + work[nCmpts] = static_cast<cmpt>(count); + + UPstream::mpiAllReduce + ( + work, + nCmpts+1, + UPstream::opCodes::op_sum, + communicator + ); + + // Unbundle + VectorSpaceOps<nCmpts>::copy_n(work, value.begin()); + count = static_cast<IntType>(work[nCmpts]); + } + else + { + Foam::reduce(value, sumOp<T>(), tag, communicator); + Foam::reduce(count, sumOp<IntType>(), tag, communicator); } } -// Floating-point sum-reduce - -#undef Pstream_SumReduce -#define Pstream_SumReduce(Native) \ - \ -/*! \brief Sum of both Native value and count (for averaging) */ \ -void sumReduce \ -( \ - Native& value, \ - label& count, \ - const int tag = UPstream::msgType(), /*!< (ignored) */ \ - const label comm = UPstream::worldComm \ -); - - -Pstream_SumReduce(float); -Pstream_SumReduce(double); - -#undef Pstream_SumReduce - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // Convenience wrappers - defined after all specialisations are known @@ -374,13 +313,13 @@ template<class T, class BinaryOp> T returnReduce ( const T& value, - const BinaryOp& bop, + BinaryOp bop, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ) { T work(value); - Foam::reduce(work, bop, tag, comm); + Foam::reduce(work, bop, tag, communicator); return work; } @@ -390,11 +329,11 @@ T returnReduce inline bool returnReduceAnd ( const bool value, - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ) { bool work(value); - UPstream::reduceAnd(work, comm); + UPstream::reduceAnd(work, communicator); return work; } @@ -404,11 +343,11 @@ inline bool returnReduceAnd inline bool returnReduceOr ( const bool value, - const label comm = UPstream::worldComm + const int communicator = UPstream::worldComm ) { bool work(value); - UPstream::reduceOr(work, comm); + UPstream::reduceOr(work, communicator); return work; } diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UIPstream.H b/src/OpenFOAM/db/IOstreams/Pstreams/UIPstream.H index eb2deb9a87dcae6e911b360b36dabc77804d1797..42ecd8f1d6c2aa05411400f93b83703b39c2476e 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/UIPstream.H +++ b/src/OpenFOAM/db/IOstreams/Pstreams/UIPstream.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2013 OpenFOAM Foundation - Copyright (C) 2017-2024 OpenCFD Ltd. + Copyright (C) 2017-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -33,6 +33,7 @@ Description Not to be used directly, thus contructors are protected. SourceFiles + UIPstream.txx UIPstreamBase.C \*---------------------------------------------------------------------------*/ @@ -124,7 +125,7 @@ protected: DynamicList<char>& receiveBuf, label& receiveBufPosition, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, const bool clearAtEnd = false, // destroy receiveBuf if at end IOstreamOption::streamFormat fmt = IOstreamOption::BINARY ); @@ -165,6 +166,9 @@ public: return std::ios_base::fmtflags(0); } + //- The number of characters remaining in the get buffer + label remaining() const noexcept; + // Read Functions @@ -249,7 +253,7 @@ public: DynamicList<char>& receiveBuf, label& receiveBufPosition, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, const bool clearAtEnd = false, // destroy receiveBuf if at end IOstreamOption::streamFormat fmt = IOstreamOption::BINARY ); @@ -280,48 +284,36 @@ public: // Static Functions - //- Read buffer contents from given processor. - // \return the message size (bytes read). May change in the future + //- Receive buffer contents (contiguous types) from given processor. + // \return the message size (elements read). May change in the future + template<class Type> static std::streamsize read ( const UPstream::commsTypes commsType, const int fromProcNo, - char* buf, - const std::streamsize bufSize, + Type* buffer, + std::streamsize count, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, //! [out] request information (for non-blocking) UPstream::Request* req = nullptr ); - //- Read buffer contents (non-blocking) from given processor. - // \return the message size (bytes read). May change in the future + //- Read buffer contents (non-blocking) from given processor + // \return number of elements read. May change in the future + template<class Type> inline static std::streamsize read ( //! [out] request information UPstream::Request& req, const int fromProcNo, - char* buf, - const std::streamsize bufSize, + Type* buffer, + std::streamsize count, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm - ) - { - return UIPstream::read - ( - UPstream::commsTypes::nonBlocking, - fromProcNo, - buf, - bufSize, - tag, - comm, - &req - ); - } + const int communicator = UPstream::worldComm + ); - //- Read into UList storage from given processor. - // Only valid for contiguous data types. - // \return the message size (bytes read). May change in the future + //- Receive into UList storage from given processor. template<class Type> inline static std::streamsize read ( @@ -329,26 +321,12 @@ public: const int fromProcNo, UList<Type>& buffer, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, //! [out] request information (for non-blocking) UPstream::Request* req = nullptr - ) - { - return UIPstream::read - ( - commsType, - fromProcNo, - buffer.data_bytes(), - buffer.size_bytes(), - tag, - comm, - req - ); - } + ); - //- Read into SubList storage from given processor. - // Only valid for contiguous data types. - // \return the message size (bytes read). May change in the future + //- Receive into SubList storage from given processor. template<class Type> inline static std::streamsize read ( @@ -356,26 +334,12 @@ public: const int fromProcNo, SubList<Type> buffer, // passed by shallow copy const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, //! [out] request information (for non-blocking) UPstream::Request* req = nullptr - ) - { - return UIPstream::read - ( - commsType, - fromProcNo, - buffer.data_bytes(), - buffer.size_bytes(), - tag, - comm, - req - ); - } + ); - //- Read into UList storage (non-blocking) from given processor. - // Only valid for contiguous data types. - // \return the message size (bytes read). May change in the future + //- Receive into UList storage (non-blocking) from given processor. template<class Type> inline static std::streamsize read ( @@ -384,24 +348,10 @@ public: const int fromProcNo, UList<Type>& buffer, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm - ) - { - return UIPstream::read - ( - UPstream::commsTypes::nonBlocking, - fromProcNo, - buffer.data_bytes(), - buffer.size_bytes(), - tag, - comm, - &req - ); - } + const int communicator = UPstream::worldComm + ); - //- Read into SubList storage (non-blocking) from given processor. - // Only valid for contiguous data types. - // \return the message size (bytes read). May change in the future + //- Receive into SubList storage (non-blocking) from given processor. template<class Type> inline static std::streamsize read ( @@ -410,20 +360,8 @@ public: const int fromProcNo, SubList<Type> buffer, // passed by shallow copy const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm - ) - { - return UIPstream::read - ( - UPstream::commsTypes::nonBlocking, - fromProcNo, - buffer.data_bytes(), - buffer.size_bytes(), - tag, - comm, - &req - ); - } + const int communicator = UPstream::worldComm + ); }; @@ -447,17 +385,13 @@ public: // Constructors - //- Construct given process index to read from using the given - //- attached receive buffer, optional communication characteristics - //- and IO format + //- Construct using the given attached receive buffer, + // optional communication characteristics and IO format UIPBstream ( - const UPstream::commsTypes, //!< irrelevant - const int rootProcNo, //!< normally UPstream::masterNo() DynamicList<char>& receiveBuf, label& receiveBufPosition, - const int tag = UPstream::msgType(), //!< irrelevant - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, const bool clearAtEnd = false, //!< destroy receiveBuf if at end IOstreamOption::streamFormat fmt = IOstreamOption::BINARY ); @@ -465,25 +399,6 @@ public: //- Destructor virtual ~UIPBstream() = default; - - - // Member Functions - - //- Use all read methods from base - using UIPstreamBase::read; - - - // Static Functions - - //- Wrapped version of UPstream::broadcast - // \return the message size (bytes read). May change in the future - static std::streamsize read - ( - const int rootProcNo, //!< normally UPstream::masterNo() - char* buf, - const std::streamsize bufSize, - const label comm = UPstream::worldComm - ); }; @@ -493,6 +408,12 @@ public: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +#ifdef NoRepository + #include "UIPstream.txx" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + #endif // ************************************************************************* // diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UIPstream.txx b/src/OpenFOAM/db/IOstreams/Pstreams/UIPstream.txx new file mode 100644 index 0000000000000000000000000000000000000000..4ee2044924e2bed6dc364738a9057d75b4c1dbb0 --- /dev/null +++ b/src/OpenFOAM/db/IOstreams/Pstreams/UIPstream.txx @@ -0,0 +1,187 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2025 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // + +template<class Type> +std::streamsize Foam::UIPstream::read +( + const UPstream::commsTypes commsType, + const int fromProcNo, + Type* buffer, + std::streamsize count, + const int tag, + const int communicator, + [[maybe_unused]] UPstream::Request* req +) +{ + if constexpr (!is_contiguous_v<Type>) + { + // Report parameters to silence compiler warnings about unused + FatalErrorInFunction + << "Invalid for non-contiguous data types. " + << int(commsType) << ':' << fromProcNo + << ':' << (buffer != nullptr) + << ':' << count + << ':' << tag + << ':' << communicator + << Foam::abort(FatalError); + return 0; + } + else + { + // Use element or component type (or byte-wise) for data type + return UPstream::mpi_receive + ( + commsType, + buffer, // The data or cmpt pointer + UPstream_dataType<Type>::size(count), + UPstream_dataType<Type>::datatype_id, + fromProcNo, + tag, + communicator, + req + ); + } +} + + +template<class Type> +std::streamsize Foam::UIPstream::read +( + UPstream::Request& req, + const int fromProcNo, + Type* buffer, + std::streamsize count, + const int tag, + const int communicator +) +{ + return UIPstream::read + ( + UPstream::commsTypes::nonBlocking, + fromProcNo, + buffer, + count, + tag, + communicator, + &req + ); +} + + +template<class Type> +std::streamsize Foam::UIPstream::read +( + const UPstream::commsTypes commsType, + const int fromProcNo, + UList<Type>& buffer, + const int tag, + const int communicator, + UPstream::Request* req +) +{ + return UIPstream::read + ( + commsType, + fromProcNo, + buffer.data(), buffer.size(), + tag, + communicator, + req + ); +} + + +template<class Type> +std::streamsize Foam::UIPstream::read +( + const UPstream::commsTypes commsType, + const int fromProcNo, + SubList<Type> buffer, + const int tag, + const int communicator, + UPstream::Request* req +) +{ + return UIPstream::read + ( + commsType, + fromProcNo, + buffer.data(), buffer.size(), + tag, + communicator, + req + ); +} + + +template<class Type> +std::streamsize Foam::UIPstream::read +( + UPstream::Request& req, + const int fromProcNo, + UList<Type>& buffer, + const int tag, + const int communicator +) +{ + return UIPstream::read + ( + UPstream::commsTypes::nonBlocking, + fromProcNo, + buffer.data(), buffer.size(), + tag, + communicator, + &req + ); +} + + +template<class Type> +std::streamsize Foam::UIPstream::read +( + UPstream::Request& req, + const int fromProcNo, + SubList<Type> buffer, + const int tag, + const int communicator +) +{ + return UIPstream::read + ( + UPstream::commsTypes::nonBlocking, + fromProcNo, + buffer.data(), buffer.size(), + tag, + communicator, + &req + ); +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UIPstreamBase.C b/src/OpenFOAM/db/IOstreams/Pstreams/UIPstreamBase.C index cfbb324164619f066e1bbce0faac81897c83b74f..c9444e673537c76c534fd8947cfb8dcaeff92242 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/UIPstreamBase.C +++ b/src/OpenFOAM/db/IOstreams/Pstreams/UIPstreamBase.C @@ -167,7 +167,7 @@ Foam::UIPstreamBase::UIPstreamBase DynamicList<char>& receiveBuf, label& receiveBufPosition, const int tag, - const label comm, + const int communicator, const bool clearAtEnd, IOstreamOption::streamFormat fmt ) @@ -176,7 +176,7 @@ Foam::UIPstreamBase::UIPstreamBase Istream(fmt), fromProcNo_(fromProcNo), tag_(tag), - comm_(comm), + comm_(communicator), messageSize_(0), storedRecvBufPos_(0), clearAtEnd_(clearAtEnd), @@ -548,6 +548,18 @@ bool Foam::UIPstreamBase::beginRawRead() /// return recvBufPos_; /// } +Foam::label Foam::UIPstreamBase::remaining() const noexcept +{ + if (messageSize_ && (recvBufPos_ < recvBuf_.size())) + { + return (recvBuf_.size() - recvBufPos_); + } + else + { + return 0; + } +} + void Foam::UIPstreamBase::rewind() { diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UOPstream.H b/src/OpenFOAM/db/IOstreams/Pstreams/UOPstream.H index e96a05d8754eedf7b4907dd9f12aa3529b3961b7..0dc65315f186b9ec6aa0a2c7ae06b12263f8b287 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/UOPstream.H +++ b/src/OpenFOAM/db/IOstreams/Pstreams/UOPstream.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2014 OpenFOAM Foundation - Copyright (C) 2017-2024 OpenCFD Ltd. + Copyright (C) 2017-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -33,6 +33,7 @@ Description Not to be used directly, thus contructors are protected. SourceFiles + UOPstream.txx UOPstreamBase.C \*---------------------------------------------------------------------------*/ @@ -121,7 +122,7 @@ protected: const int toProcNo, DynamicList<char>& sendBuf, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, const bool sendAtDestruct = true, IOstreamOption::streamFormat fmt = IOstreamOption::BINARY ); @@ -325,7 +326,7 @@ public: const int toProcNo, DynamicList<char>& sendBuf, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, const bool sendAtDestruct = true, IOstreamOption::streamFormat fmt = IOstreamOption::BINARY ); @@ -358,51 +359,39 @@ public: // Static Functions - //- Write buffer contents to given processor + //- Write buffer contents (contiguous types only) to given processor // \return True on success + template<class Type> static bool write ( const UPstream::commsTypes commsType, const int toProcNo, - const char* buf, - const std::streamsize bufSize, + const Type* buffer, + std::streamsize count, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, //! [out] request information (for non-blocking) UPstream::Request* req = nullptr, + //! optional send mode (normal | sync) const UPstream::sendModes sendMode = UPstream::sendModes::normal ); - //- Write buffer contents (non-blocking) to given processor + //- Write buffer contents (contiguous types only) to given processor // \return True on success + template<class Type> inline static bool write ( //! [out] request information UPstream::Request& req, const int toProcNo, - const char* buf, - const std::streamsize bufSize, + const Type* buffer, + std::streamsize count, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, const UPstream::sendModes sendMode = UPstream::sendModes::normal - ) - { - return UOPstream::write - ( - UPstream::commsTypes::nonBlocking, - toProcNo, - buf, - bufSize, - tag, - comm, - &req, - sendMode - ); - } + ); - //- Write UList contents to given processor. - // Only valid for contiguous data types. - // \return True on success + //- Send UList contiguous contents to given processor. template<class Type> inline static bool write ( @@ -410,28 +399,27 @@ public: const int toProcNo, const UList<Type>& buffer, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, //! [out] request information (for non-blocking) UPstream::Request* req = nullptr, const UPstream::sendModes sendMode = UPstream::sendModes::normal - ) - { - return UOPstream::write - ( - commsType, - toProcNo, - buffer.cdata_bytes(), - buffer.size_bytes(), - tag, - comm, - req, - sendMode - ); - } + ); - //- Write UList contents (non-blocking) to given processor. - // Only valid for contiguous data types. - // \return True on success + //- Send SubList contiguous contents to given processor. + template<class Type> + inline static bool write + ( + const UPstream::commsTypes commsType, + const int toProcNo, + const SubList<Type> buffer, // passed by shallow copy + const int tag = UPstream::msgType(), + const int communicator = UPstream::worldComm, + //! [out] request information (for non-blocking) + UPstream::Request* req = nullptr, + const UPstream::sendModes sendMode = UPstream::sendModes::normal + ); + + //- Send UList contiguous contents (non-blocking) to given processor. template<class Type> inline static bool write ( @@ -440,22 +428,22 @@ public: const int toProcNo, const UList<Type>& buffer, const int tag = UPstream::msgType(), - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, const UPstream::sendModes sendMode = UPstream::sendModes::normal - ) - { - return UOPstream::write - ( - UPstream::commsTypes::nonBlocking, - toProcNo, - buffer.cdata_bytes(), - buffer.size_bytes(), - tag, - comm, - &req, - sendMode - ); - } + ); + + //- Send SubList contiguous contents (non-blocking) to given processor. + template<class Type> + inline static bool write + ( + //! [out] request information + UPstream::Request& req, + const int toProcNo, + const SubList<Type> buffer, // passed by shallow copy + const int tag = UPstream::msgType(), + const int communicator = UPstream::worldComm, + const UPstream::sendModes sendMode = UPstream::sendModes::normal + ); }; @@ -481,16 +469,12 @@ public: // Constructors - //- Construct given process index to write to using the given - //- attached send buffer, optional communication characteristics - //- and IO format - UOPBstream + //- Construct with attached send buffer, + //- optional communication characteristics and IO format + explicit UOPBstream ( - const UPstream::commsTypes, //!< irrelevant - const int toProcNo, //!< normally UPstream::masterNo() DynamicList<char>& sendBuf, - const int tag = UPstream::msgType(), //!< irrelevant - const label comm = UPstream::worldComm, + const int communicator = UPstream::worldComm, const bool sendAtDestruct = true, IOstreamOption::streamFormat fmt = IOstreamOption::BINARY ); @@ -502,21 +486,9 @@ public: // Member Functions - //- Use all write methods from base - using UOPstreamBase::write; - - - // Static Functions - - //- Wrapped version of UPstream::broadcast with const-cast - // \return True on success - static bool write - ( - const int rootProcNo, //!< normally UPstream::masterNo() - const char* buf, - const std::streamsize bufSize, - const label comm = UPstream::worldComm - ); + //- Broadcast a zero value (buffer) size that can be matched + //- by the UIPBstream constructor. + static void send(Foam::zero, const int communicator); }; @@ -526,6 +498,12 @@ public: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +#ifdef NoRepository + #include "UOPstream.txx" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + #endif // ************************************************************************* // diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UOPstream.txx b/src/OpenFOAM/db/IOstreams/Pstreams/UOPstream.txx new file mode 100644 index 0000000000000000000000000000000000000000..940dfc5a166e4e1168db155b4ac189b33cf1d876 --- /dev/null +++ b/src/OpenFOAM/db/IOstreams/Pstreams/UOPstream.txx @@ -0,0 +1,200 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2025 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // + +template<class Type> +bool Foam::UOPstream::write +( + const UPstream::commsTypes commsType, + const int toProcNo, + const Type* buffer, + std::streamsize count, + const int tag, + const int communicator, + [[maybe_unused]] UPstream::Request* req, + const UPstream::sendModes sendMode +) +{ + if constexpr (!is_contiguous_v<Type>) + { + // Report parameters to silence compiler warnings about unused + FatalErrorInFunction + << "Invalid for non-contiguous data types. " + << int(commsType) << ':' << int(sendMode) + << ':' << toProcNo + << ':' << (buffer != nullptr) + << ':' << count + << ':' << tag + << ':' << communicator + << Foam::abort(FatalError); + return false; + } + else + { + // Use element or component type (or byte-wise) for data type + return UPstream::mpi_send + ( + commsType, + buffer, // The data or cmpt pointer + UPstream_dataType<Type>::size(count), + UPstream_dataType<Type>::datatype_id, + toProcNo, + tag, + communicator, + req, + sendMode + ); + } +} + + +template<class Type> +bool Foam::UOPstream::write +( + UPstream::Request& req, + const int toProcNo, + const Type* buffer, + std::streamsize count, + const int tag, + const int communicator, + const UPstream::sendModes sendMode +) +{ + return UOPstream::write + ( + UPstream::commsTypes::nonBlocking, + toProcNo, + buffer, + count, + tag, + communicator, + &req, + sendMode + ); +} + + +template<class Type> +bool Foam::UOPstream::write +( + const UPstream::commsTypes commsType, + const int toProcNo, + const UList<Type>& buffer, + const int tag, + const int communicator, + UPstream::Request* req, + const UPstream::sendModes sendMode +) +{ + return UOPstream::write + ( + commsType, + toProcNo, + buffer.cdata(), buffer.size(), + tag, + communicator, + req, + sendMode + ); +} + + +template<class Type> +bool Foam::UOPstream::write +( + const UPstream::commsTypes commsType, + const int toProcNo, + const SubList<Type> buffer, + const int tag, + const int communicator, + UPstream::Request* req, + const UPstream::sendModes sendMode +) +{ + return UOPstream::write + ( + commsType, + toProcNo, + buffer.cdata(), buffer.size(), + tag, + communicator, + req, + sendMode + ); +} + + +template<class Type> +bool Foam::UOPstream::write +( + UPstream::Request& req, + const int toProcNo, + const UList<Type>& buffer, + const int tag, + const int communicator, + const UPstream::sendModes sendMode +) +{ + return UOPstream::write + ( + UPstream::commsTypes::nonBlocking, + toProcNo, + buffer.cdata(), buffer.size(), + tag, + communicator, + &req, + sendMode + ); +} + + +template<class Type> +bool Foam::UOPstream::write +( + UPstream::Request& req, + const int toProcNo, + const SubList<Type> buffer, + const int tag, + const int communicator, + const UPstream::sendModes sendMode +) +{ + return UOPstream::write + ( + UPstream::commsTypes::nonBlocking, + toProcNo, + buffer.cdata(), buffer.size(), + tag, + communicator, + &req, + sendMode + ); +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UOPstreamBase.C b/src/OpenFOAM/db/IOstreams/Pstreams/UOPstreamBase.C index e07c5320e8f1118f9b4290a46fa455a4f7d5170d..cc665f0cb64cf66c8e65f0254391e4cd62aa8fe5 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/UOPstreamBase.C +++ b/src/OpenFOAM/db/IOstreams/Pstreams/UOPstreamBase.C @@ -146,7 +146,7 @@ Foam::UOPstreamBase::UOPstreamBase const int toProcNo, DynamicList<char>& sendBuf, const int tag, - const label comm, + const int communicator, const bool sendAtDestruct, IOstreamOption::streamFormat fmt ) @@ -155,7 +155,7 @@ Foam::UOPstreamBase::UOPstreamBase Ostream(fmt), toProcNo_(toProcNo), tag_(tag), - comm_(comm), + comm_(communicator), sendAtDestruct_(sendAtDestruct), sendBuf_(sendBuf) { diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.C b/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.C index 4ba0e1f4abb38b3cc00b858507629a7428eb36d9..2c1d72b143acf4957a5e4c1f0de0300f83052d6c 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.C +++ b/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.C @@ -112,7 +112,7 @@ void Foam::UPstream::printTopoControl(Ostream& os) // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // -void Foam::UPstream::setParRun(const label nProcs, const bool haveThreads) +void Foam::UPstream::setParRun(const int nProcs, const bool haveThreads) { parRun_ = (nProcs > 0); haveThreads_ = haveThreads; @@ -725,7 +725,7 @@ void Foam::UPstream::printCommTree } -bool Foam::UPstream::usingNodeComms(const label communicator) +bool Foam::UPstream::usingNodeComms(const int communicator) { // Starting point must be "real" world-communicator // ("real" means without any local trickery with worldComm) @@ -791,6 +791,38 @@ const Foam::List<int>& Foam::UPstream::interNode_offsets() } +const Foam::UPstream::rangeType& Foam::UPstream::localNode_parentProcs() +{ + static UPstream::rangeType singleton; + + if (singleton.empty()) + { + // The inter-node offsets [in const world comm] also include a + // startup guard + const auto& offsets = UPstream::interNode_offsets(); + + const auto nodei = + Foam::findLower + ( + offsets, + // My place within const world comm + UPstream::myProcNo(constWorldComm_)+1 + ); + + if (nodei >= 0) + { + singleton.reset + ( + offsets[nodei], + offsets[nodei+1] - offsets[nodei] + ); + } + } + + return singleton; +} + + // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // bool Foam::UPstream::parRun_(false); @@ -817,10 +849,10 @@ Foam::DynamicList<Foam::UPstream::commsStructList> Foam::UPstream::treeCommunication_(16); -Foam::label Foam::UPstream::constWorldComm_(0); -Foam::label Foam::UPstream::numNodes_(1); -Foam::label Foam::UPstream::commInterNode_(-1); -Foam::label Foam::UPstream::commLocalNode_(-1); +int Foam::UPstream::constWorldComm_(0); +int Foam::UPstream::commInterNode_(-1); +int Foam::UPstream::commLocalNode_(-1); +int Foam::UPstream::numNodes_(1); Foam::label Foam::UPstream::worldComm(0); // Initially same as constWorldComm_ Foam::label Foam::UPstream::warnComm(-1); @@ -828,7 +860,7 @@ Foam::label Foam::UPstream::warnComm(-1); // Predefine world and self communicator slots. // These are overwritten in parallel mode (by UPstream::setParRun()) -const Foam::label nPredefinedComm = []() +const int nPredefinedComm = []() { // 0: COMM_WORLD : commGlobal(), constWorldComm_, worldComm (void) Foam::UPstream::newCommunicator(-1, Foam::labelRange(1), false); @@ -862,7 +894,6 @@ registerOptSwitch Foam::UPstream::nodeCommsMin_ ); - int Foam::UPstream::topologyControl_ ( Foam::debug::optimisationSwitch("topoControl", 0) diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H b/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H index d0e23c298cc3969f8412033640e77c51e0190747..8caf255853fd814852436a50bdaf16d48312fd24 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H +++ b/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.H @@ -91,52 +91,54 @@ public: }; //- Mapping of some fundamental and aggregate types to MPI data types - enum class dataTypes : int + enum class dataTypes : char { // NOTE: changes here require adjustment in // PstreamGlobals, UPstreamTraits - // Builtin Types [8]: - DataTypes_begin, //!< (internal use) begin all data types - type_byte = DataTypes_begin, //!< byte, char, unsigned char, ... + // Fundamental Types [10]: + Basic_begin, //!< (internal use) begin marker [basic/all types] + type_byte = Basic_begin, //!< byte, char, unsigned char, ... + type_int16, type_int32, type_int64, + type_uint16, type_uint32, type_uint64, type_float, type_double, type_long_double, - //! (internal use) end of builtin data types marker - BuiltinTypes_end, UserTypes_begin = BuiltinTypes_end, - //!< (internal use) begin of user data types marker + //! (internal use) end marker [basic types] + Basic_end, User_begin = Basic_end, + //!< (internal use) begin marker [user types] // User Types [6]: - type_3float = UserTypes_begin, //!< 3*float (eg, floatVector) + type_3float = User_begin, //!< 3*float (eg, floatVector) type_3double, //!< 3*double (eg, doubleVector) type_6float, //!< 6*float (eg, floatSymmTensor, complex vector) type_6double, //!< 6*double (eg, doubleSymmTensor, complex vector) type_9float, //!< 9*float (eg, floatTensor) type_9double, //!< 9*double (eg, doubleTensor) - // Internal markers + // Internal markers [1] invalid, //!< invalid type (NULL) - //! (internal use) end of user data types marker - UserTypes_end = invalid, DataTypes_end = invalid - //!< (internal use) end of all data types marker + //! (internal use) end marker [user types] + User_end = invalid, DataTypes_end = invalid + //!< (internal use) end marker [all types] }; //- Mapping of some MPI op codes. // Currently excluding min/max location until they are needed - enum class opCodes : int + enum class opCodes : char { // NOTE: changes here require adjustment in // PstreamGlobals, UPstreamTraits - ReduceOps_begin, //!< (internal use) begin reduce/window + Basic_begin, //!< (internal use) begin marker [reduce/window types] // Reduce or window operations [10] - op_min = ReduceOps_begin, //!< min(x,y) + op_min = Basic_begin, //!< min(x,y) op_max, //!< max(x,y) op_sum, //!< (x + y) op_prod, //!< (x * y) @@ -147,19 +149,30 @@ public: op_bit_or, //!< Bit-wise \c or for (unsigned) integral types op_bit_xor, //!< Bit-wise \c xor for (unsigned) integral types - //! (internal use) end of reduce-ops marker - ReduceOps_end, WindowOps_begin = ReduceOps_end, - //!< (internal use) begin end of window-ops marker + //! (internal use) end marker [reduce types] + Basic_end, Extra_begin = Basic_end, + //!< (internal use) begin marker [window types] // Window-only operations [2] - op_replace = WindowOps_begin, //!< Replace (window only) + op_replace = Extra_begin, //!< Replace (window only) op_no_op, //!< No-op (window only) - // Internal markers + // Internal markers [1] invalid, //!< invalid op (NULL) - //! (internal use) end of window-ops marker - WindowOps_end = invalid, OpCodes_end = invalid - //!< (internal use) end of all ops marker + //! (internal use) end marker [window types] + Extra_end = invalid, OpCodes_end = invalid + //!< (internal use) end marker [all types] + }; + + //- Some bit masks corresponding to topology controls + // These selectively enable topology-aware handling + enum class topoControls : int + { + broadcast = 1, //!< broadcast [MPI] + reduce = 2, //!< reduce/all-reduce [MPI] + gather = 16, //!< gather (reduction) [manual algorithm] + mapGather = 32, //!< mapGather (reduction) [manual algorithm] + gatherList = 64, //!< gatherList/scatterList [manual algorithm] }; @@ -389,18 +402,18 @@ private: //- Index to the world-communicator as defined at startup //- (after any multi-world definitions). //- Is unaffected by any later changes to worldComm. - static label constWorldComm_; - - //- The number of shared/host nodes in the (const) world communicator. - static label numNodes_; + static int constWorldComm_; //- Index to the inter-node communicator (between nodes), //- defined based on constWorldComm_ - static label commInterNode_; + static int commInterNode_; //- Index to the intra-host communicator (within a node), //- defined based on constWorldComm_ - static label commLocalNode_; + static int commLocalNode_; + + //- The number of shared/host nodes in the (const) world communicator. + static int numNodes_; //- Names of all worlds static wordList allWorlds_; @@ -433,7 +446,7 @@ private: // Private Member Functions //- Set data for parallel running - static void setParRun(const label nProcs, const bool haveThreads); + static void setParRun(const int nProcs, const bool haveThreads); //- Initialise entries for new communicator. // @@ -489,6 +502,180 @@ private: static void freeCommunicatorComponents(const label index); +protected: + + // Protected Member Functions + + // Static Functions + + //- Broadcast buffer contents from rank=0 to all ranks. + //- The sizes must match on all processes. + // For \b non-parallel : do nothing. + // + // \note The method uses a \c void pointer and the required data type + // (as per MPI). This means it should almost never be called directly + // but always via a compile-time checked caller. + // \return True on success + static bool mpi_broadcast + ( + void* buf, + std::streamsize count, + const UPstream::dataTypes dataTypeId, + const int communicator + ); + + //- In-place reduction of \c values with result on rank 0. + // Includes internal parallel guard and checks on data types, opcode. + // + // \note The method uses a \c void pointer and the required data type + // (as per MPI). This means it should almost never be called directly + // but always via a compile-time checked caller. + static void mpi_reduce + ( + void* values, + int count, + const UPstream::dataTypes dataTypeId, + const UPstream::opCodes opCodeId, + const int communicator, + //! [out] request information (for non-blocking) + UPstream::Request* req = nullptr + ); + + //- In-place reduction of \c values with same result on all ranks. + // Includes internal parallel guard and checks on data types, opcode. + // + // \note The method uses a \c void pointer and the required data type + // (as per MPI). This means it should almost never be called directly + // but always via a compile-time checked caller. + static void mpi_allreduce + ( + void* values, + int count, + const UPstream::dataTypes dataTypeId, + const UPstream::opCodes opCodeId, + const int communicator, + //! [out] request information (for non-blocking) + UPstream::Request* req = nullptr + ); + + //- Send buffer contents of specified data type to given processor. + // + // \note The method uses a \c void pointer and the required data type + // (as per MPI). This means it should almost never be called directly + // but always via a compile-time checked caller. + // \return True on success (or Fatal) + static bool mpi_send + ( + const UPstream::commsTypes commsType, + const void* buf, + std::streamsize count, + const UPstream::dataTypes dataTypeId, + const int toProcNo, + const int tag, // eg, UPstream::msgType() + const int communicator, // eg, UPstream::worldComm + //! [out] request information (for non-blocking) + UPstream::Request* req = nullptr, + //! optional send mode (normal | sync) + const UPstream::sendModes sendMode = UPstream::sendModes::normal + ); + + //- Receive buffer contents of specified data type from given processor. + // + // \note The method uses a \c void pointer and the required data type + // (as per MPI). This means it should almost never be called directly + // but always via a compile-time checked caller. + // The commsType will be ignored if UPstream::Request is specified. + // + // \return number of elements read. May change in the future + static std::streamsize mpi_receive + ( + const UPstream::commsTypes commsType, + void* buf, + std::streamsize count, + const UPstream::dataTypes dataTypeId, + const int fromProcNo, + const int tag, // eg, UPstream::msgType() + const int communicator, // eg, UPstream::worldComm + //! [out] request information (for non-blocking) + UPstream::Request* req = nullptr + ); + + //- Receive identically-sized (contiguous) data from all ranks + // Includes internal parallel guard. + // For non-parallel, does not copy any data. + // If needed, this must be done by the caller. + static void mpi_gather + ( + //! On rank: individual value to send (or nullptr for inplace) + const void* sendData, + //! Master: receive buffer with all values + //! Or for in-place send/recv when sendData is nullptr + void* recvData, + //! Number of send/recv data per rank. Globally consistent! + int count, + const UPstream::dataTypes dataTypeId, + const int communicator, + //! [out] request information (for non-blocking) + UPstream::Request* req = nullptr + ); + + //- Send identically-sized (contiguous) data to all ranks + // Includes internal parallel guard. + static void mpi_scatter + ( + //! On master: send buffer with all values (nullptr for inplace) + const void* sendData, + //! On rank: individual value to receive + //! Or for in-place send/recv when sendData is nullptr + void* recvData, + //! Number of send/recv data per rank. Globally consistent! + int count, + const UPstream::dataTypes dataTypeId, + const int communicator, + //! [out] request information (for non-blocking) + UPstream::Request* req = nullptr + ); + + //- Gather/scatter identically-sized data + // Send data from proc slot, receive into all slots + static void mpi_allgather + ( + //! On all ranks: the base of the data locations + void* allData, + //! Number of send/recv data per rank. Globally consistent! + int count, + const UPstream::dataTypes dataTypeId, + const int communicator, + //! [out] request information (for non-blocking) + UPstream::Request* req = nullptr + ); + + //- Receive variable length data from all ranks. + //- (caution: known to scale poorly) + static void mpi_gatherv + ( + const void* sendData, + int sendCount, //!< Ignored on master if recvCount[0] == 0 + void* recvData, //!< Ignored on non-root rank + const UList<int>& recvCounts, //!< Ignored on non-root rank + const UList<int>& recvOffsets, //!< Ignored on non-root rank + const UPstream::dataTypes dataTypeId, + const int communicator + ); + + //- Send variable length data to all ranks + //- (caution: known to scale poorly) + static void mpi_scatterv + ( + const void* sendData, //!< Ignored on non-root rank + const UList<int>& sendCounts, //!< Ignored on non-root rank + const UList<int>& sendOffsets, //!< Ignored on non-root rank + void* recvData, + int recvCount, + const UPstream::dataTypes dataTypeId, + const int communicator + ); + public: //- Declare name of the class and its debug switch @@ -509,13 +696,14 @@ public: // >= 3 : when there are more than N nodes static int nodeCommsMin_; - //- Selection of topology-aware routines + //- Selection of topology-aware routines as a bitmask combination + //- of the topoControls enumerations static int topologyControl_; - //- Test for selection of given topology-aware routine (bitmask) - static bool usingTopoControl(int routine = 0) noexcept + //- Test for selection of given topology-aware routine + static bool usingTopoControl(UPstream::topoControls ctrl) noexcept { - return static_cast<bool>(topologyControl_ & routine); + return static_cast<bool>(topologyControl_ & int(ctrl)); } //- Should compact transfer be used in which floats replace doubles @@ -557,16 +745,16 @@ public: //- Communicator for all ranks, irrespective of any local worlds. // This value \em never changes during a simulation. - static constexpr label commGlobal() noexcept { return 0; } + static constexpr int commGlobal() noexcept { return 0; } //- Communicator within the current rank only // This value \em never changes during a simulation. - static constexpr label commSelf() noexcept { return 1; } + static constexpr int commSelf() noexcept { return 1; } //- Communicator for all ranks (respecting any local worlds). // This value \em never changes after startup. Unlike the commWorld() // which can be temporarily overriden. - static label commConstWorld() noexcept { return constWorldComm_; } + static int commConstWorld() noexcept { return constWorldComm_; } //- Communicator for all ranks (respecting any local worlds) static label commWorld() noexcept { return worldComm; } @@ -601,13 +789,13 @@ public: // Host Communicators //- Communicator between nodes/hosts (respects any local worlds) - static label commInterNode() noexcept + static int commInterNode() noexcept { return (parRun_ ? commInterNode_ : constWorldComm_); } //- Communicator within the node/host (respects any local worlds) - static label commLocalNode() noexcept + static int commLocalNode() noexcept { return (parRun_ ? commLocalNode_ : constWorldComm_); } @@ -626,7 +814,7 @@ public: //- it is running in parallel, the starting point is the //- world-communicator and it is not an odd corner case //- (ie, all processes on one node, all processes on different nodes) - static bool usingNodeComms(const label communicator = worldComm); + static bool usingNodeComms(const int communicator); // Constructors @@ -1168,19 +1356,16 @@ public: } //- The number of shared/host nodes in the (const) world communicator. - static label numNodes() noexcept - { - return numNodes_; - } + static int numNodes() noexcept { return numNodes_; } //- The parent communicator - static label parent(const label communicator) + static label parent(int communicator) { return parentComm_(communicator); } //- The list of ranks within a given communicator - static List<int>& procID(const label communicator) + static List<int>& procID(int communicator) { return procIDs_[communicator]; } @@ -1232,6 +1417,9 @@ public: //- Processor offsets corresponding to the inter-node communicator static const List<int>& interNode_offsets(); + //- The range (start/size) of the commLocalNode ranks in terms of the + //- (const) world communicator processors. + static const rangeType& localNode_parentProcs(); //- Linear communication schedule (special case) for given communicator static const commsStructList& linearCommunication(int communicator); @@ -1240,8 +1428,8 @@ public: static const commsStructList& treeCommunication(int communicator); //- Communication schedule for all-to-master (proc 0) as - //- linear/tree/none with switching based on UPstream::nProcsSimpleSum - //- and the is_parallel() state and the optional \c linear parameter. + //- linear/tree/none with switching based on UPstream::nProcsSimpleSum, + //- the is_parallel() state and the optional \c linear parameter. static const commsStructList& whichCommunication ( const int communicator, @@ -1391,107 +1579,69 @@ public: // Low-level gather/scatter routines - #undef Pstream_CommonRoutines - #define Pstream_CommonRoutines(Type) \ - \ - /*! \brief Receive identically-sized \c Type data from all ranks */ \ - static void mpiGather \ - ( \ - /*! On rank: individual value to send (or nullptr for inplace) */ \ - const Type* sendData, \ - /*! Master: receive buffer with all values */ \ - /*! Or for in-place send/recv when sendData is nullptr */ \ - Type* recvData, \ - /*! Number of send/recv data per rank. Globally consistent! */ \ - int count, \ - const label communicator = worldComm \ - ); \ - \ - /*! \brief Send identically-sized \c Type data to all ranks */ \ - static void mpiScatter \ - ( \ - /*! Master: send buffer with all values (nullptr for inplace) */ \ - const Type* sendData, \ - /*! On rank: individual value to receive */ \ - /*! Or for in-place send/recv when sendData is nullptr */ \ - Type* recvData, \ - /*! Number of send/recv data per rank. Globally consistent! */ \ - int count, \ - const label communicator = worldComm \ - ); \ - \ - /*! \brief Gather/scatter identically-sized \c Type data */ \ - /*! Send data from proc slot, receive into all slots */ \ - static void mpiAllGather \ - ( \ - /*! On all ranks: the base of the data locations */ \ - Type* allData, \ - /*! Number of send/recv data per rank. Globally consistent! */ \ - int count, \ - const label communicator = worldComm \ - ); \ - \ - /*! \brief Receive variable length \c Type data from all ranks */ \ - static void mpiGatherv \ - ( \ - const Type* sendData, \ - int sendCount, /*!< Ignored on master if recvCount[0] == 0 */ \ - Type* recvData, /*!< Ignored on non-root rank */ \ - const UList<int>& recvCounts, /*!< Ignored on non-root rank */ \ - const UList<int>& recvOffsets, /*!< Ignored on non-root rank */ \ - const label communicator = worldComm \ - ); \ - \ - /*! \brief Send variable length \c Type data to all ranks */ \ - static void mpiScatterv \ - ( \ - const Type* sendData, /*!< Ignored on non-root rank */ \ - const UList<int>& sendCounts, /*!< Ignored on non-root rank */ \ - const UList<int>& sendOffsets, /*!< Ignored on non-root rank */ \ - Type* recvData, \ - int recvCount, \ - const label communicator = worldComm \ - ); \ - \ - /*! \deprecated(2025-02) prefer mpiGatherv */ \ - FOAM_DEPRECATED_FOR(2025-02, "mpiGatherv()") \ - inline static void gather \ - ( \ - const Type* send, \ - int count, \ - Type* recv, \ - const UList<int>& counts, \ - const UList<int>& offsets, \ - const label comm = worldComm \ - ) \ - { \ - UPstream::mpiGatherv(send, count, recv, counts, offsets, comm); \ - } \ - \ - /*! \deprecated(2025-02) prefer mpiScatterv */ \ - FOAM_DEPRECATED_FOR(2025-02, "mpiScatterv()") \ - inline static void scatter \ - ( \ - const Type* send, \ - const UList<int>& counts, \ - const UList<int>& offsets, \ - Type* recv, \ - int count, \ - const label comm = worldComm \ - ) \ - { \ - UPstream::mpiScatterv(send, counts, offsets, recv, count, comm); \ - } + //- Receive identically-sized (contiguous) data from all ranks + template<class Type> + static void mpiGather + ( + //! On rank: individual value to send (or nullptr for inplace) + const Type* sendData, + //! Master: receive buffer with all values + //! Or for in-place send/recv when sendData is nullptr + Type* recvData, + //! Number of send/recv data per rank. Globally consistent! + int count, + const int communicator = UPstream::worldComm + ); - Pstream_CommonRoutines(char); - Pstream_CommonRoutines(int32_t); - Pstream_CommonRoutines(int64_t); - Pstream_CommonRoutines(uint32_t); - Pstream_CommonRoutines(uint64_t); - Pstream_CommonRoutines(float); - Pstream_CommonRoutines(double); + //- Send identically-sized (contiguous) data to all ranks + template<class Type> + static void mpiScatter + ( + //! On master: send buffer with all values (nullptr for inplace) + const Type* sendData, + //! On rank: individual value to receive + //! Or for in-place send/recv when sendData is nullptr + Type* recvData, + //! Number of send/recv data per rank. Globally consistent! + int count, + const int communicator = UPstream::worldComm + ); - #undef Pstream_CommonRoutines + //- Gather/scatter identically-sized data + // Send data from proc slot, receive into all slots + template<class Type> + static void mpiAllGather + ( + //! On all ranks: the base of the data locations + Type* allData, + //! Number of send/recv data per rank. Globally consistent! + int count, + const int communicator = UPstream::worldComm + ); + + //- Receive variable length data from all ranks + template<class Type> + static void mpiGatherv + ( + const Type* sendData, + int sendCount, //!< Ignored on master if recvCount[0] == 0 + Type* recvData, //!< Ignored on non-root rank + const UList<int>& recvCounts, //!< Ignored on non-root rank + const UList<int>& recvOffsets, //!< Ignored on non-root rank + const int communicator = UPstream::worldComm + ); + + //- Send variable length data to all ranks + template<class Type> + static void mpiScatterv + ( + const Type* sendData, //!< Ignored on non-root rank + const UList<int>& sendCounts, //!< Ignored on non-root rank + const UList<int>& sendOffsets, //!< Ignored on non-root rank + Type* recvData, + int recvCount, + const int communicator = UPstream::worldComm + ); // Gather single, contiguous value(s) @@ -1502,7 +1652,7 @@ public: static List<T> allGatherValues ( const T& localValue, - const label communicator = worldComm + const int communicator = UPstream::worldComm ); //- Gather individual values into list locations. @@ -1514,7 +1664,7 @@ public: static List<T> listGatherValues ( const T& localValue, - const label communicator = worldComm + const int communicator = UPstream::worldComm ); //- Scatter individual values from list locations. @@ -1526,22 +1676,59 @@ public: static T listScatterValues ( const UList<T>& allValues, - const label communicator = worldComm + const int communicator = UPstream::worldComm ); // Broadcast Functions - //- Broadcast buffer contents to all processes in given communicator. - //- The sizes must match on all processes. + //- Broadcast buffer contents (contiguous types), from rank=0 + //- to all ranks. The sizes must match on all processes. // For \b non-parallel : do nothing. // \return True on success - static bool broadcast + template<class Type> + inline static bool broadcast ( - char* buf, - const std::streamsize bufSize, - const label communicator, - const int rootProcNo = masterNo() + Type* buffer, + std::streamsize count, + const int communicator + ); + + + // Reductions + + //- MPI_Reduce (blocking) for known operators + // For \b non-parallel : do nothing. + template<class T> + static void mpiReduce + ( + T values[], + int count, + const UPstream::opCodes opCodeId, + const int communicator + ); + + //- MPI_Allreduce (blocking) for known operators + // For \b non-parallel : do nothing. + template<class T> + static void mpiAllReduce + ( + T values[], + int count, + const UPstream::opCodes opCodeId, + const int communicator + ); + + //- MPI_Iallreduce (non-blocking) for known operators + // For \b non-parallel : do nothing. + template<class T> + static void mpiAllReduce + ( + T values[], + int count, + const UPstream::opCodes opCodeId, + const int communicator, + UPstream::Request& req ); @@ -1552,7 +1739,7 @@ public: static void reduceAnd ( bool& value, - const label communicator = worldComm + const int communicator = worldComm ); //- Logical (or) reduction (MPI_AllReduce) @@ -1560,7 +1747,7 @@ public: static void reduceOr ( bool& value, - const label communicator = worldComm + const int communicator = worldComm ); @@ -1603,6 +1790,38 @@ public: // Should normally be restricted to a particular starting request. FOAM_DEPRECATED_FOR(2023-01, "waitRequests(int) method") static void waitRequests() { waitRequests(0); } + + //- \deprecated(2025-02) prefer mpiGatherv + template<class Type> + FOAM_DEPRECATED_FOR(2025-02, "mpiGatherv()") + static void gather + ( + const Type* send, + int count, + Type* recv, + const UList<int>& counts, + const UList<int>& offsets, + const int comm = UPstream::worldComm + ) + { + UPstream::mpiGatherv(send, count, recv, counts, offsets, comm); + } + + //- \deprecated(2025-02) prefer mpiScatterv + template<class Type> + FOAM_DEPRECATED_FOR(2025-02, "mpiScatterv()") + static void scatter + ( + const Type* send, + const UList<int>& counts, + const UList<int>& offsets, + Type* recv, + int count, + const int comm = UPstream::worldComm + ) + { + UPstream::mpiScatterv(send, counts, offsets, recv, count, comm); + } }; @@ -1691,7 +1910,7 @@ public: // UPstream::Communicator::lookup(UPstream::commWorld()) // ) // \endcode - static Communicator lookup(const label comm); + static Communicator lookup(const int comm); // Member Functions @@ -1710,6 +1929,9 @@ public: //- Reset to default constructed value (MPI_COMM_NULL) void reset() noexcept; + + //- The number of ranks associated with the communicator + int size() const; }; diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.txx b/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.txx index 844b203446d01f593670d2cd32a9cecb4cebe8aa..1e529ac018e5444e5c3d8977c373f38dfde88a1a 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.txx +++ b/src/OpenFOAM/db/IOstreams/Pstreams/UPstream.txx @@ -27,83 +27,238 @@ License // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -template<class T> -Foam::List<T> Foam::UPstream::allGatherValues +template<class Type> +bool Foam::UPstream::broadcast ( - const T& localValue, - const label comm + Type* buffer, + std::streamsize count, + const int communicator ) { - if constexpr (!is_contiguous_v<T>) + // Likely no reason to check for nullptr + if (!UPstream::is_parallel(communicator)) { + // Nothing to do - ignore + return true; + } + else if constexpr (!is_contiguous_v<Type>) + { + // Also report parameters to silence compiler warnings about unused FatalErrorInFunction - << "Cannot all-gather values for non-contiguous types" - " - consider Pstream variant instead" << endl + << "Invalid for non-contiguous data types." + << " buffer:" << (buffer != nullptr) + << " count:" << count << Foam::abort(FatalError); + return false; } + else + { + // Use element or component type (or byte-wise) for data type + return UPstream::mpi_broadcast + ( + buffer, // The data or cmpt pointer + UPstream_dataType<Type>::size(count), + UPstream_dataType<Type>::datatype_id, + communicator + ); + } +} - List<T> allValues; - if (UPstream::is_parallel(comm)) +template<class Type> +void Foam::UPstream::mpiGather +( + const Type* sendData, + Type* recvData, + int count, + const int communicator +) +{ + if (!count || !UPstream::is_rank(communicator)) + { + // Nothing to do + return; + } + else if constexpr (!is_contiguous_v<Type>) + { + FatalErrorInFunction + << "Invalid for non-contiguous data types" + << Foam::abort(FatalError); + } + else if (!UPstream::is_parallel(communicator)) + { + // Perform any fallback copying here, while we still know the Type + if (sendData && recvData && (sendData != recvData)) + { + std::memmove(recvData, sendData, count*sizeof(Type)); + } + } + else { - allValues.resize(UPstream::nProcs(comm)); - allValues[UPstream::myProcNo(comm)] = localValue; + // Use element or component type (or byte-wise) for data type + UPstream::mpi_gather + ( + sendData, // The data or cmpt pointer + recvData, // The data or cmpt pointer + UPstream_dataType<Type>::size(count), + UPstream_dataType<Type>::datatype_id, + communicator + ); + } +} + - UPstream::mpiAllGather(allValues.data_bytes(), sizeof(T), comm); +template<class Type> +void Foam::UPstream::mpiScatter +( + const Type* sendData, + Type* recvData, + int count, + const int communicator +) +{ + if (!count || !UPstream::is_rank(communicator)) + { + // Nothing to do + return; + } + else if constexpr (!is_contiguous_v<Type>) + { + FatalErrorInFunction + << "Invalid for non-contiguous data types" + << Foam::abort(FatalError); + } + else if (!UPstream::is_parallel(communicator)) + { + // Perform any fallback copying here, while we still know the Type + if (sendData && recvData && (sendData != recvData)) + { + std::memmove(recvData, sendData, count*sizeof(Type)); + } } else + { + // Use element or component type (or byte-wise) for data type + UPstream::mpi_scatter + ( + sendData, // The data or cmpt pointer + recvData, // The data or cmpt pointer + UPstream_dataType<Type>::size(count), + UPstream_dataType<Type>::datatype_id, + communicator + ); + } +} + + +template<class Type> +void Foam::UPstream::mpiAllGather +( + Type* allData, + int count, + const int communicator +) +{ + if (!count || !UPstream::is_parallel(communicator)) + { + // Nothing sensible to do + return; + } + else if constexpr (!is_contiguous_v<Type>) + { + FatalErrorInFunction + << "Invalid for non-contiguous data types" + << Foam::abort(FatalError); + } + else + { + // Use element or component type (or byte-wise) for data type + UPstream::mpi_allgather + ( + allData, // The data or cmpt pointer + UPstream_dataType<Type>::size(count), + UPstream_dataType<Type>::datatype_id, + communicator + ); + } +} + + +template<class T> +Foam::List<T> Foam::UPstream::allGatherValues +( + const T& localValue, + const int communicator +) +{ + if (!UPstream::is_parallel(communicator)) { // non-parallel: return own value // TBD: only when UPstream::is_rank(comm) as well? - allValues.resize(1); + List<T> allValues(1); allValues[0] = localValue; + return allValues; } + else if constexpr (!is_contiguous_v<T>) + { + FatalErrorInFunction + << "Cannot all-gather values for non-contiguous types" + << " - consider Pstream variant instead" << endl + << Foam::abort(FatalError); + return List<T>(); + } + else + { + // Standard gather with direct MPI communication + List<T> allValues; - return allValues; + allValues.resize(UPstream::nProcs(communicator)); + allValues[UPstream::myProcNo(communicator)] = localValue; + + UPstream::mpiAllGather(allValues.data(), 1, communicator); + return allValues; + } } +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + template<class T> Foam::List<T> Foam::UPstream::listGatherValues ( const T& localValue, - const label comm + const int communicator ) { - if constexpr (!is_contiguous_v<T>) + if (!UPstream::is_parallel(communicator)) + { + // non-parallel: return own value + // TBD: only when UPstream::is_rank(communicator) as well? + List<T> allValues(1); + allValues[0] = localValue; + return allValues; + } + else if constexpr (!is_contiguous_v<T>) { FatalErrorInFunction << "Cannot gather values for non-contiguous types" " - consider Pstream variant instead" << endl << Foam::abort(FatalError); + return List<T>(); } - - List<T> allValues; - - if (UPstream::is_parallel(comm)) + else { - if (UPstream::master(comm)) + // Local sizes are identical, can use MPI_Gather + List<T> allValues; + + if (UPstream::master(communicator)) { - allValues.resize(UPstream::nProcs(comm)); + allValues.resize(UPstream::nProcs(communicator)); } - UPstream::mpiGather - ( - reinterpret_cast<const char*>(&localValue), - allValues.data_bytes(), - sizeof(T), // The send/recv size per rank - comm - ); - } - else - { - // non-parallel: return own value - // TBD: only when UPstream::is_rank(comm) as well? - allValues.resize(1); - allValues[0] = localValue; + UPstream::mpiGather(&localValue, allValues.data(), 1, communicator); + return allValues; } - - return allValues; } @@ -111,51 +266,252 @@ template<class T> T Foam::UPstream::listScatterValues ( const UList<T>& allValues, - const label comm + const int communicator ) { - if constexpr (!is_contiguous_v<T>) + if (!UPstream::is_parallel(communicator)) + { + // non-parallel: return own value + // TBD: only when UPstream::is_rank(communicator) as well? + + if (!allValues.empty()) + { + return allValues[0]; + } + + return T{}; // Fallback value + } + else if constexpr (!is_contiguous_v<T>) { FatalErrorInFunction - << "Cannot scatter values for non-contiguous types" + << "Cannot scatter non-contiguous values" " - consider Pstream variant instead" << endl << Foam::abort(FatalError); - } - - T localValue{}; - if (UPstream::is_parallel(comm)) + return T{}; // Fallback value + } + else { - const label numProc = UPstream::nProcs(comm); + // Local sizes are identical, can use MPI_Scatter + + const label nProcs = UPstream::nProcs(communicator); - if (UPstream::master(comm) && allValues.size() < numProc) + if + ( + FOAM_UNLIKELY + ( + UPstream::master(communicator) + && allValues.size() < nProcs + ) + ) { FatalErrorInFunction << "Attempting to send " << allValues.size() - << " values to " << numProc << " processors" << endl + << " values to " << nProcs << " processors" << endl << Foam::abort(FatalError); } - UPstream::mpiScatter + T localValue{}; + UPstream::mpiScatter(allValues.cdata(), &localValue, 1, communicator); + return localValue; + } +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +template<class Type> +void Foam::UPstream::mpiGatherv +( + const Type* sendData, + int sendCount, + Type* recvData, + const UList<int>& recvCounts, + const UList<int>& recvOffsets, + const int communicator +) +{ + if (!UPstream::is_parallel(communicator)) + { + if constexpr (is_contiguous_v<Type>) + { + if (sendData && recvData) + { + // recvCounts[0] may be invalid - use sendCount instead + std::memmove(recvData, sendData, sendCount*sizeof(Type)); + } + } + // Nothing further to do + } + else if constexpr (UPstream_basic_dataType<Type>::value) + { + // Restrict to basic (or aliased) MPI types to avoid recalculating + // the list of counts/offsets. + + UPstream::mpi_gatherv ( - allValues.cdata_bytes(), - reinterpret_cast<char*>(&localValue), - sizeof(T), // The send/recv size per rank - comm + sendData, + sendCount, + recvData, + recvCounts, + recvOffsets, + + UPstream_basic_dataType<Type>::datatype_id, + communicator ); } else { - // non-parallel: return first value - // TBD: only when UPstream::is_rank(comm) as well? + static_assert + ( + stdFoam::dependent_false_v<Type>, "Only basic MPI data types" + ); + } +} - if (!allValues.empty()) + +template<class Type> +void Foam::UPstream::mpiScatterv +( + const Type* sendData, + const UList<int>& sendCounts, + const UList<int>& sendOffsets, + Type* recvData, + int recvCount, + const int communicator +) +{ + if (!UPstream::is_parallel(communicator)) + { + if constexpr (is_contiguous_v<Type>) { - return allValues[0]; + if (sendData && recvData) + { + std::memmove(recvData, sendData, recvCount*sizeof(Type)); + } } - } + // Nothing further to do + } + else if constexpr (UPstream_basic_dataType<Type>::value) + { + // Restrict to basic (or aliased) MPI types to avoid recalculating + // the list of counts/offsets. + + UPstream::mpi_scatterv + ( + sendData, + sendCounts, + sendOffsets, + recvData, + recvCount, - return localValue; + UPstream_basic_dataType<Type>::datatype_id, + communicator + ); + } + else + { + static_assert + ( + stdFoam::dependent_false_v<Type>, "Only basic MPI data types" + ); + } +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +template<class T> +void Foam::UPstream::mpiReduce +( + T values[], + int count, + const UPstream::opCodes opCodeId, + const int communicator +) +{ + if (!count || !UPstream::is_parallel(communicator)) + { + // Nothing to do + return; + } + else + { + // Use element or component type (or byte-wise) for data type + // Restricted to basic data types + UPstream::mpi_reduce + ( + values, // The data or cmpt pointer + UPstream_basic_dataType<T>::size(count), + UPstream_basic_dataType<T>::datatype_id, + opCodeId, + communicator + ); + } +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +template<class T> +void Foam::UPstream::mpiAllReduce +( + T values[], + int count, + const UPstream::opCodes opCodeId, + const int communicator +) +{ + if (!count || !UPstream::is_parallel(communicator)) + { + // Nothing to do + return; + } + else + { + // Use element or component type (or byte-wise) for data type + // Restricted to basic data types + UPstream::mpi_allreduce + ( + values, // The data or cmpt pointer + UPstream_basic_dataType<T>::size(count), + UPstream_basic_dataType<T>::datatype_id, + opCodeId, + communicator + ); + } +} + + +template<class T> +void Foam::UPstream::mpiAllReduce +( + T values[], + int count, + const UPstream::opCodes opCodeId, + const int communicator, + UPstream::Request& req +) +{ + if (!count || !UPstream::is_parallel(communicator)) + { + // Nothing to do + return; + } + else + { + // Use element or component type (or byte-wise) for data type + // Restricted to basic data types + UPstream::mpi_allreduce + ( + values, // The data or cmpt pointer + UPstream_basic_dataType<T>::size(count), + UPstream_basic_dataType<T>::datatype_id, + opCodeId, + communicator, + &req + ); + } } diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UPstreamTraits.H b/src/OpenFOAM/db/IOstreams/Pstreams/UPstreamTraits.H index 224300002d4750fd6cee9714d7d63c4e28815165..ec0d3ad8631bc1b3695090f2d0003755f8e5019f 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/UPstreamTraits.H +++ b/src/OpenFOAM/db/IOstreams/Pstreams/UPstreamTraits.H @@ -26,28 +26,50 @@ License Description A set of traits associated with UPstream communication - - UPstream_dataType trait: - This wrapper is unwinds the type to check against base/alias, but also - checks if it is a component aggregate of a supported UPstream data type. - This will be that main entry point for usage. + \par Front-facing traits - - UPstream_opType trait: - Provides a mapping of OpenFOAM ops to their MPI equivalent. + - \c UPstream_basic_dataType trait :<br> + The main entry point for reduction operations + (requires fundamental types).<br> + Checks against fundamental/aliased (excludes user-defined), + or is a component-wise aggregate of the same. + + - \c UPstream_dataType trait :<br> + The main entry point for transmission (broadcast, send/recv, ...).<br> + Checks against fundamental/aliased/user-defined, + or is a component-wise aggregate of the same. + + - \c UPstream_opType trait :<br> + Mapping of OpenFOAM ops to their MPI equivalent. The \c opcode_id is the corresponding internal representation. -Note - Additional helper traits: + - \c UPstream_data_opType trait :<br> + Combination of UPstream_opType and UPstream_basic_dataType. + . + + \par Additional helper traits (not normally used directly): - - UPstream_base_dataType trait: - Tests true/false if the specified data type has an internal - MPI equivalent. The \c datatype_id is the corresponding - internal enumeration. Even if this tests as false, it will - always return \c type_byte as the fallback for general contiguous data + - \c UPstream_mpi_dataType trait :<br> + Tests true and provides valid \c datatype_id for MPI fundamental + data types. This trait will should not normally be used directly: + use UPstream_alias_dataType for 'low-level' purposes (see below). - - UPstream_alias_dataType trait: - Provides mapping for <int/long/long long,...> to the fundamental + - \c UPstream_user_dataType trait :<br> + Tests true and provides valid \c datatype_id for user-defined + data types. + + - \c UPstream_alias_dataType trait :<br> + Use this in preference to UPstream_mpi_dataType.<br> + A pass-through to UPstream_mpi_dataType, but provides additional + mappings for <int/long/long long,...> to the fundamental 32/64 bit integrals, since <int/long/long long,...> may not otherwise - directly map on all systems. + map directly on all systems. + + - \c UPstream_any_dataType trait :<br> + Used as a building block for uniform aggregate types.<br> + Combines UPstream_user_dataType and UPstream_alias_dataType into a + single trait. + . \*---------------------------------------------------------------------------*/ @@ -88,130 +110,37 @@ template<class T> class Tensor; // template<class T> struct bitXorOp; //! \cond +template<class T> struct UPstream_basic_dataType; template<class T> struct UPstream_dataType; -template<class T> struct UPstream_opType; //! \endcond // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -// Base traits - -//- A supported UPstream (MPI) reduce/window operation type -template<class T> -struct UPstream_opType : std::false_type -{ - static constexpr auto opcode_id = UPstream::opCodes::invalid; -}; - - -//- A supported UPstream data type (intrinsic or user-defined) +//- UPstream data type corresponding to a fundamental (MPI) type template<class T> -struct UPstream_base_dataType : std::false_type +struct UPstream_mpi_dataType : std::false_type { static constexpr auto datatype_id = UPstream::dataTypes::invalid; }; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -// Trait specializations (op-codes) - -//- Map minOp\<T\> to \c UPstream::opCodes::op_min -template<class T> -struct UPstream_opType<Foam::minOp<T>> : std::true_type -{ - static constexpr auto opcode_id = UPstream::opCodes::op_min; -}; - -//- Map maxOp\<T\> to \c UPstream::opCodes::op_max -template<class T> -struct UPstream_opType<Foam::maxOp<T>> : std::true_type +//- Disallow \c void +template<> struct UPstream_mpi_dataType<void> : std::false_type { - static constexpr auto opcode_id = UPstream::opCodes::op_max; -}; - -//- Map sumOp\<T\> to \c UPstream::opCodes::op_sum -template<class T> -struct UPstream_opType<Foam::sumOp<T>> : std::true_type -{ - static constexpr auto opcode_id = UPstream::opCodes::op_sum; -}; - -//- Map plusOp\<T\> to \c UPstream::opCodes::op_sum -//- as a recognized alternative to sumOp\<T\> -template<class T> -struct UPstream_opType<Foam::plusOp<T>> : std::true_type -{ - static constexpr auto opcode_id = UPstream::opCodes::op_sum; -}; - -//- Map multiplyOp\<T\> to \c UPstream::opCodes::op_prod -template<class T> -struct UPstream_opType<Foam::multiplyOp<T>> : std::true_type -{ - static constexpr auto opcode_id = UPstream::opCodes::op_prod; -}; - -// NOTE (2025-02): -// currently no mappings provided for -// (op_bool_and, op_bool_or, op_bool_xor) until the calling semantics -// have been properly defined - - -// These are only viable for unsigned integral types, -// probably not for signed integral types. -// Be extra restrictive for now - -//- Map bitAndOp\<T\> to \c UPstream::opCodes::op_bit_and -//- (for unsigned integrals) -template<class T> -struct UPstream_opType<Foam::bitAndOp<T>> -: - // ie, std::unsigned_integral<T> concept - std::bool_constant<std::is_integral_v<T> && !std::is_signed_v<T>> -{ - static constexpr auto opcode_id = []() constexpr noexcept - { - if constexpr (std::is_integral_v<T> && !std::is_signed_v<T>) - return UPstream::opCodes::op_bit_and; - else - return UPstream::opCodes::invalid; - }(); + static constexpr auto datatype_id = UPstream::dataTypes::invalid; }; -//- Map bitOrOp\<T\> to \c UPstream::opCodes::op_bit_or -//- (for unsigned integrals) +//- UPstream data type corresponding to user-defined type template<class T> -struct UPstream_opType<Foam::bitOrOp<T>> -: - // ie, std::unsigned_integral<T> concept - std::bool_constant<std::is_integral_v<T> && !std::is_signed_v<T>> +struct UPstream_user_dataType : std::false_type { - static constexpr auto opcode_id = []() constexpr noexcept - { - if constexpr (std::is_integral_v<T> && !std::is_signed_v<T>) - return UPstream::opCodes::op_bit_or; - else - return UPstream::opCodes::invalid; - }(); + static constexpr auto datatype_id = UPstream::dataTypes::invalid; }; -//- Map bitXorOp\<T\> to \c UPstream::opCodes::op_bit_xor -//- (for unsigned integrals) -template<class T> -struct UPstream_opType<Foam::bitXorOp<T>> -: - // ie, std::unsigned_integral<T> concept - std::bool_constant<std::is_integral_v<T> && !std::is_signed_v<T>> +//- Disallow \c void +template<> struct UPstream_user_dataType<void> : std::false_type { - static constexpr auto opcode_id = []() constexpr noexcept - { - if constexpr (std::is_integral_v<T> && !std::is_signed_v<T>) - return UPstream::opCodes::op_bit_xor; - else - return UPstream::opCodes::invalid; - }(); + static constexpr auto datatype_id = UPstream::dataTypes::invalid; }; @@ -219,36 +148,59 @@ struct UPstream_opType<Foam::bitXorOp<T>> // Trait specializations (data types) -// Specializations to match elements of UPstream::dataTypes +// Specializations to match elements of UPstream::dataTypes. + #undef defineUPstreamDataTraits #define defineUPstreamDataTraits(TypeId, Type) \ \ /*! \brief Map \c Type to UPstream::dataTypes::TypeId */ \ - template<> struct UPstream_base_dataType<Type> : std::true_type \ + template<> struct UPstream_mpi_dataType<Type> : std::true_type \ { \ static constexpr auto datatype_id = UPstream::dataTypes::TypeId; \ }; \ /*! \brief Map \c const \c Type to \c UPstream::dataTypes::TypeId */ \ - template<> struct UPstream_base_dataType<const Type> : std::true_type \ + template<> struct UPstream_mpi_dataType<const Type> : std::true_type \ { \ static constexpr auto datatype_id = UPstream::dataTypes::TypeId; \ }; - -// Intrinsic Types [8]: +// Fundamental Types [10]: // Note: uses 'int32_t,int64_t,...' instead of 'int,long,...' to minimize -// the possibility of duplicates types. +// the possibility of duplicate types. However, 'int8_t,uint8_t' are treated +// as aliases (char,unsigned char) to avoid possible compilation issues. +// // OpenFOAM defines Foam::label as either int32_t,int64_t (not int,long) too. defineUPstreamDataTraits(type_byte, char); defineUPstreamDataTraits(type_byte, unsigned char); +defineUPstreamDataTraits(type_int16, int16_t); defineUPstreamDataTraits(type_int32, int32_t); defineUPstreamDataTraits(type_int64, int64_t); +defineUPstreamDataTraits(type_uint16, uint16_t); defineUPstreamDataTraits(type_uint32, uint32_t); defineUPstreamDataTraits(type_uint64, uint64_t); defineUPstreamDataTraits(type_float, float); defineUPstreamDataTraits(type_double, double); defineUPstreamDataTraits(type_long_double, long double); +#undef defineUPstreamDataTraits + +// ------------------------------------------------------------------------- // + +#undef defineUPstreamDataTraits +#define defineUPstreamDataTraits(TypeId, Type) \ + \ + /*! \brief Map \c Type to UPstream::dataTypes::TypeId */ \ + template<> struct UPstream_user_dataType<Type> : std::true_type \ + { \ + static constexpr auto datatype_id = UPstream::dataTypes::TypeId; \ + }; \ + /*! \brief Map \c const \c Type to \c UPstream::dataTypes::TypeId */ \ + template<> struct UPstream_user_dataType<const Type> : std::true_type \ + { \ + static constexpr auto datatype_id = UPstream::dataTypes::TypeId; \ + }; + + // User Types [6]: defineUPstreamDataTraits(type_3float, Vector<float>); defineUPstreamDataTraits(type_3double, Vector<double>); @@ -264,14 +216,17 @@ defineUPstreamDataTraits(type_9double, Tensor<double>); //- Explicit handling of data type aliases. This is necessary since //- different systems map things like 'unsigned long' differently but we -//- restrict ourselves to int32/int64 types +//- restrict ourselves to int32/int64 types. +// +// Note that this trait serves as the single pass-through point when needing +// to reference UPstream_mpi_dataType elsewhere template<class T> struct UPstream_alias_dataType : std::bool_constant < - // Base type (no alias needed) - UPstream_base_dataType<std::remove_cv_t<T>>::value || + // Basic MPI type + UPstream_mpi_dataType<std::remove_cv_t<T>>::value || ( // Or some int 32/64 type to re-map std::is_integral_v<T> @@ -279,14 +234,10 @@ struct UPstream_alias_dataType ) > { - // Is it using the base type? (no alias needed) - static constexpr bool is_base = - UPstream_base_dataType<std::remove_cv_t<T>>::value; - using base = std::conditional_t < - UPstream_base_dataType<std::remove_cv_t<T>>::value, - std::remove_cv_t<T>, // <- using base + UPstream_mpi_dataType<std::remove_cv_t<T>>::value, + std::remove_cv_t<T>, // <- using mpi type (no alias) std::conditional_t // <- using alias < ( @@ -304,66 +255,342 @@ struct UPstream_alias_dataType >; static constexpr auto datatype_id = - UPstream_base_dataType<base>::datatype_id; + UPstream_mpi_dataType<base>::datatype_id; +}; + + +// Handle int8_t/uint8_t as aliases since 'signed char' etc may be +// ambiguous + +//- Map \c int8_t to UPstream::dataTypes::type_byte +template<> +struct UPstream_alias_dataType<int8_t> : std::true_type +{ + using base = char; + static constexpr auto datatype_id = UPstream::dataTypes::type_byte; +}; + +//- Map \c uint8_t to UPstream::dataTypes::type_byte +template<> +struct UPstream_alias_dataType<uint8_t> : std::true_type +{ + using base = unsigned char; + static constexpr auto datatype_id = UPstream::dataTypes::type_byte; +}; + +// ------------------------------------------------------------------------- // + +//- UPstream data type (fundamental or user-defined), +//- after resolving any aliases +template<class T> +struct UPstream_any_dataType +: + std::bool_constant + < + UPstream_user_dataType<std::remove_cv_t<T>>::value + || UPstream_alias_dataType<T>::value + > +{ + using base = std::conditional_t + < + UPstream_user_dataType<std::remove_cv_t<T>>::value, + std::remove_cv_t<T>, + typename UPstream_alias_dataType<T>::base + >; + + //- The corresponding UPstream::dataTypes enumeration + static constexpr auto datatype_id = []() constexpr noexcept + { + if constexpr (UPstream_user_dataType<std::remove_cv_t<T>>::value) + { + // A user-defined type + return UPstream_user_dataType<std::remove_cv_t<T>>::datatype_id; + } + else if constexpr (UPstream_alias_dataType<T>::value) + { + // Fundamental type or alias to a fundamental type + return UPstream_alias_dataType<T>::datatype_id; + } + else + { + return UPstream::dataTypes::invalid; + } + }(); }; // ------------------------------------------------------------------------- // -//- A supported UPstream data type (fundamental or user-defined) -//- or a component aggregate of a supported UPstream data type. +//- UPstream fundamental/aliased (excludes user-defined) data type +//- or a component aggregate of the same. // -// Is true for the following conditions: +// True for the following conditions: // - The \c Type is directly supported // - The \c cmptType (eg, from VectorSpace) exists and is directly supported // - Fallback to byte-wise representation (ie, for contiguous) // . template<class T> -struct UPstream_dataType +struct UPstream_basic_dataType : std::bool_constant < + // non-aggregate type UPstream_alias_dataType<T>::value + // aggregate type || UPstream_alias_dataType<typename pTraits_cmptType<T>::type>::value > { - // Is it using the base type? (ie, not using components) - static constexpr bool is_base = UPstream_alias_dataType<T>::value; - //- The underlying data type (if supported) or byte using base = std::conditional_t < UPstream_alias_dataType<T>::value, - typename UPstream_alias_dataType<T>::base, // <- using base + typename UPstream_alias_dataType<T>::base, // <- non-aggregate typename UPstream_alias_dataType - <typename pTraits_cmptType<T>::type>::base // <- using components + <typename pTraits_cmptType<T>::type>::base // <- aggregate >; //- The corresponding UPstream::dataTypes enumeration static constexpr auto datatype_id = - UPstream_base_dataType<base>::datatype_id; + UPstream_alias_dataType<base>::datatype_id; //- The size in terms of the number of underlying data elements - static std::streamsize size(std::streamsize count) noexcept + static std::streamsize size(std::streamsize n) noexcept { if constexpr (UPstream_alias_dataType<T>::value) { - // using base: no multiplier - return count; + // non-aggregate: no multiplier + return n; } else { - // using components: with multiplier - return count*(sizeof(T)/sizeof(base)); + // aggregate: with multiplier + return n*(sizeof(T)/sizeof(base)); } } }; +//- Disallow \c void +template<> struct UPstream_basic_dataType<void> : UPstream_mpi_dataType<void> +{ + using base = void; + static std::streamsize size(std::streamsize n) noexcept { return n; } +}; + + +// ------------------------------------------------------------------------- // + +//- UPstream fundamental/aliased/user-defined data type +//- or a component aggregate of the same. +// +// True for the following conditions: +// - The \c Type is directly supported +// - The \c cmptType (eg, from VectorSpace) exists and is directly supported +// - Fallback to byte-wise representation (ie, for contiguous) +// . +template<class T> +struct UPstream_dataType +: + std::bool_constant + < + UPstream_any_dataType<T>::value + || UPstream_any_dataType<typename pTraits_cmptType<T>::type>::value + > +{ + //- The underlying data type (if supported) or byte + using base = std::conditional_t + < + UPstream_any_dataType<T>::value, + typename UPstream_any_dataType<T>::base, // <- non-aggregate + typename UPstream_any_dataType + <typename pTraits_cmptType<T>::type>::base // <- aggregate + >; + + //- The corresponding UPstream::dataTypes enumeration + static constexpr auto datatype_id = + UPstream_any_dataType<base>::datatype_id; + + //- The size in terms of the number of base data elements + static std::streamsize size(std::streamsize n) noexcept + { + if constexpr (UPstream_any_dataType<T>::value) + { + // non-aggregate: no multiplier + return n; + } + else + { + // aggregate: with multiplier + return n*(sizeof(T)/sizeof(base)); + } + } +}; + +//- Disallow \c void +template<> struct UPstream_dataType<void> : UPstream_basic_dataType<void> {}; + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -} // End namespace Foam +// Reduction op-codes + +//- A supported UPstream (MPI) reduce/window operation type +template<class BinaryOp> +struct UPstream_opType : std::false_type +{ + static constexpr auto opcode_id = UPstream::opCodes::invalid; +}; + +//- Disallow \c void +template<> struct UPstream_opType<void> : std::false_type +{ + static constexpr auto opcode_id = UPstream::opCodes::invalid; +}; + +//- Map minOp\<T\> to \c UPstream::opCodes::op_min +template<class T> +struct UPstream_opType<Foam::minOp<T>> : std::true_type +{ + static constexpr auto opcode_id = UPstream::opCodes::op_min; +}; + +//- Map maxOp\<T\> to \c UPstream::opCodes::op_max +template<class T> +struct UPstream_opType<Foam::maxOp<T>> : std::true_type +{ + static constexpr auto opcode_id = UPstream::opCodes::op_max; +}; + +//- Map sumOp\<T\> to \c UPstream::opCodes::op_sum +template<class T> +struct UPstream_opType<Foam::sumOp<T>> : std::true_type +{ + static constexpr auto opcode_id = UPstream::opCodes::op_sum; +}; + +//- Map plusOp\<T\> (same as sumOp\<T\>) to \c UPstream::opCodes::op_sum +template<class T> +struct UPstream_opType<Foam::plusOp<T>> : std::true_type +{ + static constexpr auto opcode_id = UPstream::opCodes::op_sum; +}; + +//- Map multiplyOp\<T\> to \c UPstream::opCodes::op_prod +template<class T> +struct UPstream_opType<Foam::multiplyOp<T>> : std::true_type +{ + static constexpr auto opcode_id = UPstream::opCodes::op_prod; +}; + +// NOTE (2025-02): +// currently no mappings provided for +// (op_bool_and, op_bool_or, op_bool_xor) until the calling semantics +// have been properly defined + + +// These are only viable for unsigned integral types, +// probably not for signed integral types. +// Be extra restrictive for now + +//- Map bitAndOp\<T\> to \c UPstream::opCodes::op_bit_and +//- for integrals (signed or unsigned), but also allow void as "generic" +template<class T> +struct UPstream_opType<Foam::bitAndOp<T>> +: + std::bool_constant<std::is_integral_v<T> || std::is_void_v<T>> +{ + static constexpr auto opcode_id = []() constexpr noexcept + { + if constexpr (std::is_integral_v<T> || std::is_void_v<T>) + return UPstream::opCodes::op_bit_and; + else + return UPstream::opCodes::invalid; + }(); +}; + +//- Map bitOrOp\<T\> to \c UPstream::opCodes::op_bit_or +//- for integrals (signed or unsigned), but also allow void as "generic" +template<class T> +struct UPstream_opType<Foam::bitOrOp<T>> +: + std::bool_constant<std::is_integral_v<T> || std::is_void_v<T>> +{ + static constexpr auto opcode_id = []() constexpr noexcept + { + if constexpr (std::is_integral_v<T> || std::is_void_v<T>) + return UPstream::opCodes::op_bit_or; + else + return UPstream::opCodes::invalid; + }(); +}; +//- Map bitXorOp\<T\> to \c UPstream::opCodes::op_bit_xor +//- for integrals (signed or unsigned), but also allow void as "generic" +template<class T> +struct UPstream_opType<Foam::bitXorOp<T>> +: + std::bool_constant<std::is_integral_v<T> || std::is_void_v<T>> +{ + static constexpr auto opcode_id = []() constexpr noexcept + { + if constexpr (std::is_integral_v<T> || std::is_void_v<T>) + return UPstream::opCodes::op_bit_xor; + else + return UPstream::opCodes::invalid; + }(); +}; + + +//- Combined query of opType and the underlying basic data type +// This handling may be simplified in the future... +template<class BinaryOp, class T> +struct UPstream_data_opType +: + std::bool_constant + < + UPstream_opType<BinaryOp>::value + && UPstream_basic_dataType<T>::value + > +{ + static constexpr auto opcode_id = []() constexpr noexcept + { + if constexpr + ( + UPstream_opType<BinaryOp>::value + && UPstream_basic_dataType<T>::value + ) + return UPstream_opType<BinaryOp>::opcode_id; + else + return UPstream::opCodes::invalid; + }(); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Convenience Functions (FUTURE?) + +// inline bool is_UPstream_mpi_dataTypeCode(UPstream::dataTypes id) noexcept +// { +// return +// ( +// int(id) >= int(UPstream::opCodes::Basic_begin) +// && int(id) < int(UPstream::opCodes::Basic_end) +// ); +// } +// +// inline bool is_UPstream_reduceOpCode(UPstream::opCodes id) noexcept +// { +// return +// ( +// int(id) >= int(UPstream::opCodes::Basic_begin) +// && int(id) < int(UPstream::opCodes::Basic_end) +// ); +// } + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UPstreamWindow.H b/src/OpenFOAM/db/IOstreams/Pstreams/UPstreamWindow.H index aa3ef233f87ccf952718979c0889681d1191cd2a..54ce90aecc94b7c9c4b076f7c5bcb40dcb2499ef 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/UPstreamWindow.H +++ b/src/OpenFOAM/db/IOstreams/Pstreams/UPstreamWindow.H @@ -137,6 +137,11 @@ public: //- Reset to default constructed value (MPI_WIN_NULL) void reset() noexcept; + + //- The number of ranks associated with the window group. + // The same as querying the original communicator, assuming the + // communicator is available within the current code scope. + int size() const; }; diff --git a/src/OpenFOAM/db/error/IOerror.C b/src/OpenFOAM/db/error/IOerror.C index 23029959ffcb24ae3c37985a59eb61e891b04190..b245976499b2b8a3f473d14a884beebaab4129aa 100644 --- a/src/OpenFOAM/db/error/IOerror.C +++ b/src/OpenFOAM/db/error/IOerror.C @@ -69,7 +69,7 @@ Foam::OSstream& Foam::IOerror::operator() const char* functionName, const char* sourceFileName, const int sourceFileLineNumber, - const string& ioFileName, + string ioFileName, const label ioStartLineNumber, const label ioEndLineNumber ) @@ -81,7 +81,7 @@ Foam::OSstream& Foam::IOerror::operator() sourceFileLineNumber ); - ioFileName_ = ioFileName; + ioFileName_ = std::move(ioFileName); ioStartLineNumber_ = ioStartLineNumber; ioEndLineNumber_ = ioEndLineNumber; @@ -296,7 +296,7 @@ void Foam::IOerror::write(Ostream& os, const bool withTitle) const } - const label lineNo = sourceFileLineNumber(); + const auto lineNo = sourceFileLineNumber(); if (messageStream::level >= 2 && lineNo && !functionName().empty()) { diff --git a/src/OpenFOAM/db/error/error.C b/src/OpenFOAM/db/error/error.C index 22b81ca642fae6e7b1c33acc5d2b15227f935a34..f127e5f8aa3e057b6a2710176c69c88591e8abaf 100644 --- a/src/OpenFOAM/db/error/error.C +++ b/src/OpenFOAM/db/error/error.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2014 OpenFOAM Foundation - Copyright (C) 2015-2023 OpenCFD Ltd. + Copyright (C) 2015-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -57,7 +57,7 @@ Foam::error::handlerNames // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // -bool Foam::error::master(const label communicator) +bool Foam::error::master(const int communicator) { // Trap negative value for comm as 'default'. This avoids direct use // of UPstream::worldComm which may have not yet been initialised @@ -177,12 +177,20 @@ Foam::error::~error() noexcept Foam::OSstream& Foam::error::operator() ( - const string& functionName + string functionName, + const char* sourceFileName, + const int sourceFileLineNumber ) { - functionName_ = functionName; + functionName_ = std::move(functionName); sourceFileName_.clear(); - sourceFileLineNumber_ = -1; + + if (sourceFileName) // nullptr check + { + sourceFileName_.assign(sourceFileName); + } + + sourceFileLineNumber_ = sourceFileLineNumber; return this->stream(); } @@ -198,14 +206,12 @@ Foam::OSstream& Foam::error::operator() functionName_.clear(); sourceFileName_.clear(); - if (functionName) + if (functionName) // nullptr check { - // With nullptr protection functionName_.assign(functionName); } - if (sourceFileName) + if (sourceFileName) // nullptr check { - // With nullptr protection sourceFileName_.assign(sourceFileName); } sourceFileLineNumber_ = sourceFileLineNumber; @@ -214,22 +220,6 @@ Foam::OSstream& Foam::error::operator() } -Foam::OSstream& Foam::error::operator() -( - const string& functionName, - const char* sourceFileName, - const int sourceFileLineNumber -) -{ - return operator() - ( - functionName.c_str(), - sourceFileName, - sourceFileLineNumber - ); -} - - Foam::error::operator Foam::dictionary() const { dictionary errDict; @@ -401,7 +391,7 @@ void Foam::error::write(Ostream& os, const bool withTitle) const os << message().c_str(); - const label lineNo = sourceFileLineNumber(); + const auto lineNo = sourceFileLineNumber(); if (messageStream::level >= 2 && lineNo && !functionName().empty()) { diff --git a/src/OpenFOAM/db/error/error.H b/src/OpenFOAM/db/error/error.H index 22832dd8e4af951d156b0a293203f842515c509a..59d7128fd931e304fbf68dd7db63730a2af869fb 100644 --- a/src/OpenFOAM/db/error/error.H +++ b/src/OpenFOAM/db/error/error.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation - Copyright (C) 2015-2024 OpenCFD Ltd. + Copyright (C) 2015-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -89,7 +89,7 @@ protected: string functionName_; string sourceFileName_; - label sourceFileLineNumber_; + int sourceFileLineNumber_; bool throwing_; std::unique_ptr<OStringStream> messageStreamPtr_; @@ -143,7 +143,7 @@ public: // // \param communicator is the numbered MPI communicator. // By default it uses UPstream::worldComm - static bool master(const label communicator = -1); + static bool master(const int communicator = -1); //- Test if an age warning should be emitted. // \param version is the old version (YYMM) for determining the @@ -180,7 +180,7 @@ public: } //- The currently defined source-file line number for output messages - label sourceFileLineNumber() const noexcept + int sourceFileLineNumber() const noexcept { return sourceFileLineNumber_; } @@ -218,29 +218,24 @@ public: return this->stream(); } - //- Define basic print message + //- Define basic print message with originating function name, + //- optionally with 'source file, line number' // \return OSstream for further operations OSstream& operator() ( - const string& functionName + string functionName, + const char* sourceFileName = nullptr, + const int sourceFileLineNumber = -1 ); - //- Define basic print message + //- Define basic print message with originating function name, + //- optionally with 'source file, line number' // \return OSstream for further operations OSstream& operator() ( const char* functionName, - const char* sourceFileName, - const int sourceFileLineNumber = 0 - ); - - //- Define basic print message - // \return OSstream for further operations - OSstream& operator() - ( - const string& functionName, - const char* sourceFileName, - const int sourceFileLineNumber = 0 + const char* sourceFileName = nullptr, + const int sourceFileLineNumber = -1 ); @@ -361,7 +356,7 @@ public: const char* functionName, const char* sourceFileName, const int sourceFileLineNumber, - const string& ioFileName, + string ioFileName, const label ioStartLineNumber = -1, const label ioEndLineNumber = -1 ); diff --git a/src/OpenFOAM/db/error/messageStream.C b/src/OpenFOAM/db/error/messageStream.C index 04a3e907bdcda13cae30b1265ad1c14509387df1..62e26d30d21734b4a00d947521293ba0124d069e 100644 --- a/src/OpenFOAM/db/error/messageStream.C +++ b/src/OpenFOAM/db/error/messageStream.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2017-2024 OpenCFD Ltd. + Copyright (C) 2017-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -49,21 +49,15 @@ int Foam::infoDetailLevel(1); Foam::messageStream::messageStream ( - const char* title, errorSeverity severity, int maxErrors, bool use_stderr ) : - title_(), severity_(severity), maxErrors_(maxErrors), errorCount_(0) { - if (title) - { - title_ = title; - } if (use_stderr) { severity_ |= errorSeverity::USE_STDERR; @@ -71,12 +65,40 @@ Foam::messageStream::messageStream } +Foam::messageStream::messageStream +( + const char* title, + errorSeverity severity, + int maxErrors, + bool use_stderr +) +: + messageStream(severity, maxErrors, use_stderr) +{ + if (title) + { + title_ = title; + } +} + + +Foam::messageStream::messageStream +( + string title, + errorSeverity severity, + int maxErrors, + bool use_stderr +) +: + messageStream(severity, maxErrors, use_stderr) +{ + title_ = std::move(title); +} + + Foam::messageStream::messageStream(const dictionary& dict) : - title_(dict.get<string>("title")), - severity_(errorSeverity::FATAL), - maxErrors_(0), - errorCount_(0) + messageStream(dict.get<string>("title"), errorSeverity::FATAL) {} @@ -153,7 +175,7 @@ Foam::OSstream& Foam::messageStream::stream } -Foam::OSstream& Foam::messageStream::masterStream(const label communicator) +Foam::OSstream& Foam::messageStream::masterStream(const int communicator) { if (UPstream::warnComm >= 0 && communicator != UPstream::warnComm) { @@ -178,23 +200,6 @@ std::ostream& Foam::messageStream::stdStream() // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // -Foam::OSstream& Foam::messageStream::operator() -( - const std::string& functionName -) -{ - OSstream& os = this->stream(); - - if (!functionName.empty()) - { - os << nl - << " From " << functionName.c_str() << nl; - } - - return os; -} - - Foam::OSstream& Foam::messageStream::deprecated ( const int afterVersion, @@ -239,10 +244,15 @@ Foam::OSstream& Foam::messageStream::deprecated { os << " From " << functionName << nl; } - if (sourceFileName) + if (sourceFileName) // nullptr check { - os << " in file " << sourceFileName - << " at line " << sourceFileLineNumber << nl; + os << " in file " << sourceFileName; + + if (sourceFileLineNumber >= 0) + { + os << " at line " << sourceFileLineNumber; + } + os << nl; } } os << " "; @@ -253,18 +263,29 @@ Foam::OSstream& Foam::messageStream::deprecated Foam::OSstream& Foam::messageStream::operator() ( - const char* functionName, + const std::string& functionName, const char* sourceFileName, const int sourceFileLineNumber ) { OSstream& os = this->stream(); - os << nl - << " From " << functionName << nl - << " in file " << sourceFileName - << " at line " << sourceFileLineNumber << nl - << " "; + if (!functionName.empty()) + { + os << nl + << " From " << functionName.c_str() << nl; + } + + if (sourceFileName) // nullptr check + { + os << " in file " << sourceFileName; + + if (sourceFileLineNumber >= 0) + { + os << " at line " << sourceFileLineNumber; + } + os << nl << " "; + } return os; } @@ -272,17 +293,31 @@ Foam::OSstream& Foam::messageStream::operator() Foam::OSstream& Foam::messageStream::operator() ( - const std::string& functionName, + const char* functionName, const char* sourceFileName, const int sourceFileLineNumber ) { - return operator() - ( - functionName.c_str(), - sourceFileName, - sourceFileLineNumber - ); + OSstream& os = this->stream(); + + if (functionName) // nullptr check + { + os << nl + << " From " << functionName << nl; + } + + if (sourceFileName) // nullptr check + { + os << " in file " << sourceFileName; + + if (sourceFileLineNumber >= 0) + { + os << " at line " << sourceFileLineNumber; + } + os << nl << " "; + } + + return os; } diff --git a/src/OpenFOAM/db/error/messageStream.H b/src/OpenFOAM/db/error/messageStream.H index e22d8d0abec143ec168947b85f822bee5f35fa90..6fe86394e9465e3f5cf8e9cd53cc2b9e8f25cfed 100644 --- a/src/OpenFOAM/db/error/messageStream.H +++ b/src/OpenFOAM/db/error/messageStream.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016-2024 OpenCFD Ltd. + Copyright (C) 2016-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -130,6 +130,14 @@ public: // Constructors + //- Construct untitled with given characteristics + explicit messageStream + ( + errorSeverity severity, + int maxErrors = 0, + bool use_stderr = false + ); + //- Construct from components messageStream ( @@ -142,14 +150,11 @@ public: //- Construct from components messageStream ( - const std::string& title, + string title, errorSeverity severity, int maxErrors = 0, bool use_stderr = false - ) - : - messageStream(title.c_str(), severity, maxErrors, use_stderr) - {} + ); //- Construct from dictionary as Fatal, extracting 'title'. @@ -191,7 +196,7 @@ public: //- Return OSstream for output operations on the master process only, //- Snull on other processes. - OSstream& masterStream(const label communicator); + OSstream& masterStream(const int communicator); //- Return std::ostream for output operations. std::ostream& stdStream(); @@ -220,28 +225,23 @@ public: return this->stream(); } - //- Report 'From function-name' - // \return OSstream for further operations - OSstream& operator() - ( - const std::string& functionName - ); - - //- Report 'From function-name, source file, line number' + //- Report 'From function-name', + //- optionally with 'source file, line number' // \return OSstream for further operations OSstream& operator() ( - const char* functionName, - const char* sourceFileName, + const std::string& functionName, + const char* sourceFileName = nullptr, const int sourceFileLineNumber = 0 ); - //- Report 'From function-name, source file, line number' + //- Report 'From function-name', + //- optionally with 'source file, line number' // \return OSstream for further operations OSstream& operator() ( - const std::string& functionName, - const char* sourceFileName, + const char* functionName, + const char* sourceFileName = nullptr, const int sourceFileLineNumber = 0 ); diff --git a/src/OpenFOAM/fields/Fields/Field/FieldFunctions.C b/src/OpenFOAM/fields/Fields/Field/FieldFunctions.C index 583c4439710246ebc4abfc18b44a55a9cd8d08fc..b9053f08627c9d11c5109898c06c47029218b4b0 100644 --- a/src/OpenFOAM/fields/Fields/Field/FieldFunctions.C +++ b/src/OpenFOAM/fields/Fields/Field/FieldFunctions.C @@ -652,7 +652,7 @@ Type gAverage { label n = f1.size(); Type s = sum(f1); - sumReduce(s, n, UPstream::msgType(), comm); + Foam::sumReduce(s, n, UPstream::msgType(), comm); if (n > 0) { diff --git a/src/OpenFOAM/global/profiling/profilingPstream.C b/src/OpenFOAM/global/profiling/profilingPstream.C index e7ad9050e0c2bb524383aae8022761532d6d4571..9189cd86ff490d825e31aa5e129c20c30f53cc8a 100644 --- a/src/OpenFOAM/global/profiling/profilingPstream.C +++ b/src/OpenFOAM/global/profiling/profilingPstream.C @@ -228,9 +228,9 @@ void Foam::profilingPstream::report(const int reportLevel) UPstream::mpiGather ( - procValues.cdata_bytes(), // Send - allTimes.data_bytes(), // Recv - procValues.size_bytes(), // Num send/recv data per rank + procValues.cdata(), // Send + allTimes.data(), // Recv + procValues.size(), // Num send/recv data per rank UPstream::commWorld() ); } @@ -247,9 +247,9 @@ void Foam::profilingPstream::report(const int reportLevel) UPstream::mpiGather ( - procValues.cdata_bytes(), // Send - allCounts.data_bytes(), // Recv - procValues.size_bytes(), // Num send/recv data per rank + procValues.cdata(), // Send + allCounts.data(), // Recv + procValues.size(), // Num send/recv data per rank UPstream::commWorld() ); } diff --git a/src/OpenFOAM/meshes/lduMesh/lduMesh.H b/src/OpenFOAM/meshes/lduMesh/lduMesh.H index 493bbcaabc20b57af0da9d3a1c52660e89f68345..9c7e3045795e5712a70e8eef130214fbf61e314b 100644 --- a/src/OpenFOAM/meshes/lduMesh/lduMesh.H +++ b/src/OpenFOAM/meshes/lduMesh/lduMesh.H @@ -91,11 +91,10 @@ public: //- Helper: reduce with current communicator template<class T, class BinaryOp> - void reduce - ( - T& Value, - const BinaryOp& bop - ) const; + void reduce(T& val, BinaryOp bop) const + { + Foam::reduce(val, bop, UPstream::msgType(), comm()); + } // Info @@ -117,10 +116,6 @@ public: // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -#ifdef NoRepository - #include "lduMeshTemplates.C" -#endif - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // #endif diff --git a/src/OpenFOAM/meshes/lduMesh/lduMeshTemplates.C b/src/OpenFOAM/meshes/lduMesh/lduMeshTemplates.C index b44e74541732a177e0e8f72913104e7a93281deb..7cec1b4541d1553571d30afa2aac3b841f6c3d51 100644 --- a/src/OpenFOAM/meshes/lduMesh/lduMeshTemplates.C +++ b/src/OpenFOAM/meshes/lduMesh/lduMeshTemplates.C @@ -1,43 +1 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | www.openfoam.com - \\/ M anipulation | -------------------------------------------------------------------------------- - Copyright (C) 2013 OpenFOAM Foundation -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenFOAM is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - - You should have received a copy of the GNU General Public License - along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. - -\*---------------------------------------------------------------------------*/ - -#include "lduMesh.H" - -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -template<class T, class BinaryOp> -void Foam::lduMesh::reduce -( - T& Value, - const BinaryOp& bop -) const -{ - Foam::reduce(Value, bop, Pstream::msgType(), comm()); -} - - -// ************************************************************************* // +#warning File removed - left for old dependency check only diff --git a/src/OpenFOAM/parallel/globalIndex/globalIndex.C b/src/OpenFOAM/parallel/globalIndex/globalIndex.C index 95f64b161c6ca1f94a990b133e31d6909f1dffce..12113485a4feaedd1df3f941a347b7d961ac24e3 100644 --- a/src/OpenFOAM/parallel/globalIndex/globalIndex.C +++ b/src/OpenFOAM/parallel/globalIndex/globalIndex.C @@ -319,12 +319,7 @@ bool Foam::globalIndex::splitNodeOffsets allOffsets.resize_nocopy(numProc+1); } - UPstream::broadcast - ( - allOffsets.data_bytes(), - allOffsets.size_bytes(), - interNodeComm - ); + UPstream::broadcast(allOffsets.data(), allOffsets.size(), interNodeComm); if (FOAM_UNLIKELY(allOffsets.empty())) diff --git a/src/OpenFOAM/primitives/Scalar/scalarImpl.H b/src/OpenFOAM/primitives/Scalar/scalarImpl.H index 2517aa0aef379406f24ed7e02524aa93bc0511ca..0d1564dde5600894b06ac07b521ba82bd5ffc1f9 100644 --- a/src/OpenFOAM/primitives/Scalar/scalarImpl.H +++ b/src/OpenFOAM/primitives/Scalar/scalarImpl.H @@ -116,10 +116,7 @@ public: // Constructors //- Copy construct from primitive - explicit pTraits(Scalar val) noexcept - : - p_(val) - {} + explicit pTraits(Scalar val) noexcept : p_(val) {} //- Read construct from Istream explicit pTraits(Istream& is); @@ -128,16 +125,10 @@ public: // Member Functions //- Return the value - operator Scalar() const noexcept - { - return p_; - } + operator Scalar() const noexcept { return p_; } //- Access the value - operator Scalar&() noexcept - { - return p_; - } + operator Scalar&() noexcept { return p_; } }; diff --git a/src/OpenFOAM/primitives/VectorSpace/VectorSpace.H b/src/OpenFOAM/primitives/VectorSpace/VectorSpace.H index 048f49bb407a64899cbc3622f9e1b63cfb59430a..c3f7163c4b73b39447d26e75fe6da14fa8f1c16d 100644 --- a/src/OpenFOAM/primitives/VectorSpace/VectorSpace.H +++ b/src/OpenFOAM/primitives/VectorSpace/VectorSpace.H @@ -158,7 +158,7 @@ public: // Constructors //- Construct initialized to zero - inline VectorSpace(const Foam::zero); + inline VectorSpace(Foam::zero); //- Copy construct inline VectorSpace(const VectorSpace<Form, Cmpt, Ncmpts>& vs); @@ -174,10 +174,7 @@ public: // Member Functions //- The number of elements in the VectorSpace = Ncmpts. - static constexpr direction size() noexcept - { - return Ncmpts; - } + static constexpr direction size() noexcept { return Ncmpts; } inline const Cmpt& component(const direction) const; inline Cmpt& component(const direction); @@ -186,10 +183,10 @@ public: inline void replace(const direction, const Cmpt&); //- Return const pointer to the first data element - inline const Cmpt* cdata() const noexcept; + const Cmpt* cdata() const noexcept { return v_; } //- Return pointer to the first data element - inline Cmpt* data() noexcept; + Cmpt* data() noexcept { return v_; } //- Assign all components to given value inline void fill(const Cmpt& s); @@ -210,7 +207,7 @@ public: inline void operator+=(const VectorSpace<Form, Cmpt, Ncmpts>&); inline void operator-=(const VectorSpace<Form, Cmpt, Ncmpts>&); - inline void operator=(const Foam::zero); + inline void operator=(Foam::zero); inline void operator*=(const scalar); inline void operator/=(const scalar); @@ -224,28 +221,25 @@ public: typedef const Cmpt* const_iterator; - // Random access iterator (non-const) - - //- Return an iterator to begin of VectorSpace - inline iterator begin() noexcept; - - //- Return an iterator to end of VectorSpace - inline iterator end() noexcept; + // Random access iterators (const and non-const) + //- Return an iterator (pointer) to begin of VectorSpace + iterator begin() noexcept { return v_; } - // Random access iterator (const) + //- Return const_iterator (const pointer) to begin of VectorSpace + const_iterator begin() const noexcept { return v_; } - //- Return const_iterator to begin of VectorSpace - inline const_iterator cbegin() const noexcept; + //- Return const_iterator (const pointer) to begin of VectorSpace + const_iterator cbegin() const noexcept { return v_; } - //- Return const_iterator to end of VectorSpace - inline const_iterator cend() const noexcept; + //- Return an iterator (pointer) to end of VectorSpace + iterator end() noexcept { return (v_ + Ncmpts); } - //- Return const_iterator to begin of VectorSpace - inline const_iterator begin() const noexcept; + //- Return const_iterator (const pointer) to end of VectorSpace + const_iterator end() const noexcept { return (v_ + Ncmpts); } - //- Return const_iterator to end of VectorSpace - inline const_iterator end() const noexcept; + //- Return const_iterator (const pointer) to end of VectorSpace + const_iterator cend() const noexcept { return (v_ + Ncmpts); } // IOstream Operators diff --git a/src/OpenFOAM/primitives/VectorSpace/VectorSpaceI.H b/src/OpenFOAM/primitives/VectorSpace/VectorSpaceI.H index 7f8bbd46dc17820ac248c2378485ab55f8d03503..772baa7d4fc2a04c4f161540e4608b0477bf8547 100644 --- a/src/OpenFOAM/primitives/VectorSpace/VectorSpaceI.H +++ b/src/OpenFOAM/primitives/VectorSpace/VectorSpaceI.H @@ -35,9 +35,9 @@ License // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // template<class Form, class Cmpt, Foam::direction Ncmpts> -inline Foam::VectorSpace<Form, Cmpt, Ncmpts>::VectorSpace(const Foam::zero) +inline Foam::VectorSpace<Form, Cmpt, Ncmpts>::VectorSpace(Foam::zero) { - VectorSpaceOps<Ncmpts,0>::eqOpS(*this, Zero, eqOp<Cmpt>()); + VectorSpaceOps<Ncmpts>::fill_n(this->begin(), Cmpt(Foam::zero{})); } @@ -47,7 +47,7 @@ inline Foam::VectorSpace<Form, Cmpt, Ncmpts>::VectorSpace const VectorSpace<Form, Cmpt, Ncmpts>& vs ) { - VectorSpaceOps<Ncmpts,0>::eqOp(*this, vs, eqOp<Cmpt>()); + VectorSpaceOps<Ncmpts>::copy_n(vs.cbegin(), this->begin()); } @@ -58,7 +58,7 @@ inline Foam::VectorSpace<Form, Cmpt, Ncmpts>::VectorSpace const VectorSpace<Form2, Cmpt2, Ncmpts>& vs ) { - VectorSpaceOps<Ncmpts,0>::eqOp(*this, vs, eqOp<Cmpt>()); + VectorSpaceOps<Ncmpts>::copy_n(vs.cbegin(), this->begin()); } @@ -163,7 +163,7 @@ inline void Foam::VectorSpace<Form, Cmpt, Ncmpts>::replace template<class Form, class Cmpt, Foam::direction Ncmpts> inline void Foam::VectorSpace<Form, Cmpt, Ncmpts>::fill(const Cmpt& s) { - VectorSpaceOps<Ncmpts,0>::eqOpS(*this, s, eqOp<Cmpt>()); + VectorSpaceOps<Ncmpts>::fill_n(this->begin(), s); } @@ -171,7 +171,7 @@ template<class Form, class Cmpt, Foam::direction Ncmpts> inline Form Foam::VectorSpace<Form, Cmpt, Ncmpts>::uniform(const Cmpt& s) { Form v; - VectorSpaceOps<Ncmpts,0>::eqOpS(v, s, eqOp<Cmpt>()); + v.fill(s); return v; } @@ -186,68 +186,6 @@ Foam::VectorSpace<Form, Cmpt, Ncmpts>::block() const } -// * * * * * * * * * * * * * * * * Iterator * * * * * * * * * * * * * * * * // - -template<class Form, class Cmpt, Foam::direction Ncmpts> -inline Cmpt* Foam::VectorSpace<Form, Cmpt, Ncmpts>::data() noexcept -{ - return v_; -} - - -template<class Form, class Cmpt, Foam::direction Ncmpts> -inline const Cmpt* Foam::VectorSpace<Form, Cmpt, Ncmpts>::cdata() const noexcept -{ - return v_; -} - - -template<class Form, class Cmpt, Foam::direction Ncmpts> -inline Cmpt* Foam::VectorSpace<Form, Cmpt, Ncmpts>::begin() noexcept -{ - return v_; -} - - -template<class Form, class Cmpt, Foam::direction Ncmpts> -inline Cmpt* Foam::VectorSpace<Form, Cmpt, Ncmpts>::end() noexcept -{ - return (v_ + Ncmpts); -} - - -template<class Form, class Cmpt, Foam::direction Ncmpts> -inline const Cmpt* Foam::VectorSpace<Form, Cmpt, Ncmpts>::cbegin() -const noexcept -{ - return v_; -} - - -template<class Form, class Cmpt, Foam::direction Ncmpts> -inline const Cmpt* Foam::VectorSpace<Form, Cmpt, Ncmpts>::cend() -const noexcept -{ - return (v_ + Ncmpts); -} - - -template<class Form, class Cmpt, Foam::direction Ncmpts> -inline const Cmpt* Foam::VectorSpace<Form, Cmpt, Ncmpts>::begin() -const noexcept -{ - return v_; -} - - -template<class Form, class Cmpt, Foam::direction Ncmpts> -inline const Cmpt* Foam::VectorSpace<Form, Cmpt, Ncmpts>::end() -const noexcept -{ - return (v_ + Ncmpts); -} - - // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // template<class Form, class Cmpt, Foam::direction Ncmpts> @@ -346,7 +284,7 @@ inline void Foam::VectorSpace<Form, Cmpt, Ncmpts>::operator= const VectorSpace<Form, Cmpt, Ncmpts>& vs ) { - VectorSpaceOps<Ncmpts,0>::eqOp(*this, vs, eqOp<Cmpt>()); + VectorSpaceOps<Ncmpts>::copy_n(vs.cbegin(), this->begin()); } @@ -371,9 +309,9 @@ inline void Foam::VectorSpace<Form, Cmpt, Ncmpts>::operator-= template<class Form, class Cmpt, Foam::direction Ncmpts> -inline void Foam::VectorSpace<Form, Cmpt, Ncmpts>::operator=(const Foam::zero) +inline void Foam::VectorSpace<Form, Cmpt, Ncmpts>::operator=(Foam::zero) { - VectorSpaceOps<Ncmpts,0>::eqOpS(*this, 0, eqOp<Cmpt>()); + VectorSpaceOps<Ncmpts>::fill_n(this->begin(), Cmpt(Foam::zero{})); } diff --git a/src/OpenFOAM/primitives/VectorSpace/VectorSpaceOps.H b/src/OpenFOAM/primitives/VectorSpace/VectorSpaceOps.H index c608971b26577b6fd8fd69b5c9835ccea2577d5a..bc1e7366880a1fe0a6c25e3b802b0e703524ebc3 100644 --- a/src/OpenFOAM/primitives/VectorSpace/VectorSpaceOps.H +++ b/src/OpenFOAM/primitives/VectorSpace/VectorSpaceOps.H @@ -43,9 +43,40 @@ namespace Foam // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // //- Recursive execution. Terminating at \<N\>, starting at index \<I\> -template<direction N, direction I> +template<direction N, direction I=0> struct VectorSpaceOps { + //- Somewhat equivalent to std::copy_n() but with templated loops. + // \param [in] input indexable input data + // \param [out] result indexable output data + template<class Input, class Output> + static inline void copy_n(Input input, Output result) + { + // if constexpr (I < N) + { + result[I] = input[I]; + VectorSpaceOps<N, I+1>::copy_n(input, result); + } + } + + //- Somewhat equivalent to std::fill_n() but with templated loops + // \param [out] result indexable output data + // \param val the value to assign for each entry + template<class Output, class T> + static inline void fill_n(Output result, const T& val) + { + // if constexpr (I < N) + { + result[I] = val; + VectorSpaceOps<N, I+1>::fill_n(result, val); + } + } + + //- Apply the binary assignment operation to each vector-space + //- component. + // \param [in,out] vs vector-space (indexed) data + // \param s scalar/component data (non-indexed) + // \param eo binary combine/assign operation template<class V, class S, class EqOp> static inline void eqOpS(V& vs, const S& s, EqOp eo) { @@ -56,6 +87,10 @@ struct VectorSpaceOps } } + //- Apply the inplace binary reduction operation. + // \param [in,out] s scalar or component data (non-indexed) + // \param [in] vs input vector-space (indexed) data + // \param eo binary combine/assign operation template<class S, class V, class EqOp> static inline void SeqOp(S& s, const V& vs, EqOp eo) { @@ -66,6 +101,10 @@ struct VectorSpaceOps } } + //- Apply the inplace binary assignment operation to the components. + // \param [in,out] vs1 vector-space (indexed) data + // \param [in] vs2 second vector-space (indexed) data + // \param eo binary combine/assign operation template<class V1, class V2, class EqOp> static inline void eqOp(V1& vs1, const V2& vs2, EqOp eo) { @@ -76,34 +115,51 @@ struct VectorSpaceOps } } - - template<class V, class V1, class S, class Op> - static inline void opVS(V& vs, const V1& vs1, const S& s, Op o) + //- Apply the binary operation between vector-space and scalar data + //- and assign the result. + // \param [out] vs vector-space (indexed) data + // \param [in] vs1 vector-space (indexed) data operand + // \param [in] s scalar operand + // \param bop binary operation + template<class V, class V1, class S, class BinaryOp> + static inline void opVS(V& vs, const V1& vs1, const S& s, BinaryOp bop) { // if constexpr (I < N) { - vs.v_[I] = o(vs1.v_[I], s); - VectorSpaceOps<N, I+1>::opVS(vs, vs1, s, o); + vs.v_[I] = bop(vs1.v_[I], s); + VectorSpaceOps<N, I+1>::opVS(vs, vs1, s, bop); } } - template<class V, class S, class V1, class Op> - static inline void opSV(V& vs, const S& s, const V1& vs1, Op o) + //- Apply the binary operation between scalar and vector-space data + //- and assign the result. + // \param [out] vs vector-space (indexed) data + // \param [in] s scalar operand + // \param [in] vs1 vector-space (indexed) data operand + // \param bop binary operation + template<class V, class S, class V1, class BinaryOp> + static inline void opSV(V& vs, const S& s, const V1& vs1, BinaryOp bop) { // if constexpr (I < N) { - vs.v_[I] = o(s, vs1.v_[I]); - VectorSpaceOps<N, I+1>::opSV(vs, s, vs1, o); + vs.v_[I] = bop(s, vs1.v_[I]); + VectorSpaceOps<N, I+1>::opSV(vs, s, vs1, bop); } } - template<class V, class V1, class Op> - static inline void op(V& vs, const V1& vs1, const V1& vs2, Op o) + //- Apply the binary operation between two vector-space data + //- and assign the result. + // \param [out] vs vector-space (indexed) data + // \param [in] vs1 vector-space (indexed) data operand + // \param [in] vs2 vector-space (indexed) data operand + // \param bop binary operation + template<class V, class V1, class BinaryOp> + static inline void op(V& vs, const V1& vs1, const V1& vs2, BinaryOp bop) { // if constexpr (I < N) { - vs.v_[I] = o(vs1.v_[I], vs2.v_[I]); - VectorSpaceOps<N, I+1>::op(vs, vs1, vs2, o); + vs.v_[I] = bop(vs1.v_[I], vs2.v_[I]); + VectorSpaceOps<N, I+1>::op(vs, vs1, vs2, bop); } } }; @@ -115,6 +171,12 @@ struct VectorSpaceOps template<direction N> struct VectorSpaceOps<N, N> { + template<class Input, class Output> + static inline void copy_n(Input, Output) {} + + template<class Output, class T> + static inline void fill_n(Output, const T&) {} + template<class V, class S, class EqOp> static inline void eqOpS(V&, const S&, EqOp) {} @@ -124,14 +186,14 @@ struct VectorSpaceOps<N, N> template<class V1, class V2, class EqOp> static inline void eqOp(V1&, const V2&, EqOp) {} - template<class V, class V1, class S, class Op> - static inline void opVS(V& vs, const V1&, const S&, Op) {} + template<class V, class V1, class S, class BinaryOp> + static inline void opVS(V&, const V1&, const S&, BinaryOp) {} - template<class V, class S, class V1, class Op> - static inline void opSV(V& vs, const S&, const V1&, Op) {} + template<class V, class S, class V1, class BinaryOp> + static inline void opSV(V&, const S&, const V1&, BinaryOp) {} - template<class V, class V1, class Op> - static inline void op(V& vs, const V1&, const V1&, Op) {} + template<class V, class V1, class BinaryOp> + static inline void op(V&, const V1&, const V1&, BinaryOp) {} }; diff --git a/src/OpenFOAM/primitives/bools/bool/bool.H b/src/OpenFOAM/primitives/bools/bool/bool.H index 0e791d0404b2b5d7954b10926c44852789816857..090fae4137570279d43b6e90afe30e73ce5a03bf 100644 --- a/src/OpenFOAM/primitives/bools/bool/bool.H +++ b/src/OpenFOAM/primitives/bools/bool/bool.H @@ -102,10 +102,7 @@ public: // Constructors //- Copy construct from primitive - explicit pTraits(bool val) noexcept - : - p_(val) - {} + explicit pTraits(bool val) noexcept : p_(val) {} //- Read construct from Istream explicit pTraits(Istream& is); diff --git a/src/OpenFOAM/primitives/chars/char/char.H b/src/OpenFOAM/primitives/chars/char/char.H index 959e0f075c3747625bb9a6bdc963ec581785d7a9..25ecd83f388ae9011cd8cd7c49beed0f41406f04 100644 --- a/src/OpenFOAM/primitives/chars/char/char.H +++ b/src/OpenFOAM/primitives/chars/char/char.H @@ -94,10 +94,7 @@ public: // Constructors //- Copy construct from primitive - explicit pTraits(char val) noexcept - : - p_(val) - {} + explicit pTraits(char val) noexcept : p_(val) {} //- Read construct from Istream explicit pTraits(Istream& is); diff --git a/src/OpenFOAM/primitives/complex/complex.H b/src/OpenFOAM/primitives/complex/complex.H index 7749aae7adf027e7314cc7e24da0786ff192d70e..b04f76b4afbbac665197c05c949ace98e831333e 100644 --- a/src/OpenFOAM/primitives/complex/complex.H +++ b/src/OpenFOAM/primitives/complex/complex.H @@ -288,10 +288,7 @@ public: // Constructors //- Copy construct from primitive - explicit pTraits(const complex& val) noexcept - : - p_(val) - {} + explicit pTraits(const complex& val) noexcept : p_(val) {} //- Read construct from Istream diff --git a/src/OpenFOAM/primitives/ints/int16/int16.C b/src/OpenFOAM/primitives/ints/int16/int16.C index 27a16f57f64acf1e549d2f21dbf4d8cf1686d4b8..1fc4b094288a7d253831d75d70743f186dc32177 100644 --- a/src/OpenFOAM/primitives/ints/int16/int16.C +++ b/src/OpenFOAM/primitives/ints/int16/int16.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018 OpenCFD Ltd. + Copyright (C) 2018-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -29,6 +29,19 @@ License #include "int32.H" #include "IOstreams.H" +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const char* const Foam::pTraits<int16_t>::typeName = "int16"; +const char* const Foam::pTraits<int16_t>::componentNames[] = { "" }; + +const int16_t Foam::pTraits<int16_t>::zero = 0; +const int16_t Foam::pTraits<int16_t>::one = 1; +const int16_t Foam::pTraits<int16_t>::min = INT16_MIN; +const int16_t Foam::pTraits<int16_t>::max = INT16_MAX; +const int16_t Foam::pTraits<int16_t>::rootMin = INT16_MIN; +const int16_t Foam::pTraits<int16_t>::rootMax = INT16_MAX; + + // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // Foam::Istream& Foam::operator>>(Istream& is, int16_t& val) diff --git a/src/OpenFOAM/primitives/ints/int16/int16.H b/src/OpenFOAM/primitives/ints/int16/int16.H index 21587e88e6b2d6799fd389b270ca7c65c73e32a2..44f6fc96c5acc9ffb9d35959151929625d78f9c1 100644 --- a/src/OpenFOAM/primitives/ints/int16/int16.H +++ b/src/OpenFOAM/primitives/ints/int16/int16.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018 OpenCFD Ltd. + Copyright (C) 2018-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -73,6 +73,67 @@ Istream& operator>>(Istream& is, int16_t& val); Ostream& operator<<(Ostream& os, const int16_t val); +/*---------------------------------------------------------------------------*\ + Specialization pTraits<int16_t> +\*---------------------------------------------------------------------------*/ + +//- Template specialization for pTraits<int16_t> +template<> +class pTraits<int16_t> +{ + int16_t p_; + +public: + + // Typedefs + + //- Component type + typedef int16_t cmptType; + + + // Member Constants + + //- Dimensionality of space + static constexpr direction dim = 3; + + //- Rank of int16_t is 0 + static constexpr direction rank = 0; + + //- Number of components in int16_t is 1 + static constexpr direction nComponents = 1; + + + // Static Data Members + + static const char* const typeName; + static const char* const componentNames[]; + static const int16_t zero; + static const int16_t one; + static const int16_t min; + static const int16_t max; + static const int16_t rootMax; + static const int16_t rootMin; + + + // Constructors + + //- Copy construct from primitive + explicit pTraits(int16_t val) noexcept : p_(val) {} + + //- Read construct from Istream + explicit pTraits(Istream& is); + + + // Member Functions + + //- Return the value + operator int16_t() const noexcept { return p_; } + + //- Access the value + operator int16_t&() noexcept { return p_; } +}; + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace Foam diff --git a/src/OpenFOAM/primitives/ints/int32/int32.C b/src/OpenFOAM/primitives/ints/int32/int32.C index c1606ab63eb28073fbe878456a518137b478add5..ccfe8eebbc1feece70cfc36a198df61ddaa90ae2 100644 --- a/src/OpenFOAM/primitives/ints/int32/int32.C +++ b/src/OpenFOAM/primitives/ints/int32/int32.C @@ -36,8 +36,8 @@ const int32_t Foam::pTraits<int32_t>::zero = 0; const int32_t Foam::pTraits<int32_t>::one = 1; const int32_t Foam::pTraits<int32_t>::min = INT32_MIN; const int32_t Foam::pTraits<int32_t>::max = INT32_MAX; -const int32_t Foam::pTraits<int32_t>::rootMin = pTraits<int32_t>::min; -const int32_t Foam::pTraits<int32_t>::rootMax = pTraits<int32_t>::max; +const int32_t Foam::pTraits<int32_t>::rootMin = INT32_MIN; +const int32_t Foam::pTraits<int32_t>::rootMax = INT32_MAX; // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/primitives/ints/int32/int32.H b/src/OpenFOAM/primitives/ints/int32/int32.H index bd97eae76b247e21ed07b973d1575c0f2e247eb5..39d75b155bc50f9fba48f29ae3a7b07569334d4d 100644 --- a/src/OpenFOAM/primitives/ints/int32/int32.H +++ b/src/OpenFOAM/primitives/ints/int32/int32.H @@ -181,10 +181,7 @@ public: // Constructors //- Copy construct from primitive - explicit pTraits(int32_t val) noexcept - : - p_(val) - {} + explicit pTraits(int32_t val) noexcept : p_(val) {} //- Read construct from Istream explicit pTraits(Istream& is); diff --git a/src/OpenFOAM/primitives/ints/int64/int64.C b/src/OpenFOAM/primitives/ints/int64/int64.C index 30ad0534e2a050276f1cd3da65be25621b654fbe..051a8a7e5f8bcdb59372e85169b929b8b242382e 100644 --- a/src/OpenFOAM/primitives/ints/int64/int64.C +++ b/src/OpenFOAM/primitives/ints/int64/int64.C @@ -36,8 +36,8 @@ const int64_t Foam::pTraits<int64_t>::zero = 0; const int64_t Foam::pTraits<int64_t>::one = 1; const int64_t Foam::pTraits<int64_t>::min = INT64_MIN; const int64_t Foam::pTraits<int64_t>::max = INT64_MAX; -const int64_t Foam::pTraits<int64_t>::rootMin = pTraits<int64_t>::min; -const int64_t Foam::pTraits<int64_t>::rootMax = pTraits<int64_t>::max; +const int64_t Foam::pTraits<int64_t>::rootMin = INT64_MIN; +const int64_t Foam::pTraits<int64_t>::rootMax = INT64_MAX; // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/primitives/ints/int64/int64.H b/src/OpenFOAM/primitives/ints/int64/int64.H index 49766d262127b262320a94cae97ea7b5ec5940ae..e88716e14aa6f0eb18ce6666d2ccf91c0f7ef3dc 100644 --- a/src/OpenFOAM/primitives/ints/int64/int64.H +++ b/src/OpenFOAM/primitives/ints/int64/int64.H @@ -180,10 +180,7 @@ public: // Constructors //- Copy construct from primitive - explicit pTraits(int64_t val) noexcept - : - p_(val) - {} + explicit pTraits(int64_t val) noexcept : p_(val) {} //- Read construct from Istream explicit pTraits(Istream& is); diff --git a/src/OpenFOAM/primitives/ints/int8/int8.H b/src/OpenFOAM/primitives/ints/int8/int8.H index 734b5323a957cc1975980d0736f273193cf0e970..91ca4a678c6d3fbc2731d5a75df278ed38b7c691 100644 --- a/src/OpenFOAM/primitives/ints/int8/int8.H +++ b/src/OpenFOAM/primitives/ints/int8/int8.H @@ -124,10 +124,7 @@ public: // Constructors //- Copy construct from primitive - explicit pTraits(int8_t val) noexcept - : - p_(val) - {} + explicit pTraits(int8_t val) noexcept : p_(val) {} //- Read construct from Istream explicit pTraits(Istream& is); diff --git a/src/OpenFOAM/primitives/ints/uint16/uint16.C b/src/OpenFOAM/primitives/ints/uint16/uint16.C index 1b4516ae4952f11df523bdde06cfe3dacccc46f1..91d1acbc392692375b6fc8f24b6cc99f59215066 100644 --- a/src/OpenFOAM/primitives/ints/uint16/uint16.C +++ b/src/OpenFOAM/primitives/ints/uint16/uint16.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018 OpenCFD Ltd. + Copyright (C) 2018-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -29,6 +29,19 @@ License #include "int32.H" #include "IOstreams.H" +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const char* const Foam::pTraits<uint16_t>::typeName = "uint16"; +const char* const Foam::pTraits<uint16_t>::componentNames[] = { "" }; + +const uint16_t Foam::pTraits<uint16_t>::zero = 0; +const uint16_t Foam::pTraits<uint16_t>::one = 1; +const uint16_t Foam::pTraits<uint16_t>::min = 0; +const uint16_t Foam::pTraits<uint16_t>::max = UINT16_MAX; +const uint16_t Foam::pTraits<uint16_t>::rootMin = 0; +const uint16_t Foam::pTraits<uint16_t>::rootMax = UINT16_MAX; + + // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // Foam::Istream& Foam::operator>>(Istream& is, uint16_t& val) diff --git a/src/OpenFOAM/primitives/ints/uint16/uint16.H b/src/OpenFOAM/primitives/ints/uint16/uint16.H index 14b9b249fd13139ae794482709975d4b67d45456..4ab782dd6c208a2e5f546070303b44bd56f21343 100644 --- a/src/OpenFOAM/primitives/ints/uint16/uint16.H +++ b/src/OpenFOAM/primitives/ints/uint16/uint16.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018 OpenCFD Ltd. + Copyright (C) 2018-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -74,6 +74,67 @@ Istream& operator>>(Istream& is, uint16_t& val); Ostream& operator<<(Ostream& os, const uint16_t val); +/*---------------------------------------------------------------------------*\ + Specialization pTraits<uint16_t> +\*---------------------------------------------------------------------------*/ + +//- Template specialization for pTraits<uint16_t> +template<> +class pTraits<uint16_t> +{ + uint16_t p_; + +public: + + // Typedefs + + //- Component type + typedef uint16_t cmptType; + + + // Member Constants + + //- Dimensionality of space + static constexpr direction dim = 3; + + //- Rank of uint16_t is 0 + static constexpr direction rank = 0; + + //- Number of components in uint16_t is 1 + static constexpr direction nComponents = 1; + + + // Static Data Members + + static const char* const typeName; + static const char* const componentNames[]; + static const uint16_t zero; + static const uint16_t one; + static const uint16_t min; + static const uint16_t max; + static const uint16_t rootMax; + static const uint16_t rootMin; + + + // Constructors + + //- Copy construct from primitive + explicit pTraits(uint16_t val) noexcept : p_(val) {} + + //- Read construct from Istream + explicit pTraits(Istream& is); + + + // Member Functions + + //- Return the value + operator uint16_t() const noexcept { return p_; } + + //- Access the value + operator uint16_t&() noexcept { return p_; } +}; + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace Foam diff --git a/src/OpenFOAM/primitives/ints/uint32/uint32.C b/src/OpenFOAM/primitives/ints/uint32/uint32.C index aa728626e01784ea35cfb028fba4e259d8baf4a2..9c179acadbda2939580c781c314772dfbec6e19f 100644 --- a/src/OpenFOAM/primitives/ints/uint32/uint32.C +++ b/src/OpenFOAM/primitives/ints/uint32/uint32.C @@ -37,7 +37,7 @@ const uint32_t Foam::pTraits<uint32_t>::one = 1; const uint32_t Foam::pTraits<uint32_t>::min = 0; const uint32_t Foam::pTraits<uint32_t>::max = UINT32_MAX; const uint32_t Foam::pTraits<uint32_t>::rootMin = 0; -const uint32_t Foam::pTraits<uint32_t>::rootMax = pTraits<uint32_t>::max; +const uint32_t Foam::pTraits<uint32_t>::rootMax = UINT32_MAX; // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/primitives/ints/uint32/uint32.H b/src/OpenFOAM/primitives/ints/uint32/uint32.H index ba0e7e588726f19f49896b7ced229fb70cafe5d8..7d2f1e01e99964c66c81f3132af6b5a569b83df9 100644 --- a/src/OpenFOAM/primitives/ints/uint32/uint32.H +++ b/src/OpenFOAM/primitives/ints/uint32/uint32.H @@ -162,10 +162,7 @@ public: // Constructors //- Copy construct from primitive - explicit pTraits(uint32_t val) noexcept - : - p_(val) - {} + explicit pTraits(uint32_t val) noexcept : p_(val) {} //- Read construct from Istream explicit pTraits(Istream& is); diff --git a/src/OpenFOAM/primitives/ints/uint64/uint64.C b/src/OpenFOAM/primitives/ints/uint64/uint64.C index ab6269623485af5bac63652ff21f8198e35476fd..bf5dbb4ecbf1fc16ec87117bf341e201684965be 100644 --- a/src/OpenFOAM/primitives/ints/uint64/uint64.C +++ b/src/OpenFOAM/primitives/ints/uint64/uint64.C @@ -37,7 +37,7 @@ const uint64_t Foam::pTraits<uint64_t>::one = 1; const uint64_t Foam::pTraits<uint64_t>::min = 0; const uint64_t Foam::pTraits<uint64_t>::max = UINT64_MAX; const uint64_t Foam::pTraits<uint64_t>::rootMin = 0; -const uint64_t Foam::pTraits<uint64_t>::rootMax = pTraits<uint64_t>::max; +const uint64_t Foam::pTraits<uint64_t>::rootMax = UINT64_MAX; // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/primitives/ints/uint64/uint64.H b/src/OpenFOAM/primitives/ints/uint64/uint64.H index 98e6346d6b6bbf3df01c1758ffcef9cd18d66d03..3c352e4148bbc6cd7d7d307bcf051977e7c9921a 100644 --- a/src/OpenFOAM/primitives/ints/uint64/uint64.H +++ b/src/OpenFOAM/primitives/ints/uint64/uint64.H @@ -170,10 +170,7 @@ public: // Constructors //- Copy construct from primitive - explicit pTraits(uint64_t val) noexcept - : - p_(val) - {} + explicit pTraits(uint64_t val) noexcept : p_(val) {} //- Read construct from Istream explicit pTraits(Istream& is); diff --git a/src/OpenFOAM/primitives/ints/uint8/uint8.H b/src/OpenFOAM/primitives/ints/uint8/uint8.H index b17d19f72939404ad7a73a1fb303c2f8fb701ce1..4fc6c28f36666620e525fc6a7b53f965c20defbe 100644 --- a/src/OpenFOAM/primitives/ints/uint8/uint8.H +++ b/src/OpenFOAM/primitives/ints/uint8/uint8.H @@ -123,10 +123,7 @@ public: // Constructors //- Copy construct from primitive - explicit pTraits(uint8_t val) noexcept - : - p_(val) - {} + explicit pTraits(uint8_t val) noexcept : p_(val) {} //- Read construct from Istream explicit pTraits(Istream& is); @@ -135,16 +132,10 @@ public: // Member Functions //- Return the value - operator uint8_t() const noexcept - { - return p_; - } + operator uint8_t() const noexcept { return p_; } //- Access the value - operator uint8_t&() noexcept - { - return p_; - } + operator uint8_t&() noexcept { return p_; } }; diff --git a/src/Pstream/dummy/UIPBstreamRead.C b/src/Pstream/dummy/UIPBstreamRead.C index 31e0f0743fa0fd7ab502edbb20f9fb9822bb4d31..2a30bd5cbb07489fdaaef94c635298332cdbb49f 100644 --- a/src/Pstream/dummy/UIPBstreamRead.C +++ b/src/Pstream/dummy/UIPBstreamRead.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2022-2024 OpenCFD Ltd. + Copyright (C) 2022-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -35,19 +35,4 @@ void Foam::UIPBstream::bufferIPCrecv() } -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -std::streamsize Foam::UIPBstream::read -( - const int rootProcNo, - char* buf, - const std::streamsize bufSize, - const label comm -) -{ - NotImplemented; - return 0; -} - - // ************************************************************************* // diff --git a/src/Pstream/dummy/UIPstreamRead.C b/src/Pstream/dummy/UIPstreamRead.C index c8b7286fdf623ef7c04afb15c7b663830431cdfb..396a7a204b7268faa30eb546a469864458f6ef40 100644 --- a/src/Pstream/dummy/UIPstreamRead.C +++ b/src/Pstream/dummy/UIPstreamRead.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation - Copyright (C) 2021-2024 OpenCFD Ltd. + Copyright (C) 2021-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -28,24 +28,17 @@ License #include "UIPstream.H" -// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // - -void Foam::UIPstream::bufferIPCrecv() -{ - NotImplemented; -} - - -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +// * * * * * * * * * * Protected Static Member Functions * * * * * * * * * * // -std::streamsize Foam::UIPstream::read +std::streamsize Foam::UPstream::mpi_receive ( const UPstream::commsTypes commsType, + void* buf, + std::streamsize count, + const UPstream::dataTypes dataTypeId, const int fromProcNo, - char* buf, - const std::streamsize bufSize, const int tag, - const label communicator, + const int communicator, UPstream::Request* req ) { @@ -54,4 +47,12 @@ std::streamsize Foam::UIPstream::read } +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::UIPstream::bufferIPCrecv() +{ + NotImplemented; +} + + // ************************************************************************* // diff --git a/src/Pstream/dummy/UOPBstreamWrite.C b/src/Pstream/dummy/UOPBstreamWrite.C index 72c702f0343345bb1b1ffd00ce113b75bb474a2b..794791fc6140bf85bec9b7c6468c2e7798967adb 100644 --- a/src/Pstream/dummy/UOPBstreamWrite.C +++ b/src/Pstream/dummy/UOPBstreamWrite.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2022-2023 OpenCFD Ltd. + Copyright (C) 2022-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -38,17 +38,8 @@ bool Foam::UOPBstream::bufferIPCsend() // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -bool Foam::UOPBstream::write -( - const int rootProcNo, - const char* buf, - const std::streamsize bufSize, - const label comm -) -{ - NotImplemented; - return false; -} +void Foam::UOPBstream::send(Foam::zero, const int communicator) +{} // ************************************************************************* // diff --git a/src/Pstream/dummy/UOPstreamWrite.C b/src/Pstream/dummy/UOPstreamWrite.C index 24078ca9244d150dc9828a570d9f5fc5a2edaafe..b6f2a61f6dbd75c04d8b78f145c889de411ad7c5 100644 --- a/src/Pstream/dummy/UOPstreamWrite.C +++ b/src/Pstream/dummy/UOPstreamWrite.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation - Copyright (C) 2022-2023 OpenCFD Ltd. + Copyright (C) 2022-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -37,16 +37,17 @@ bool Foam::UOPstream::bufferIPCsend() } -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +// * * * * * * * * * * Protected Static Member Functions * * * * * * * * * * // -bool Foam::UOPstream::write +bool Foam::UPstream::mpi_send ( const UPstream::commsTypes commsType, + const void* buf, + std::streamsize count, + const UPstream::dataTypes dataTypeId, const int toProcNo, - const char* buf, - const std::streamsize bufSize, const int tag, - const label communicator, + const int communicator, UPstream::Request* req, const UPstream::sendModes sendMode ) diff --git a/src/Pstream/dummy/UPstreamBroadcast.C b/src/Pstream/dummy/UPstreamBroadcast.C index 079512f255ee5777047a973b7aec9f8751ef8b0f..0e87b5b50bc7ac98913afefbfdc0d6e25d1b64c2 100644 --- a/src/Pstream/dummy/UPstreamBroadcast.C +++ b/src/Pstream/dummy/UPstreamBroadcast.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2022 OpenCFD Ltd. + Copyright (C) 2022-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -27,17 +27,17 @@ License #include "UPstream.H" -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +// * * * * * * * * * * Protected Static Member Functions * * * * * * * * * * // -bool Foam::UPstream::broadcast +bool Foam::UPstream::mpi_broadcast ( - char* buf, - const std::streamsize bufSize, - const label comm, - const int rootProcNo + void* buf, + std::streamsize count, + const UPstream::dataTypes dataTypeId, + const int communicator ) { - // Nothing to do - ignore + // Treat like serial return true; } diff --git a/src/Pstream/dummy/UPstreamCommunicator.C b/src/Pstream/dummy/UPstreamCommunicator.C index e7c713f85c5dee460d74bd7863be5e3fb2f7a2f1..29055a6da2d2579cd16174039dcc8de271e1ded4 100644 --- a/src/Pstream/dummy/UPstreamCommunicator.C +++ b/src/Pstream/dummy/UPstreamCommunicator.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2024 OpenCFD Ltd. + Copyright (C) 2024-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -38,7 +38,7 @@ Foam::UPstream::Communicator::Communicator() noexcept // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // Foam::UPstream::Communicator -Foam::UPstream::Communicator::lookup(const label comm) +Foam::UPstream::Communicator::lookup(const int comm) { return UPstream::Communicator(nullptr); } @@ -56,4 +56,10 @@ void Foam::UPstream::Communicator::reset() noexcept {} +int Foam::UPstream::Communicator::size() const +{ + return 0; +} + + // ************************************************************************* // diff --git a/src/Pstream/dummy/UPstreamGatherScatter.C b/src/Pstream/dummy/UPstreamGatherScatter.C index 9034fc75f39e4c6b9eb77ee84265a5f6c28a2fdc..4d4e3992ef5cbb68fba1dcaaadf47329198872ca 100644 --- a/src/Pstream/dummy/UPstreamGatherScatter.C +++ b/src/Pstream/dummy/UPstreamGatherScatter.C @@ -26,91 +26,76 @@ License \*---------------------------------------------------------------------------*/ #include "UPstream.H" -#include <cstring> // memmove // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -#undef Pstream_CommonRoutines -#define Pstream_CommonRoutines(Type) \ - \ -void Foam::UPstream::mpiGather \ -( \ - const Type* sendData, \ - Type* recvData, \ - int count, \ - const label comm \ -) \ -{ \ - if (sendData && recvData) \ - { \ - std::memmove(recvData, sendData, count*sizeof(Type)); \ - } \ -} \ - \ - \ -void Foam::UPstream::mpiScatter \ -( \ - const Type* sendData, \ - Type* recvData, \ - int count, \ - const label comm \ -) \ -{ \ - if (sendData && recvData) \ - { \ - std::memmove(recvData, sendData, count*sizeof(Type)); \ - } \ -} \ - \ - \ -void Foam::UPstream::mpiAllGather \ -( \ - Type* allData, \ - int count, \ - const label comm \ -) \ -{} \ - \ - \ -void Foam::UPstream::mpiGatherv \ -( \ - const Type* sendData, \ - int sendCount, \ - \ - Type* recvData, \ - const UList<int>& recvCounts, \ - const UList<int>& recvOffsets, \ - const label comm \ -) \ -{ \ - /* recvCounts[0] may be invalid - use sendCount instead */ \ - std::memmove(recvData, sendData, sendCount*sizeof(Type)); \ -} \ - \ -void Foam::UPstream::mpiScatterv \ -( \ - const Type* sendData, \ - const UList<int>& sendCounts, \ - const UList<int>& sendOffsets, \ - \ - Type* recvData, \ - int recvCount, \ - const label comm \ -) \ -{ \ - std::memmove(recvData, sendData, recvCount*sizeof(Type)); \ -} - - -//TDB: Pstream_CommonRoutines(bool); -Pstream_CommonRoutines(char); -Pstream_CommonRoutines(int32_t); -Pstream_CommonRoutines(int64_t); -Pstream_CommonRoutines(uint32_t); -Pstream_CommonRoutines(uint64_t); -Pstream_CommonRoutines(float); -Pstream_CommonRoutines(double); - -#undef Pstream_CommonRoutines +void Foam::UPstream::mpi_gather +( + const void* sendData, + void* recvData, + int count, + const UPstream::dataTypes dataTypeId, + + const int communicator, + UPstream::Request* req +) +{} + + +void Foam::UPstream::mpi_scatter +( + const void* sendData, + void* recvData, + int count, + const UPstream::dataTypes dataTypeId, + + const int communicator, + UPstream::Request* req +) +{} + + +void Foam::UPstream::mpi_allgather +( + void* allData, + int count, + const UPstream::dataTypes dataTypeId, + + const int communicator, + UPstream::Request* req +) +{} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +void Foam::UPstream::mpi_gatherv +( + const void* sendData, + int sendCount, + void* recvData, + const UList<int>& recvCounts, + const UList<int>& recvOffsets, + + const UPstream::dataTypes dataTypeId, + const int communicator +) +{} + + +void Foam::UPstream::mpi_scatterv +( + const void* sendData, + const UList<int>& sendCounts, + const UList<int>& sendOffsets, + + void* recvData, + int recvCount, + + const UPstream::dataTypes dataTypeId, + const int communicator +) +{} + // ************************************************************************* // diff --git a/src/Pstream/dummy/UPstreamReduce.C b/src/Pstream/dummy/UPstreamReduce.C index 9572d0e52d19ac24a88308aaff3cfaa8e0e7fbd5..610b06e3579fa65b6d8097155f26a3d521beb950 100644 --- a/src/Pstream/dummy/UPstreamReduce.C +++ b/src/Pstream/dummy/UPstreamReduce.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2022-2023 OpenCFD Ltd. + Copyright (C) 2022-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -28,186 +28,60 @@ License #include "Pstream.H" #include "PstreamReduceOps.H" -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // // Special reductions for bool -void Foam::UPstream::reduceAnd(bool& value, const label comm) +void Foam::UPstream::reduceAnd(bool& value, const int communicator) {} -void Foam::UPstream::reduceOr(bool& value, const label comm) +void Foam::UPstream::reduceOr(bool& value, const int communicator) {} void Foam::reduce ( bool& value, - const andOp<bool>&, + Foam::andOp<bool>, const int tag, - const label comm + const int communicator ) {} void Foam::reduce ( bool& value, - const orOp<bool>&, + Foam::orOp<bool>, const int tag, - const label comm + const int communicator ) {} -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -// Common reductions - -#undef Pstream_CommonReductions -#define Pstream_CommonReductions(Native) \ - \ -void Foam::reduce \ -( \ - Native values[], \ - const int size, \ - const minOp<Native>&, \ - const int tag, \ - const label comm \ -) \ -{} \ - \ -void Foam::reduce \ -( \ - Native values[], \ - const int size, \ - const maxOp<Native>&, \ - const int tag, \ - const label comm \ -) \ -{} \ - \ -void Foam::reduce \ -( \ - Native values[], \ - const int size, \ - const sumOp<Native>&, \ - const int tag, \ - const label comm \ -) \ -{} \ - \ -void Foam::reduce \ -( \ - Native& value, \ - const minOp<Native>&, \ - const int tag, \ - const label comm \ -) \ -{} \ - \ -void Foam::reduce \ -( \ - Native& value, \ - const maxOp<Native>&, \ - const int tag, \ - const label comm \ -) \ -{} \ - \ -void Foam::reduce \ -( \ - Native& value, \ - const sumOp<Native>&, \ - const int tag, \ - const label comm \ -) \ -{} - +// * * * * * * * * * * Protected Static Member Functions * * * * * * * * * * // -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -// Floating-point reductions - -#undef Pstream_FloatReductions -#define Pstream_FloatReductions(Native) \ - \ -Pstream_CommonReductions(Native); \ - \ -void Foam::reduce \ -( \ - Native values[], \ - const int size, \ - const sumOp<Native>&, \ - const int tag, \ - const label comm, \ - UPstream::Request& req \ -) \ -{} \ - \ -void Foam::reduce \ -( \ - Native& value, \ - const sumOp<Native>&, \ - const int tag, \ - const label comm, \ - UPstream::Request& req \ -) \ -{} \ - \ -void Foam::sumReduce \ -( \ - Native& value, \ - label& count, \ - const int tag, \ - const label comm \ -) \ +void Foam::UPstream::mpi_reduce +( + void* values, + int count, + const UPstream::dataTypes dataTypeId, + const UPstream::opCodes opCodeId, + const int communicator, + UPstream::Request* req +) {} -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -// Bitwise reductions - -#undef Pstream_BitwiseReductions -#define Pstream_BitwiseReductions(Native) \ - \ -void Foam::reduce \ -( \ - Native values[], \ - const int size, \ - const bitOrOp<Native>&, \ - const int tag, \ - const label comm \ -) \ -{} \ - \ -void Foam::reduce \ -( \ - Native& value, \ - const bitOrOp<Native>&, \ - const int tag, \ - const label comm \ -) \ +void Foam::UPstream::mpi_allreduce +( + void* values, + int count, + const UPstream::dataTypes dataTypeId, + const UPstream::opCodes opCodeId, + const int communicator, + UPstream::Request* req +) {} -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -Pstream_CommonReductions(int32_t); -Pstream_CommonReductions(int64_t); -Pstream_CommonReductions(uint32_t); -Pstream_CommonReductions(uint64_t); - -Pstream_FloatReductions(float); -Pstream_FloatReductions(double); - -Pstream_BitwiseReductions(unsigned char); -Pstream_BitwiseReductions(unsigned int); - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -#undef Pstream_CommonReductions -#undef Pstream_FloatReductions -#undef Pstream_BitwiseReductions - - // ************************************************************************* // diff --git a/src/Pstream/dummy/UPstreamWindow.C b/src/Pstream/dummy/UPstreamWindow.C index 4c8e5b7906145f9989fef10819812bdf58e77e23..9af10b6e9119722f4564681db99ed74fc7f12d15 100644 --- a/src/Pstream/dummy/UPstreamWindow.C +++ b/src/Pstream/dummy/UPstreamWindow.C @@ -47,4 +47,10 @@ void Foam::UPstream::Window::reset() noexcept {} +int Foam::UPstream::Window::size() const +{ + return 0; +} + + // ************************************************************************* // diff --git a/src/Pstream/mpi/PstreamGlobals.C b/src/Pstream/mpi/PstreamGlobals.C index b7aa206aea7f0afa884b9bfcb3db4446e4b6e12a..20a6868c7231c42e87febcc7906e015de9bcd4bd 100644 --- a/src/Pstream/mpi/PstreamGlobals.C +++ b/src/Pstream/mpi/PstreamGlobals.C @@ -34,6 +34,9 @@ Foam::DynamicList<bool> Foam::PstreamGlobals::pendingMPIFree_; Foam::DynamicList<MPI_Comm> Foam::PstreamGlobals::MPICommunicators_; Foam::DynamicList<MPI_Request> Foam::PstreamGlobals::outstandingRequests_; +Foam::PstreamGlobals::DataTypeCountLookupTable +Foam::PstreamGlobals::dataTypesCount_(1); + Foam::PstreamGlobals::DataTypeLookupTable Foam::PstreamGlobals::MPIdataTypes_(MPI_DATATYPE_NULL); @@ -70,6 +73,12 @@ void Foam::PstreamGlobals::initCommunicator(const label index) void Foam::PstreamGlobals::initDataTypes() { + static_assert + ( + PstreamGlobals::DataTypeCountLookupTable::max_size() + == (int(UPstream::dataTypes::DataTypes_end)+1), + "Data count lookup table size != number of dataTypes enumerations" + ); static_assert ( PstreamGlobals::DataTypeLookupTable::max_size() @@ -77,15 +86,21 @@ void Foam::PstreamGlobals::initDataTypes() "Lookup table size != number of dataTypes enumerations" ); - // From enumeration to MPI datatype + // From enumeration to MPI datatype for fundamental types + // (count is always 1) #undef defineType - #define defineType(Idx, BaseType) \ - MPIdataTypes_[int(UPstream::dataTypes::Idx)] = BaseType; + #define defineType(Idx, BaseType) \ + { \ + dataTypesCount_[int(UPstream::dataTypes::Idx)] = 1; \ + MPIdataTypes_[int(UPstream::dataTypes::Idx)] = BaseType; \ + } - // Intrinsic Types [8]: + // Fundamental Types [10]: defineType(type_byte, MPI_BYTE); + defineType(type_int16, MPI_INT16_T); defineType(type_int32, MPI_INT32_T); defineType(type_int64, MPI_INT64_T); + defineType(type_uint16, MPI_UINT16_T); defineType(type_uint32, MPI_UINT32_T); defineType(type_uint64, MPI_UINT64_T); defineType(type_float, MPI_FLOAT); @@ -98,6 +113,7 @@ void Foam::PstreamGlobals::initDataTypes() #undef defineUserType #define defineUserType(Idx, Count, BaseType, Name) \ { \ + dataTypesCount_[int(UPstream::dataTypes::Idx)] = Count; \ auto& dt = MPIdataTypes_[int(UPstream::dataTypes::Idx)]; \ MPI_Type_contiguous(Count, BaseType, &dt); \ MPI_Type_set_name(dt, Name); \ @@ -121,11 +137,11 @@ void Foam::PstreamGlobals::deinitDataTypes() // User types only auto first = ( - MPIdataTypes_.begin() + int(UPstream::dataTypes::UserTypes_begin) + MPIdataTypes_.begin() + int(UPstream::dataTypes::User_begin) ); const auto last = ( - MPIdataTypes_.begin() + int(UPstream::dataTypes::UserTypes_end) + MPIdataTypes_.begin() + int(UPstream::dataTypes::User_end) ); for (; first != last; ++first) @@ -200,20 +216,20 @@ void Foam::PstreamGlobals::printDataTypes(bool all) std::cerr << "enumerated data types:\n"; print ( - UPstream::dataTypes::DataTypes_begin, - UPstream::dataTypes::DataTypes_end + UPstream::dataTypes::Basic_begin, + UPstream::dataTypes::Basic_end ); } else { // User types only. std::cerr << "enumerated user-defined data types:\n"; - print - ( - UPstream::dataTypes::UserTypes_begin, - UPstream::dataTypes::UserTypes_end - ); } + print + ( + UPstream::dataTypes::User_begin, + UPstream::dataTypes::User_end + ); } diff --git a/src/Pstream/mpi/PstreamGlobals.H b/src/Pstream/mpi/PstreamGlobals.H index bf46434ad788e1b16eb3cb1f1d4658906491988b..e895883992f36ba72b7166a6fc1bc84780c37f43 100644 --- a/src/Pstream/mpi/PstreamGlobals.H +++ b/src/Pstream/mpi/PstreamGlobals.H @@ -63,18 +63,28 @@ extern DynamicList<MPI_Comm> MPICommunicators_; //- Outstanding non-blocking operations. extern DynamicList<MPI_Request> outstandingRequests_; -typedef Foam::FixedList<MPI_Datatype, 15> DataTypeLookupTable; +// The fundamental count for each UPstream::dataTypes entry +typedef Foam::FixedList<int, 17> DataTypeCountLookupTable; -//- MPI data types corresponding to some fundamental and OpenFOAM types. +//- Fundamental count for each valid UPstream::dataTypes entry +//- Indexed by UPstream::dataTypes enum +extern DataTypeCountLookupTable dataTypesCount_; + +// For UPstream::dataTypes lookup, includes space for last 'invalid' entry +typedef Foam::FixedList<MPI_Datatype, 17> DataTypeLookupTable; + +//- MPI data types corresponding to fundamental and OpenFOAM types. //- Indexed by UPstream::dataTypes enum extern DataTypeLookupTable MPIdataTypes_; +// For UPstream::opCodes lookup, includes space for last 'invalid' entry typedef Foam::FixedList<MPI_Op, 13> OpCodesLookupTable; //- MPI operation types, indexed by UPstream::opCodes enum extern OpCodesLookupTable MPIopCodes_; + // * * * * * * * * * * * * * * * Communicators * * * * * * * * * * * * * * * // //- Initialize bookkeeping for MPI communicator index @@ -203,6 +213,25 @@ inline void push_request } +// * * * * * * * * * * * * * * Convenience Methods * * * * * * * * * * * * * // + +//- Broadcast a single int64 value. +// +// Ensures consistent data types. Used within the following: +// - UIPBstream::bufferIPCrecv() +// - UOPBstream::bufferIPCsend() +// - UOPBstream::send(Foam::zero, ...) + +inline bool broadcast_int64(int64_t& value, int comm) +{ + return + ( + MPI_SUCCESS + == MPI_Bcast(&value, 1, MPI_INT64_T, 0, MPICommunicators_[comm]) + ); +} + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace PstreamGlobals diff --git a/src/Pstream/mpi/UIPBstreamRead.C b/src/Pstream/mpi/UIPBstreamRead.C index 5080583396cd19d300eae994d0617a803f4c19ea..93db0ff80f94ecc481dcd3b8e79a13d11aa146af 100644 --- a/src/Pstream/mpi/UIPBstreamRead.C +++ b/src/Pstream/mpi/UIPBstreamRead.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2022-2024 OpenCFD Ltd. + Copyright (C) 2022-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -26,8 +26,8 @@ License \*---------------------------------------------------------------------------*/ #include "UIPstream.H" -#include "PstreamGlobals.H" #include "IOstreams.H" +#include "PstreamGlobals.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // @@ -37,33 +37,32 @@ void Foam::UIPBstream::bufferIPCrecv() // 1. for the data size // 2. for the data itself - // Expected message size, similar to MPI_Probe - // Same type must be expected in UOPBstream::bufferIPCsend() - std::streamsize bufSize(0); - // Broadcast #1 - data size - if - ( - !UPstream::broadcast - ( - reinterpret_cast<char*>(&bufSize), - sizeof(std::streamsize), - comm_, - fromProcNo_ //< is actually rootProcNo - ) - ) + // Same data type must be used in UOPBstream::bufferIPCsend() + + int64_t count(0); + if (!PstreamGlobals::broadcast_int64(count, comm_)) { FatalErrorInFunction - << "MPI_Bcast failure receiving buffer size" << nl + << "Broadcast failure receiving buffer size" << nl + << " comm:" << comm_ << nl << Foam::abort(FatalError); } - if (UPstream::debug) + // This is not actually possible - sender uses List::size() + // + // if (FOAM_UNLIKELY(count > int64_t(UList<char>::max_size()))) + // { + // FatalErrorInFunction + // << "Broadcast list size larger than UList<char>::max_size()" + // << Foam::abort(FatalError); + // } + + if (FOAM_UNLIKELY(UPstream::debug)) { - Perr<< "UOPBstream IPC read buffer :" - << " root:" << fromProcNo_ + Perr<< "UIPBstream IPC read buffer :" << " comm:" << comm_ - << " probed size:" << label(bufSize) + << " probed size:" << label(count) << " wanted size:" << recvBuf_.capacity() << Foam::endl; } @@ -71,33 +70,33 @@ void Foam::UIPBstream::bufferIPCrecv() // Set buffer size, avoiding any copying and resize doubling etc. recvBuf_.clear(); - if (recvBuf_.capacity() < label(bufSize)) + if (recvBuf_.capacity() < label(count)) { - recvBuf_.setCapacity_nocopy(label(bufSize)); + recvBuf_.setCapacity_nocopy(label(count)); } - recvBuf_.resize_nocopy(label(bufSize)); + recvBuf_.resize_nocopy(label(count)); // This is the only real information we can trust - messageSize_ = label(bufSize); + messageSize_ = label(count); // Broadcast #2 - data content // - skip if there is no data to receive if ( - (bufSize > 0) - && !UPstream::broadcast + (count > 0) // ie, not empty + && !UPstream::mpi_broadcast ( recvBuf_.data(), - recvBuf_.size(), // same as bufSize - comm_, - fromProcNo_ //< is actually rootProcNo + recvBuf_.size(), // same as count + UPstream::dataTypes::type_byte, + comm_ ) ) { FatalErrorInFunction - << "MPI_Bcast failure receiving buffer data:" - << recvBuf_.size() << nl + << "Broadcast failure receiving buffer data:" + << recvBuf_.size() << " comm:" << comm_ << nl << Foam::abort(FatalError); } @@ -108,29 +107,4 @@ void Foam::UIPBstream::bufferIPCrecv() } -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -std::streamsize Foam::UIPBstream::read -( - const int rootProcNo, - char* buf, - const std::streamsize bufSize, - const label comm -) -{ - if - ( - !UPstream::broadcast(buf, bufSize, comm, rootProcNo) - ) - { - FatalErrorInFunction - << "MPI_Bcast failure receiving data:" << label(bufSize) << nl - << Foam::abort(FatalError); - return 0; - } - - return bufSize; -} - - // ************************************************************************* // diff --git a/src/Pstream/mpi/UIPstreamRead.C b/src/Pstream/mpi/UIPstreamRead.C index 4f94257e712752c2351c2389772fb258e89fd919..050995e952bb176376fd771111451663faaff305 100644 --- a/src/Pstream/mpi/UIPstreamRead.C +++ b/src/Pstream/mpi/UIPstreamRead.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2019-2024 OpenCFD Ltd. + Copyright (C) 2019-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -35,41 +35,47 @@ License // - as of 2023-06 appears to be broken with INTELMPI + PMI-2 (slurm) // and perhaps other places so currently avoid -#undef Pstream_use_MPI_Get_count - -// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // +// * * * * * * * * * * Protected Static Member Functions * * * * * * * * * * // // General blocking/non-blocking MPI receive -static std::streamsize UPstream_mpi_receive +std::streamsize Foam::UPstream::mpi_receive ( - const Foam::UPstream::commsTypes commsType, - char* buf, - const std::streamsize bufSize, + const UPstream::commsTypes commsType, + void* buf, // Type checking done by caller + std::streamsize count, + const UPstream::dataTypes dataTypeId, // Proper type passed by caller const int fromProcNo, const int tag, - const Foam::label communicator, - Foam::UPstream::Request* req + const int communicator, + UPstream::Request* req ) { - using namespace Foam; + MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId); PstreamGlobals::reset_request(req); + // Could check if nonBlocking and request are consistently specified... + + // TODO: some corrective action, at least when not nonBlocking #if 0 // No warnings here, just on the sender side. - if (bufSize > std::streamsize(INT_MAX)) + if (count > std::streamsize(INT_MAX)) { - Perr<< "UIPstream::read() : from rank " << fromProcNo - << " exceeds INT_MAX bytes" << Foam::endl; + Perr<< "[mpi_recv] from rank " << fromProcNo + << " exceeds INT_MAX values of " + << PstreamGlobals::dataType_name(datatype) + << Foam::endl; + error::printStack(Perr); } #endif if (FOAM_UNLIKELY(PstreamGlobals::warnCommunicator(communicator))) { - Perr<< "UIPstream::read : starting read from:" << fromProcNo - << " size:" << label(bufSize) + Perr<< "[mpi_recv] : starting recv from:" << fromProcNo + << " type:" << int(dataTypeId) + << " count:" << label(count) << " tag:" << tag << " comm:" << communicator << " commsType:" << UPstream::commsTypeNames[commsType] << " warnComm:" << UPstream::warnComm @@ -78,8 +84,9 @@ static std::streamsize UPstream_mpi_receive } else if (FOAM_UNLIKELY(UPstream::debug)) { - Perr<< "UIPstream::read : starting read from:" << fromProcNo - << " size:" << label(bufSize) + Perr<< "[mpi_recv] : starting recv from:" << fromProcNo + << " type:" << int(dataTypeId) + << " count:" << label(count) << " tag:" << tag << " comm:" << communicator << " commsType:" << UPstream::commsTypeNames[commsType] << Foam::endl; @@ -103,68 +110,75 @@ static std::streamsize UPstream_mpi_receive returnCode = MPI_Recv ( buf, - bufSize, - MPI_BYTE, + count, + datatype, fromProcNo, tag, PstreamGlobals::MPICommunicators_[communicator], - &status + &status ); } profilingPstream::addGatherTime(); - if (returnCode != MPI_SUCCESS) + if (FOAM_UNLIKELY(returnCode != MPI_SUCCESS)) { FatalErrorInFunction - << "MPI_Recv cannot receive incoming message" + << "[mpi_recv] : cannot receive message from:" + << fromProcNo + << " type:" << int(dataTypeId) + << " count:" << label(count) << " tag:" << tag << Foam::abort(FatalError); return 0; } else if (FOAM_UNLIKELY(UPstream::debug)) { - Perr<< "UIPstream::read : finished recv from:" + Perr<< "[mpi_recv] : finished recv from:" << fromProcNo - << " size:" << label(bufSize) << " tag:" << tag + << " type:" << int(dataTypeId) + << " count:" << label(count) << " tag:" << tag << Foam::endl; } - // Check size of message read - #ifdef Pstream_use_MPI_Get_count - int count(0); - MPI_Get_count(&status, MPI_BYTE, &count); - #else - MPI_Count count(0); - MPI_Get_elements_x(&status, MPI_BYTE, &count); - #endif + // Check size of message read (number of basic elements) + MPI_Count num_recv(0); + MPI_Get_elements_x(&status, datatype, &num_recv); // Errors - if (count == MPI_UNDEFINED || int64_t(count) < 0) + if (FOAM_UNLIKELY(num_recv == MPI_UNDEFINED || int64_t(num_recv) < 0)) { FatalErrorInFunction - << "MPI_Get_count() or MPI_Get_elements_x() : " - "returned undefined or negative value" + << "[mpi_recv] : receive from:" << fromProcNo + << " type:" << int(dataTypeId) + << " received count is undefined or negative value" << Foam::abort(FatalError); } - else if (int64_t(count) > int64_t(UList<char>::max_size())) + else + { + // From number of basic elements to number of 'datatype' + num_recv /= PstreamGlobals::dataTypesCount_[int(dataTypeId)]; + } + + if (FOAM_UNLIKELY(int64_t(num_recv) > int64_t(UList<char>::max_size()))) { FatalErrorInFunction - << "MPI_Get_count() or MPI_Get_elements_x() : " - "count is larger than UList<char>::max_size() bytes" + << "[mpi_recv] : receive from:" << fromProcNo + << " type:" << int(dataTypeId) + << " received count is larger than UList<T>::max_size()" << Foam::abort(FatalError); } - - - if (bufSize < std::streamsize(count)) + else if (FOAM_UNLIKELY(count < std::streamsize(num_recv))) { FatalErrorInFunction - << "buffer (" << label(bufSize) - << ") not large enough for incoming message (" - << label(count) << ')' + << "[mpi_recv] : receive from:" << fromProcNo + << " type:" << int(dataTypeId) + << " count:" << label(count) + << " buffer is too small for incoming message (" + << label(num_recv) << ')' << Foam::abort(FatalError); } - return std::streamsize(count); + return std::streamsize(num_recv); } else if (commsType == UPstream::commsTypes::nonBlocking) { @@ -174,19 +188,22 @@ static std::streamsize UPstream_mpi_receive returnCode = MPI_Irecv ( buf, - bufSize, - MPI_BYTE, + count, + datatype, fromProcNo, tag, PstreamGlobals::MPICommunicators_[communicator], - &request + &request ); } - if (returnCode != MPI_SUCCESS) + if (FOAM_UNLIKELY(returnCode != MPI_SUCCESS)) { FatalErrorInFunction - << "MPI_Irecv cannot start non-blocking receive" + << "[mpi_recv] : cannot start non-blocking receive from:" + << fromProcNo + << " type:" << int(dataTypeId) + << " count:" << label(count) << Foam::abort(FatalError); return 0; @@ -198,16 +215,17 @@ static std::streamsize UPstream_mpi_receive if (FOAM_UNLIKELY(UPstream::debug)) { - Perr<< "UIPstream::read : started non-blocking recv from:" + Perr<< "[mpi_recv] : started non-blocking recv from:" << fromProcNo - << " size:" << label(bufSize) << " tag:" << tag + << " type:" << int(dataTypeId) + << " count:" << label(count) << " tag:" << tag << " request:" << (req ? label(-1) : PstreamGlobals::outstandingRequests_.size()) << Foam::endl; } // Assume the message will be completely received. - return bufSize; + return count; } FatalErrorInFunction @@ -264,63 +282,64 @@ void Foam::UIPstream::bufferIPCrecv() profilingPstream::addProbeTime(); - - #ifdef Pstream_use_MPI_Get_count - int count(0); - MPI_Get_count(&status, MPI_BYTE, &count); - #else - MPI_Count count(0); - MPI_Get_elements_x(&status, MPI_BYTE, &count); - #endif + // Buffer of characters (bytes) + MPI_Count num_recv(0); + MPI_Get_elements_x(&status, MPI_BYTE, &num_recv); // Errors - if (count == MPI_UNDEFINED || int64_t(count) < 0) + if (FOAM_UNLIKELY(num_recv == MPI_UNDEFINED || int64_t(num_recv) < 0)) { FatalErrorInFunction - << "MPI_Get_count() or MPI_Get_elements_x() : " - "returned undefined or negative value" + << "UIPstream IPC read buffer from:" << fromProcNo_ + << " received count is undefined or negative value" << Foam::abort(FatalError); } - else if (int64_t(count) > int64_t(UList<char>::max_size())) + + // Count is already in basic elements, no need to scale the result + + if (FOAM_UNLIKELY(int64_t(num_recv) > int64_t(UList<char>::max_size()))) { FatalErrorInFunction - << "MPI_Get_count() or MPI_Get_elements_x() : " - "count is larger than UList<char>::max_size() bytes" + << "UIPstream IPC read buffer from:" << fromProcNo_ + << " received count is larger than UList<T>::max_size()" << Foam::abort(FatalError); } if (FOAM_UNLIKELY(UPstream::debug)) { - Perr<< "UIPstream::UIPstream : probed size:" - << label(count) << Foam::endl; + Perr<< "UIPstream::bufferIPCrecv : probed size:" + << label(num_recv) << Foam::endl; } - recvBuf_.resize(label(count)); - messageSize_ = label(count); + recvBuf_.resize(label(num_recv)); + messageSize_ = label(num_recv); } - std::streamsize count = UPstream_mpi_receive + std::streamsize count = UPstream::mpi_receive ( commsType(), - recvBuf_.data(), - messageSize_, // The expected size + recvBuf_.data(), // buffer + messageSize_, // expected size + UPstream::dataTypes::type_byte, // MPI_BYTE fromProcNo_, tag_, comm_, nullptr // UPstream::Request ); - if (count < 0) + // Errors + if (FOAM_UNLIKELY(count < 0)) { FatalErrorInFunction - << "MPI_recv() with negative size??" + << "UIPstream IPC read buffer from:" << fromProcNo_ + << " with negative size?" << Foam::abort(FatalError); } - else if (int64_t(count) > int64_t(UList<char>::max_size())) + else if (FOAM_UNLIKELY(int64_t(count) > int64_t(UList<char>::max_size()))) { FatalErrorInFunction - << "MPI_recv() larger than " - "UList<char>::max_size() bytes" + << "UIPstream IPC read buffer from:" << fromProcNo_ + << " received size is larger than UList<T>::max_size()" << Foam::abort(FatalError); } @@ -335,30 +354,4 @@ void Foam::UIPstream::bufferIPCrecv() } -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -std::streamsize Foam::UIPstream::read -( - const UPstream::commsTypes commsType, - const int fromProcNo, - char* buf, - const std::streamsize bufSize, - const int tag, - const label communicator, - UPstream::Request* req -) -{ - return UPstream_mpi_receive - ( - commsType, - buf, - bufSize, - fromProcNo, - tag, - communicator, - req - ); -} - - // ************************************************************************* // diff --git a/src/Pstream/mpi/UOPBstreamWrite.C b/src/Pstream/mpi/UOPBstreamWrite.C index f4c9412fca4e182564450d8b0cc75361ff92d255..90c96ab3a2d4539154bdd12f37e0f046e533c09e 100644 --- a/src/Pstream/mpi/UOPBstreamWrite.C +++ b/src/Pstream/mpi/UOPBstreamWrite.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2022-2023 OpenCFD Ltd. + Copyright (C) 2022-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -39,55 +39,36 @@ bool Foam::UOPBstream::bufferIPCsend() PstreamGlobals::checkCommunicator(comm_, toProcNo_); - // Same type must be expected in UIPBstream::bufferIPCrecv() - std::streamsize bufSize(sendBuf_.size()); - - // TODO: some corrective action - #if 0 - if (bufSize > std::streamsize(INT_MAX)) - { - Perr<< "UOPBstream::write() :" - << " exceeds INT_MAX bytes" << Foam::endl; - error::printStack(Perr); - } - #endif - // Broadcast #1 - data size - if - ( - !UPstream::broadcast - ( - reinterpret_cast<char*>(&bufSize), - sizeof(std::streamsize), - comm_, - toProcNo_ //< is actually rootProcNo - ) - ) + // Same data type must be used in UIPBstream::bufferIPCrecv() + + int64_t count(sendBuf_.size()); + if (!PstreamGlobals::broadcast_int64(count, comm_)) { FatalErrorInFunction - << "MPI_Bcast failure sending buffer size:" << bufSize << nl + << "Broadcast failure sending buffer size:" + << label(count) << " comm:" << comm_ << nl << Foam::abort(FatalError); return false; } - // Broadcast #2 - data content // - skip if there is no data to send if ( - (bufSize > 0) - && !UPstream::broadcast + (count > 0) // ie, not empty + && !UPstream::mpi_broadcast ( sendBuf_.data(), - sendBuf_.size(), // same as bufSize - comm_, - toProcNo_ //< is actually rootProcNo + sendBuf_.size(), // same as count + UPstream::dataTypes::type_byte, + comm_ ) ) { FatalErrorInFunction - << "MPI_Bcast failure sending buffer data:" - << sendBuf_.size() << nl + << "Broadcast failure sending buffer data:" + << sendBuf_.size() << " comm:" << comm_ << nl << Foam::abort(FatalError); return false; } @@ -98,26 +79,10 @@ bool Foam::UOPBstream::bufferIPCsend() // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -bool Foam::UOPBstream::write -( - const int rootProcNo, - const char* buf, - const std::streamsize bufSize, - const label comm -) +void Foam::UOPBstream::send(Foam::zero, const int communicator) { - if - ( - !UPstream::broadcast(const_cast<char*>(buf), bufSize, comm, rootProcNo) - ) - { - FatalErrorInFunction - << "MPI_Bcast failure sending buffer data:" << label(bufSize) << nl - << Foam::abort(FatalError); - return false; - } - - return true; + int64_t count(0); + PstreamGlobals::broadcast_int64(count, communicator); } diff --git a/src/Pstream/mpi/UOPstreamWrite.C b/src/Pstream/mpi/UOPstreamWrite.C index d2e1da2ec65f255d3d215793843e079a6f015829..dca49157c2737294eff70b07b209f2bfd81723ef 100644 --- a/src/Pstream/mpi/UOPstreamWrite.C +++ b/src/Pstream/mpi/UOPstreamWrite.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2019-2023 OpenCFD Ltd. + Copyright (C) 2019-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -46,36 +46,47 @@ bool Foam::UOPstream::bufferIPCsend() } -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +// * * * * * * * * * * Protected Static Member Functions * * * * * * * * * * // -bool Foam::UOPstream::write +// General blocking/non-blocking MPI send +bool Foam::UPstream::mpi_send ( const UPstream::commsTypes commsType, + const void* buf, // Type checking done by caller + std::streamsize count, + const UPstream::dataTypes dataTypeId, // Proper type passed by caller const int toProcNo, - const char* buf, - const std::streamsize bufSize, const int tag, - const label communicator, + const int communicator, UPstream::Request* req, const UPstream::sendModes sendMode ) { + MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId); + PstreamGlobals::reset_request(req); + // Could check if nonBlocking and request are consistently specified... + + // TODO: some corrective action, at least when not nonBlocking #if 0 - if (bufSize > std::streamsize(INT_MAX)) + if (count > std::streamsize(INT_MAX)) { - Perr<< "UOPstream::write() : to rank " << toProcNo - << " exceeds INT_MAX bytes" << Foam::endl; + Perr<< "[mpi_send] : to rank " << toProcNo + << " type:" << int(dataTypeId) + << " exceeds INT_MAX values" + << Foam::endl; + error::printStack(Perr); } #endif if (FOAM_UNLIKELY(PstreamGlobals::warnCommunicator(communicator))) { - Perr<< "UOPstream::write : starting write to:" << toProcNo - << " size:" << label(bufSize) + Perr<< "[mpi_send] : starting send to:" << toProcNo + << " type:" << int(dataTypeId) + << " count:" << label(count) << " tag:" << tag << " comm:" << communicator << " commType:" << UPstream::commsTypeNames[commsType] << " warnComm:" << UPstream::warnComm @@ -84,8 +95,9 @@ bool Foam::UOPstream::write } else if (FOAM_UNLIKELY(UPstream::debug)) { - Perr<< "UOPstream::write : starting write to:" << toProcNo - << " size:" << label(bufSize) + Perr<< "[mpi_send] : starting send to:" << toProcNo + << " type:" << int(dataTypeId) + << " count:" << label(count) << " tag:" << tag << " comm:" << communicator << " commType:" << UPstream::commsTypeNames[commsType] << Foam::endl; @@ -101,9 +113,9 @@ bool Foam::UOPstream::write { returnCode = MPI_Bsend ( - const_cast<char*>(buf), - bufSize, - MPI_BYTE, + buf, + count, + datatype, toProcNo, tag, PstreamGlobals::MPICommunicators_[communicator] @@ -114,9 +126,9 @@ bool Foam::UOPstream::write if (FOAM_UNLIKELY(UPstream::debug)) { - Perr<< "UOPstream::write : finished buffered send to:" + Perr<< "[mpi_send] : finished buffered send to:" << toProcNo - << " size:" << label(bufSize) << " tag:" << tag + << " count:" << label(count) << " tag:" << tag << Foam::endl; } } @@ -126,9 +138,9 @@ bool Foam::UOPstream::write { returnCode = MPI_Ssend ( - const_cast<char*>(buf), - bufSize, - MPI_BYTE, + buf, + count, + datatype, toProcNo, tag, PstreamGlobals::MPICommunicators_[communicator] @@ -138,9 +150,9 @@ bool Foam::UOPstream::write { returnCode = MPI_Send ( - const_cast<char*>(buf), - bufSize, - MPI_BYTE, + buf, + count, + datatype, toProcNo, tag, PstreamGlobals::MPICommunicators_[communicator] @@ -152,9 +164,10 @@ bool Foam::UOPstream::write if (FOAM_UNLIKELY(UPstream::debug)) { - Perr<< "UOPstream::write : finished send to:" + Perr<< "[mpi_send] : finished send to:" << toProcNo - << " size:" << label(bufSize) << " tag:" << tag + << " type:" << int(dataTypeId) + << " count:" << label(count) << " tag:" << tag << Foam::endl; } } @@ -166,9 +179,9 @@ bool Foam::UOPstream::write { returnCode = MPI_Issend ( - const_cast<char*>(buf), - bufSize, - MPI_BYTE, + buf, + count, + datatype, toProcNo, tag, PstreamGlobals::MPICommunicators_[communicator], @@ -179,9 +192,9 @@ bool Foam::UOPstream::write { returnCode = MPI_Isend ( - const_cast<char*>(buf), - bufSize, - MPI_BYTE, + buf, + count, + datatype, toProcNo, tag, PstreamGlobals::MPICommunicators_[communicator], @@ -191,9 +204,10 @@ bool Foam::UOPstream::write if (FOAM_UNLIKELY(UPstream::debug)) { - Perr<< "UOPstream::write : started non-blocking send to:" + Perr<< "[mpi_send] : started non-blocking send to:" << toProcNo - << " size:" << label(bufSize) << " tag:" << tag + << " type:" << int(dataTypeId) + << " count:" << label(count) << " tag:" << tag << " request:" << (req ? label(-1) : PstreamGlobals::outstandingRequests_.size()) << Foam::endl; @@ -207,6 +221,7 @@ bool Foam::UOPstream::write FatalErrorInFunction << "Unsupported communications type " << int(commsType) << Foam::abort(FatalError); + return false; } return (returnCode == MPI_SUCCESS); diff --git a/src/Pstream/mpi/UPstream.C b/src/Pstream/mpi/UPstream.C index a3bfe3ab4296730979bc254c236f2dd175fa948c..1b051b072fb2d20c3583dd8e591edaf3ae14b557 100644 --- a/src/Pstream/mpi/UPstream.C +++ b/src/Pstream/mpi/UPstream.C @@ -1253,14 +1253,14 @@ Foam::UPstream::probeMessage MPI_Get_elements_x(&status, MPI_BYTE, &num_recv); // Errors - if (num_recv == MPI_UNDEFINED || int64_t(num_recv) < 0) + if (FOAM_UNLIKELY(num_recv == MPI_UNDEFINED || int64_t(num_recv) < 0)) { FatalErrorInFunction << "MPI_Get_elements_x() : " "returned undefined or negative value" << Foam::abort(FatalError); } - else if (int64_t(num_recv) > int64_t(INT_MAX)) + else if (FOAM_UNLIKELY(int64_t(num_recv) > int64_t(INT_MAX))) { FatalErrorInFunction << "MPI_Get_elements_x() : " diff --git a/src/Pstream/mpi/UPstreamBroadcast.C b/src/Pstream/mpi/UPstreamBroadcast.C index 1b3669d3a4121c95a28b332d5ebd6d1e307e8aec..91f4b1abfc66f671379f7f4c81019e2fd027b4f7 100644 --- a/src/Pstream/mpi/UPstreamBroadcast.C +++ b/src/Pstream/mpi/UPstreamBroadcast.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2022-2023 OpenCFD Ltd. + Copyright (C) 2022-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -29,51 +29,62 @@ License #include "PstreamGlobals.H" #include "profilingPstream.H" -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +// * * * * * * * * * * Protected Static Member Functions * * * * * * * * * * // -bool Foam::UPstream::broadcast +bool Foam::UPstream::mpi_broadcast ( - char* buf, - const std::streamsize bufSize, - const label comm, - const int rootProcNo + void* buf, // Type checking done by caller + std::streamsize count, + const UPstream::dataTypes dataTypeId, // Proper type passed by caller + const int communicator // Index into MPICommunicators_ ) { - if (!UPstream::is_parallel(comm)) + MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId); + + if (!count || !UPstream::is_parallel(communicator)) { // Nothing to do - ignore return true; } - //Needed? PstreamGlobals::checkCommunicator(comm, rootProcNo); + //Needed? PstreamGlobals::checkCommunicator(communicator, 0); - if (FOAM_UNLIKELY(PstreamGlobals::warnCommunicator(comm))) + // Without MPI_Bcast_c() + if (FOAM_UNLIKELY(count > std::streamsize(INT_MAX))) { - Perr<< "UPstream::broadcast : root:" << rootProcNo - << " comm:" << comm - << " size:" << label(bufSize) - << " warnComm:" << UPstream::warnComm - << Foam::endl; - error::printStack(Perr); + FatalErrorInFunction + << "Broadcast size " << label(count) + << " exceeds INT_MAX bytes" << Foam::endl + << Foam::abort(FatalError); + return false; } - else if (FOAM_UNLIKELY(UPstream::debug)) + + if (FOAM_UNLIKELY(UPstream::debug)) { - Perr<< "UPstream::broadcast : root:" << rootProcNo - << " comm:" << comm - << " size:" << label(bufSize) + Perr<< "[mpi_broadcast] :" + << " type:" << int(dataTypeId) + << " count:" << label(count) + << " comm:" << communicator << Foam::endl; } + int returnCode = MPI_SUCCESS; + profilingPstream::beginTiming(); - const int returnCode = MPI_Bcast - ( - buf, - bufSize, - MPI_BYTE, - rootProcNo, - PstreamGlobals::MPICommunicators_[comm] - ); + { + // Regular broadcast + // OR: PstreamDetail::broadcast0(buf, count, datatype, communicator); + + returnCode = MPI_Bcast + ( + buf, + count, + datatype, + 0, // (root rank) == UPstream::masterNo() + PstreamGlobals::MPICommunicators_[communicator] + ); + } profilingPstream::addBroadcastTime(); diff --git a/src/Pstream/mpi/UPstreamCommunicator.C b/src/Pstream/mpi/UPstreamCommunicator.C index 9040f2f0dc24345c5cfeede063b583e4c680e0eb..adff0a7ea300c3327f14c5419eaf1bd7a0213caf 100644 --- a/src/Pstream/mpi/UPstreamCommunicator.C +++ b/src/Pstream/mpi/UPstreamCommunicator.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2024 OpenCFD Ltd. + Copyright (C) 2024-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -39,7 +39,7 @@ Foam::UPstream::Communicator::Communicator() noexcept // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // Foam::UPstream::Communicator -Foam::UPstream::Communicator::lookup(const label comm) +Foam::UPstream::Communicator::lookup(const int comm) { if (comm < 0 || comm >= PstreamGlobals::MPICommunicators_.size()) { @@ -70,4 +70,27 @@ void Foam::UPstream::Communicator::reset() noexcept } +int Foam::UPstream::Communicator::size() const +{ + int val = 0; + + MPI_Comm comm = PstreamUtils::Cast::to_mpi(*this); + + if (MPI_COMM_SELF == comm) + { + return 1; + } + else if + ( + (MPI_COMM_NULL == comm) + || (MPI_SUCCESS != MPI_Comm_size(comm, &val)) + ) + { + val = 0; + } + + return val; +} + + // ************************************************************************* // diff --git a/src/Pstream/mpi/UPstreamGatherScatter.C b/src/Pstream/mpi/UPstreamGatherScatter.C index 36cac86dd427d9df5a82961127c467d29b5de79c..561a1d41c982ef631a16c06bbb83e78a4187570e 100644 --- a/src/Pstream/mpi/UPstreamGatherScatter.C +++ b/src/Pstream/mpi/UPstreamGatherScatter.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2022-2023 OpenCFD Ltd. + Copyright (C) 2022-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -26,109 +26,235 @@ License \*---------------------------------------------------------------------------*/ #include "Pstream.H" +#include "PstreamGlobals.H" #include "UPstreamWrapping.H" -#include <cinttypes> +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +static inline bool is_basic_dataType(Foam::UPstream::dataTypes id) noexcept +{ + return + ( + int(id) >= int(Foam::UPstream::dataTypes::Basic_begin) + && int(id) < int(Foam::UPstream::dataTypes::Basic_end) + ); +} + +namespace +{ + +using namespace Foam; + +// Local function to print some error information +inline void printErrorNonIntrinsic +( + const char* context, + UPstream::dataTypes dataTypeId +) +{ + FatalError + << "Bad input for " << context << ": likely a programming problem\n" + << " Non-intrinsic data (" << int(dataTypeId) << ")\n" + << Foam::endl; +} + +} // End anonymous namespace + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -#undef Pstream_CommonRoutines -#define Pstream_CommonRoutines(Native, TaggedType) \ - \ -void Foam::UPstream::mpiGather \ -( \ - const Native* sendData, \ - Native* recvData, \ - int count, \ - const label comm \ -) \ -{ \ - PstreamDetail::gather \ - ( \ - sendData, recvData, count, \ - TaggedType, comm \ - ); \ -} \ - \ - \ -void Foam::UPstream::mpiScatter \ -( \ - const Native* sendData, \ - Native* recvData, \ - int count, \ - const label comm \ -) \ -{ \ - PstreamDetail::scatter \ - ( \ - sendData, recvData, count, \ - TaggedType, comm \ - ); \ -} \ - \ - \ -void Foam::UPstream::mpiAllGather \ -( \ - Native* allData, \ - int count, \ - const label comm \ -) \ -{ \ - PstreamDetail::allGather \ - ( \ - allData, count, \ - TaggedType, comm \ - ); \ -} \ - \ -void Foam::UPstream::mpiGatherv \ -( \ - const Native* sendData, \ - int sendCount, \ - \ - Native* recvData, \ - const UList<int>& recvCounts, \ - const UList<int>& recvOffsets, \ - const label comm \ -) \ -{ \ - PstreamDetail::gatherv \ - ( \ - sendData, sendCount, \ - recvData, recvCounts, recvOffsets, \ - TaggedType, comm \ - ); \ -} \ - \ -void Foam::UPstream::mpiScatterv \ -( \ - const Native* sendData, \ - const UList<int>& sendCounts, \ - const UList<int>& sendOffsets, \ - \ - Native* recvData, \ - int recvCount, \ - const label comm \ -) \ -{ \ - PstreamDetail::scatterv \ - ( \ - sendData, sendCounts, sendOffsets, \ - recvData, recvCount, \ - TaggedType, comm \ - ); \ +void Foam::UPstream::mpi_gather +( + const void* sendData, // Type checking done by caller + void* recvData, // Type checking done by caller + int count, + const UPstream::dataTypes dataTypeId, // Proper type passed by caller + + const int communicator, // Index into MPICommunicators_ + UPstream::Request* req +) +{ + MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId); + + if (FOAM_UNLIKELY(UPstream::debug)) + { + Perr<< "[mpi_gather] : " + << " type:" << int(dataTypeId) << " count:" << count + << " comm:" << communicator + << Foam::endl; + } + + { + // Regular gather + + PstreamDetail::gather + ( + sendData, + recvData, + count, + datatype, + communicator, + req + ); + } } -//TDB: Pstream_CommonRoutines(bool, MPI_C_BOOL); -Pstream_CommonRoutines(char, MPI_BYTE); -Pstream_CommonRoutines(int32_t, MPI_INT32_T); -Pstream_CommonRoutines(int64_t, MPI_INT64_T); -Pstream_CommonRoutines(uint32_t, MPI_UINT32_T); -Pstream_CommonRoutines(uint64_t, MPI_UINT64_T); -Pstream_CommonRoutines(float, MPI_FLOAT); -Pstream_CommonRoutines(double, MPI_DOUBLE); +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +void Foam::UPstream::mpi_scatter +( + const void* sendData, // Type checking done by caller + void* recvData, // Type checking done by caller + int count, + const UPstream::dataTypes dataTypeId, // Proper type passed by caller + + const int communicator, // Index into MPICommunicators_ + UPstream::Request* req +) +{ + MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId); + + if (FOAM_UNLIKELY(UPstream::debug)) + { + Perr<< "[mpi_scatter] : " + << " type:" << int(dataTypeId) << " count:" << count + << " comm:" << communicator + << Foam::endl; + } + + { + // Regular scatter + + PstreamDetail::scatter + ( + sendData, + recvData, + count, + datatype, + communicator, + req + ); + } +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +void Foam::UPstream::mpi_allgather +( + void* allData, // Type checking done by caller + int count, + const UPstream::dataTypes dataTypeId, // Proper type passed by caller + + const int communicator, // Index into MPICommunicators_ + UPstream::Request* req +) +{ + MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId); + + if (FOAM_UNLIKELY(UPstream::debug)) + { + Perr<< "[mpi_allgather] : " + << " type:" << int(dataTypeId) << " count:" << count + << " comm:" << communicator + << Foam::endl; + } + + { + // Regular all gather + + PstreamDetail::allGather + ( + allData, + count, + datatype, + communicator, + req + ); + } +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +void Foam::UPstream::mpi_gatherv +( + const void* sendData, + int sendCount, + void* recvData, + const UList<int>& recvCounts, + const UList<int>& recvOffsets, + + const UPstream::dataTypes dataTypeId, // Proper type passed by caller + const int communicator +) +{ + MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId); + + if + ( + FOAM_UNLIKELY + ( + !is_basic_dataType(dataTypeId) + ) + ) + { + FatalErrorInFunction; + printErrorNonIntrinsic("MPI_Gatherv()", dataTypeId); + FatalError << Foam::abort(FatalError); + } + + { + PstreamDetail::gatherv + ( + sendData, sendCount, + recvData, recvCounts, recvOffsets, + datatype, communicator + ); + } +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +void Foam::UPstream::mpi_scatterv +( + const void* sendData, + const UList<int>& sendCounts, + const UList<int>& sendOffsets, + + void* recvData, + int recvCount, + + const UPstream::dataTypes dataTypeId, // Proper type passed by caller + const int communicator +) +{ + MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId); + + if + ( + FOAM_UNLIKELY + ( + !is_basic_dataType(dataTypeId) + ) + ) + { + FatalErrorInFunction; + printErrorNonIntrinsic("MPI_Scatterv()", dataTypeId); + FatalError << Foam::abort(FatalError); + } + + { + PstreamDetail::scatterv + ( + sendData, sendCounts, sendOffsets, + recvData, recvCount, + datatype, communicator + ); + } +} -#undef Pstream_CommonRoutines // ************************************************************************* // diff --git a/src/Pstream/mpi/UPstreamReduce.C b/src/Pstream/mpi/UPstreamReduce.C index d9e96a89ceb13cd211c858a34345ed50bf0cd092..3ade1de388ebd1c44420aac082dc645012ab06cb 100644 --- a/src/Pstream/mpi/UPstreamReduce.C +++ b/src/Pstream/mpi/UPstreamReduce.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2022-2023 OpenCFD Ltd. + Copyright (C) 2022-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -31,261 +31,257 @@ License #include <cinttypes> -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // // Special reductions for bool -void Foam::UPstream::reduceAnd(bool& value, const label comm) +void Foam::UPstream::reduceAnd(bool& value, const int communicator) { - PstreamDetail::allReduce(&value, 1, MPI_C_BOOL, MPI_LAND, comm); + PstreamDetail::allReduce(&value, 1, MPI_C_BOOL, MPI_LAND, communicator); } -void Foam::UPstream::reduceOr(bool& value, const label comm) +void Foam::UPstream::reduceOr(bool& value, const int communicator) { - PstreamDetail::allReduce(&value, 1, MPI_C_BOOL, MPI_LOR, comm); + PstreamDetail::allReduce(&value, 1, MPI_C_BOOL, MPI_LOR, communicator); } void Foam::reduce ( bool& value, - const andOp<bool>&, + Foam::andOp<bool>, const int tag, /* (unused) */ - const label comm + const int communicator ) { - PstreamDetail::allReduce(&value, 1, MPI_C_BOOL, MPI_LAND, comm); + UPstream::reduceAnd(value, communicator); } void Foam::reduce ( bool& value, - const orOp<bool>&, + Foam::orOp<bool>, const int tag, /* (unused) */ - const label comm + const int communicator ) { - PstreamDetail::allReduce(&value, 1, MPI_C_BOOL, MPI_LOR, comm); + UPstream::reduceOr(value, communicator); } +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -// Common reductions - -#undef Pstream_CommonReductions -#define Pstream_CommonReductions(Native, TaggedType) \ - \ -void Foam::reduce \ -( \ - Native values[], \ - const int size, \ - const minOp<Native>&, \ - const int tag, /* (unused) */ \ - const label comm \ -) \ -{ \ - PstreamDetail::allReduce<Native> \ - ( \ - values, size, TaggedType, MPI_MIN, comm \ - ); \ -} \ - \ -void Foam::reduce \ -( \ - Native values[], \ - const int size, \ - const maxOp<Native>&, \ - const int tag, /* (unused) */ \ - const label comm \ -) \ -{ \ - PstreamDetail::allReduce<Native> \ - ( \ - values, size, TaggedType, MPI_MAX, comm \ - ); \ -} \ - \ -void Foam::reduce \ -( \ - Native values[], \ - const int size, \ - const sumOp<Native>&, \ - const int tag, /* (unused) */ \ - const label comm \ -) \ -{ \ - PstreamDetail::allReduce<Native> \ - ( \ - values, size, TaggedType, MPI_SUM, comm \ - ); \ -} \ - \ -void Foam::reduce \ -( \ - Native& value, \ - const minOp<Native>&, \ - const int tag, /* (unused) */ \ - const label comm \ -) \ -{ \ - PstreamDetail::allReduce<Native> \ - ( \ - &value, 1, TaggedType, MPI_MIN, comm \ - ); \ -} \ - \ -void Foam::reduce \ -( \ - Native& value, \ - const maxOp<Native>&, \ - const int tag, /* (unused) */ \ - const label comm \ -) \ -{ \ - PstreamDetail::allReduce<Native> \ - ( \ - &value, 1, TaggedType, MPI_MAX, comm \ - ); \ -} \ - \ -void Foam::reduce \ -( \ - Native& value, \ - const sumOp<Native>&, \ - const int tag, /* (unused) */ \ - const label comm \ -) \ -{ \ - PstreamDetail::allReduce<Native> \ - ( \ - &value, 1, TaggedType, MPI_SUM, comm \ - ); \ +static inline bool is_basic_dataType(Foam::UPstream::dataTypes id) noexcept +{ + return + ( + int(id) >= int(Foam::UPstream::dataTypes::Basic_begin) + && int(id) < int(Foam::UPstream::dataTypes::Basic_end) + ); +} + +static inline bool is_reduce_opCode(Foam::UPstream::opCodes id) noexcept +{ + return + ( + int(id) >= int(Foam::UPstream::opCodes::Basic_begin) + && int(id) < int(Foam::UPstream::opCodes::Basic_end) + ); } -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -// Floating-point reductions - -#undef Pstream_FloatReductions -#define Pstream_FloatReductions(Native, TaggedType) \ - \ -Pstream_CommonReductions(Native, TaggedType); \ - \ -void Foam::reduce \ -( \ - Native values[], \ - const int size, \ - const sumOp<Native>&, \ - const int tag, /* (unused) */ \ - const label comm, \ - UPstream::Request& req \ -) \ -{ \ - PstreamDetail::allReduce<Native> \ - ( \ - values, size, TaggedType, MPI_SUM, comm, &req \ - ); \ -} \ - \ -void Foam::reduce \ -( \ - Native& value, \ - const sumOp<Native>&, \ - const int tag, /* (unused) */ \ - const label comm, \ - UPstream::Request& req \ -) \ -{ \ - PstreamDetail::allReduce<Native> \ - ( \ - &value, 1, TaggedType, MPI_SUM, comm, &req \ - ); \ -} \ - \ -void Foam::sumReduce \ -( \ - Native& value, \ - label& count, \ - const int tag, /* (unused) */ \ - const label comm \ -) \ -{ \ - if (UPstream::is_parallel(comm)) \ - { \ - Native values[2]; \ - values[0] = static_cast<Native>(count); \ - values[1] = value; \ - \ - PstreamDetail::allReduce<Native> \ - ( \ - values, 2, TaggedType, MPI_SUM, comm \ - ); \ - \ - count = static_cast<label>(values[0]); \ - value = values[1]; \ - } \ +namespace +{ + +using namespace Foam; + +// Local function to print some error information +void printErrorMessage +( + const void* values, + const UPstream::dataTypes datatype_id, + const UPstream::opCodes opcode_id +) +{ + FatalError + << "Bad input for reduce(): likely a programming problem\n"; + + if (!is_basic_dataType(datatype_id)) + { + FatalError<< " Non-basic data tyoe (" << int(datatype_id) << ")\n"; + } + + if (!is_reduce_opCode(opcode_id)) + { + FatalError<< " Invalid reduce op (" << int(opcode_id) << ")\n"; + } + + if (values == nullptr) + { + FatalError<< " nullptr for values\n"; + } + FatalError<< Foam::endl; } +} // End anonymous namespace + + +// * * * * * * * * * * Protected Static Member Functions * * * * * * * * * * // -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -// Bitwise reductions - -#undef Pstream_BitwiseReductions -#define Pstream_BitwiseReductions(Native, TaggedType) \ - \ -void Foam::reduce \ -( \ - Native values[], \ - const int size, \ - const bitOrOp<Native>&, \ - const int tag, /* (unused) */ \ - const label comm \ -) \ -{ \ - PstreamDetail::allReduce<Native> \ - ( \ - values, size, TaggedType, MPI_BOR, comm \ - ); \ -} \ - \ -void Foam::reduce \ -( \ - Native& value, \ - const bitOrOp<Native>&, \ - const int tag, /* (unused) */ \ - const label comm \ -) \ -{ \ - PstreamDetail::allReduce<Native> \ - ( \ - &value, 1, TaggedType, MPI_BOR, comm \ - ); \ -} \ - -\ -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -Pstream_CommonReductions(int32_t, MPI_INT32_T); -Pstream_CommonReductions(int64_t, MPI_INT64_T); -Pstream_CommonReductions(uint32_t, MPI_UINT32_T); -Pstream_CommonReductions(uint64_t, MPI_UINT64_T); - -Pstream_FloatReductions(float, MPI_FLOAT); -Pstream_FloatReductions(double, MPI_DOUBLE); - -Pstream_BitwiseReductions(unsigned char, MPI_UNSIGNED_CHAR); -Pstream_BitwiseReductions(unsigned int, MPI_UNSIGNED); - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -#undef Pstream_CommonReductions -#undef Pstream_FloatReductions -#undef Pstream_BitwiseReductions +// The intel-mpi version of MPI_Reduce() does not accept IN_PLACE +// operations (issue #3331) +// Assume the same may be true for ms-mpi +#if defined(I_MPI_VERSION) || defined(MSMPI_VER) +#define Foam_broken_vendor_INPLACE_REDUCE +#else +#undef Foam_broken_vendor_INPLACE_REDUCE +#endif + +void Foam::UPstream::mpi_reduce +( + void* values, // Type checking done by caller + int count, + const UPstream::dataTypes dataTypeId, // Proper type passed by caller + const UPstream::opCodes opCodeId, // Proper code passed by caller + const int communicator, // Index into MPICommunicators_ + UPstream::Request* req +) +{ + MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId); + MPI_Op optype = PstreamGlobals::getOpCode(opCodeId); + + if (!count || !UPstream::is_parallel(communicator)) + { + // Nothing to do - ignore + return; + } + if + ( + FOAM_UNLIKELY + ( + !is_basic_dataType(dataTypeId) + || !is_reduce_opCode(opCodeId) + || (values == nullptr) + ) + ) + { + FatalErrorInFunction; + printErrorMessage(values, dataTypeId, opCodeId); + FatalError << Foam::abort(FatalError); + } + + if (FOAM_UNLIKELY(UPstream::debug)) + { + Perr<< "[mpi_reduce] : " + << " op:" << int(opCodeId) + << " type:" << int(dataTypeId) << " count:" << count + << " comm:" << communicator + << Foam::endl; + } + + // Workaround for broken in-place handling. + // Use a local buffer to send the data from. + + #ifdef Foam_broken_vendor_INPLACE_REDUCE + static std::unique_ptr<char[]> work; + static int work_len(0); + + const int num_bytes = [=](int n) + { + int size = 1; + MPI_Type_size(datatype, &size); + return (size * n); + }(count); + + if (work_len < num_bytes) + { + // Min length to avoid many initial re-allocations + work_len = std::max(256, num_bytes); + work.reset(); + work = std::make_unique<char[]>(work_len); + } + void* sendData = work.get(); + + std::memcpy(sendData, values, num_bytes); + #else + void* sendData(nullptr); + #endif + + + { + // Regular reduce + + PstreamDetail::reduce0 + ( + sendData, + values, + count, + datatype, + optype, + communicator, + req + ); + } +} + + +void Foam::UPstream::mpi_allreduce +( + void* values, // Type checking done by caller + int count, + const UPstream::dataTypes dataTypeId, // Proper type passed by caller + const UPstream::opCodes opCodeId, // Proper code passed by caller + const int communicator, // Index into MPICommunicators_ + UPstream::Request* req +) +{ + MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId); + MPI_Op optype = PstreamGlobals::getOpCode(opCodeId); + + if (!count || !UPstream::is_parallel(communicator)) + { + // Nothing to do - ignore + return; + } + if + ( + FOAM_UNLIKELY + ( + !is_basic_dataType(dataTypeId) + || !is_reduce_opCode(opCodeId) + || (values == nullptr) + ) + ) + { + FatalErrorInFunction; + printErrorMessage(values, dataTypeId, opCodeId); + FatalError << Foam::abort(FatalError); + } + + if (FOAM_UNLIKELY(UPstream::debug)) + { + Perr<< "[mpi_allreduce] : " + << " op:" << int(opCodeId) + << " type:" << int(dataTypeId) << " count:" << count + << " comm:" << communicator + << Foam::endl; + } + + { + // Regular allReduce + + PstreamDetail::allReduce + ( + values, + count, + datatype, + optype, + communicator, + req + ); + } +} // ************************************************************************* // diff --git a/src/Pstream/mpi/UPstreamWindow.C b/src/Pstream/mpi/UPstreamWindow.C index 8bcce43014d910a105350a6baeb094f2a53e23e6..0657c86096aeb036b67160668138b38dd3aaff10 100644 --- a/src/Pstream/mpi/UPstreamWindow.C +++ b/src/Pstream/mpi/UPstreamWindow.C @@ -50,4 +50,29 @@ void Foam::UPstream::Window::reset() noexcept } +int Foam::UPstream::Window::size() const +{ + int val = 0; + + MPI_Win win = PstreamUtils::Cast::to_mpi(*this); + MPI_Group group; + + // Get num of ranks from the group information + if + ( + (MPI_WIN_NULL != win) + && (MPI_SUCCESS == MPI_Win_get_group(win, &group)) + ) + { + if (MPI_SUCCESS != MPI_Group_size(group, &val)) + { + val = 0; + } + MPI_Group_free(&group); + } + + return val; +} + + // ************************************************************************* // diff --git a/src/Pstream/mpi/UPstreamWrapping.H b/src/Pstream/mpi/UPstreamWrapping.H index b98c99f314f2c2a521016c7f4117be46df886f42..2587d840dc2a9de4369b622114e7e3a798fef461 100644 --- a/src/Pstream/mpi/UPstreamWrapping.H +++ b/src/Pstream/mpi/UPstreamWrapping.H @@ -62,6 +62,7 @@ bool broadcast0 template<class Type> void reduce0 ( + const Type* sendData, // Use nullptr for in-place operation Type* values, int count, MPI_Datatype datatype, @@ -70,7 +71,7 @@ void reduce0 UPstream::Request* req = nullptr // Non-null for non-blocking ); -// MPI_Allreduce or MPI_Iallreduce +// MPI_Allreduce or MPI_Iallreduce : in-place operation template<class Type> void allReduce ( diff --git a/src/Pstream/mpi/UPstreamWrapping.txx b/src/Pstream/mpi/UPstreamWrapping.txx index 057c0e6025fe25709699ddcb0d42194fc75cc018..fdcc5d22183b93002567311730ca4fec62560f33 100644 --- a/src/Pstream/mpi/UPstreamWrapping.txx +++ b/src/Pstream/mpi/UPstreamWrapping.txx @@ -74,6 +74,7 @@ bool Foam::PstreamDetail::broadcast0 template<class Type> void Foam::PstreamDetail::reduce0 ( + const Type* sendData, Type* values, int count, MPI_Datatype datatype, @@ -92,6 +93,13 @@ void Foam::PstreamDetail::reduce0 return; } + const void* send_buffer = sendData; + if (sendData == nullptr || (sendData == values)) + { + // Appears to be an in-place request + send_buffer = MPI_IN_PLACE; + } + if (FOAM_UNLIKELY(PstreamGlobals::warnCommunicator(communicator))) { if (immediate) @@ -102,22 +110,12 @@ void Foam::PstreamDetail::reduce0 { Perr<< "** MPI_Reduce (blocking):"; } - if constexpr (std::is_void_v<Type>) + if (sendData == nullptr || (sendData == values)) { - Perr<< count << " values"; - } - else - { - if (count == 1) - { - Perr<< (*values); - } - else - { - Perr<< UList<Type>(values, count); - } + Perr<< " [inplace]"; } - Perr<< " with comm:" << communicator + Perr<< " count:" << count + << " comm:" << communicator << " warnComm:" << UPstream::warnComm << endl; error::printStack(Perr); } @@ -135,7 +133,7 @@ void Foam::PstreamDetail::reduce0 returnCode = MPI_Ireduce ( - MPI_IN_PLACE, // recv is also send + send_buffer, values, count, datatype, @@ -156,7 +154,7 @@ void Foam::PstreamDetail::reduce0 returnCode = MPI_Reduce ( - MPI_IN_PLACE, // recv is also send + send_buffer, values, count, datatype, @@ -174,24 +172,9 @@ void Foam::PstreamDetail::reduce0 FatalErrorInFunction<< "MPI Reduce "; if (immediate) FatalError<< "(non-blocking) "; - FatalError<< "failed for "; - - if constexpr (std::is_void_v<Type>) - { - FatalError<< count << " values"; - } - else - { - if (count == 1) - { - FatalError<< (*values); - } - else - { - FatalError<< UList<Type>(values, count); - } - } - FatalError<< Foam::abort(FatalError); + FatalError + << "failed for count:" << count + << Foam::abort(FatalError); } } @@ -997,7 +980,7 @@ void Foam::PstreamDetail::gather const bool immediate = (req); - if (!UPstream::is_rank(communicator) || !count) + if (!count || !UPstream::is_rank(communicator)) { return; } @@ -1115,7 +1098,7 @@ void Foam::PstreamDetail::scatter const bool immediate = (req); - if (!UPstream::is_rank(communicator) || !count) + if (!count || !UPstream::is_rank(communicator)) { return; } @@ -1243,9 +1226,14 @@ void Foam::PstreamDetail::gatherv } else if (!UPstream::is_parallel(communicator)) { - // recvCounts[0] may be invalid - use sendCount instead - if (sendData && recvData) + if constexpr (std::is_void_v<Type>) { + // Cannot copy data here since we don't know the number of bytes + // - must be done by the caller. + } + else if (sendData && recvData) + { + // recvCounts[0] may be invalid - use sendCount instead std::memmove(recvData, sendData, sendCount*sizeof(Type)); } return; @@ -1385,7 +1373,15 @@ void Foam::PstreamDetail::scatterv } else if (!UPstream::is_parallel(communicator)) { - std::memmove(recvData, sendData, recvCount*sizeof(Type)); + if constexpr (std::is_void_v<Type>) + { + // Cannot copy data here since we don't know the number of bytes + // - must be done by the caller. + } + else if (sendData && recvData) + { + std::memmove(recvData, sendData, recvCount*sizeof(Type)); + } return; } diff --git a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/hexMeshSmootherMotionSolver.C b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/hexMeshSmootherMotionSolver.C index d8964afef6d473e5f2c29f484b4173baebb4c1d1..2b28c6e06d2e1a8b3a723e8594a4e27ae84670fa 100644 --- a/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/hexMeshSmootherMotionSolver.C +++ b/src/dynamicMesh/motionSolvers/displacement/pointSmoothing/hexMeshSmootherMotionSolver.C @@ -464,7 +464,7 @@ Foam::labelList Foam::hexMeshSmootherMotionSolver::countZeroOrPos } } - Pstream::listCombineReduce(n, plusEqOp<label>()); + Pstream::listReduce(n, sumOp<label>()); return n; } diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.C b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.C index 73501db8cf9852d788b938841e9606ffc8214fdb..380bc5080325ee944345c18b0fcac58886465d3e 100644 --- a/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.C +++ b/src/dynamicMesh/polyTopoChange/polyTopoChange/hexRef8/hexRef8.C @@ -440,7 +440,7 @@ Foam::scalar Foam::hexRef8::getLevel0EdgeLength() const // Get the minimum per level over all processors. Note minimum so if // cells are not cubic we use the smallest edge side. - Pstream::listCombineReduce(typEdgeLenSqr, minEqOp<scalar>()); + Pstream::listReduce(typEdgeLenSqr, minOp<scalar>()); if (debug) { @@ -474,7 +474,7 @@ Foam::scalar Foam::hexRef8::getLevel0EdgeLength() const } } - Pstream::listCombineReduce(maxEdgeLenSqr, maxEqOp<scalar>()); + Pstream::listReduce(maxEdgeLenSqr, maxOp<scalar>()); if (debug) { diff --git a/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubset.C b/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubset.C index 839d102a171ffd708b3cd0dd51084d0494c50df8..2c5e8ec4197886b4d896801ccb2713792e53f0b6 100644 --- a/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubset.C +++ b/src/finiteVolume/fvMesh/fvMeshSubset/fvMeshSubset.C @@ -1108,7 +1108,7 @@ void Foam::fvMeshSubset::reset // Get patch sizes (up to nextPatchID). // Note that up to nextPatchID the globalPatchMap is an identity so // no need to index through that. - Pstream::listCombineReduce(globalPatchSizes, plusEqOp<label>()); + Pstream::listReduce(globalPatchSizes, sumOp<label>()); // Now all processors have all the patchnames. // Decide: if all processors have the same patch names and size is zero diff --git a/src/functionObjects/field/Curle/Curle.C b/src/functionObjects/field/Curle/Curle.C index 6b53be072347faaa564cdd1971bc2ffd2f709cca..0ee78d920037d28ef35e47fd4c2dc9a1893945c9 100644 --- a/src/functionObjects/field/Curle/Curle.C +++ b/src/functionObjects/field/Curle/Curle.C @@ -222,7 +222,7 @@ bool Foam::functionObjects::Curle::execute() pDash /= 4*mathematical::pi; - Pstream::listCombineReduce(pDash, plusEqOp<scalar>()); + Pstream::listReduce(pDash, sumOp<scalar>()); if (surfaceWriterPtr_) { diff --git a/src/functionObjects/field/columnAverage/columnAverageTemplates.C b/src/functionObjects/field/columnAverage/columnAverageTemplates.C index 2bba02a3dc32112295fbe26ae61e47ce7bf29dae..aa7cc893e9b368f5acbb9f4071bbad245be21df0 100644 --- a/src/functionObjects/field/columnAverage/columnAverageTemplates.C +++ b/src/functionObjects/field/columnAverage/columnAverageTemplates.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018-2024 OpenCFD Ltd. + Copyright (C) 2018-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -88,8 +88,8 @@ bool Foam::functionObjects::columnAverage::columnAverageField } // Global sum - Pstream::listCombineReduce(regionField, plusEqOp<Type>()); - Pstream::listCombineReduce(regionCount, plusEqOp<label>()); + Pstream::listReduce(regionField, sumOp<Type>()); + Pstream::listReduce(regionCount, sumOp<label>()); forAll(regionField, regioni) { diff --git a/src/functionObjects/field/extractEulerianParticles/extractEulerianParticles/extractEulerianParticles.C b/src/functionObjects/field/extractEulerianParticles/extractEulerianParticles/extractEulerianParticles.C index c8e2c76cb505851c14def8c44476d0cfa89cf543..bba3209e6397eb5c1afff010093b4fb8e4a8b541 100644 --- a/src/functionObjects/field/extractEulerianParticles/extractEulerianParticles/extractEulerianParticles.C +++ b/src/functionObjects/field/extractEulerianParticles/extractEulerianParticles/extractEulerianParticles.C @@ -329,7 +329,7 @@ void Foam::functionObjects::extractEulerianParticles::calculateAddressing // Create map from new regions to slots in particles list // - filter through new-to-new addressing to identify new particles - Pstream::listCombineReduce(newToNewRegion, maxEqOp<label>()); + Pstream::listReduce(newToNewRegion, maxOp<label>()); label nParticle = -1; labelHashSet newRegions; @@ -348,7 +348,7 @@ void Foam::functionObjects::extractEulerianParticles::calculateAddressing // Accumulate old region data or create a new particle if there is no // mapping from the old-to-new region - Pstream::listCombineReduce(oldToNewRegion, maxEqOp<label>()); + Pstream::listReduce(oldToNewRegion, maxOp<label>()); List<eulerianParticle> newParticles(newRegionToParticleMap.size()); forAll(oldToNewRegion, oldRegioni) diff --git a/src/functionObjects/field/histogram/histogramModels/equalBinWidth/equalBinWidth.C b/src/functionObjects/field/histogram/histogramModels/equalBinWidth/equalBinWidth.C index 790e6213c540f37518df43040f3495b52aeb0642..e8d40cb54e47dc277562b9eb04fde2415837df66 100644 --- a/src/functionObjects/field/histogram/histogramModels/equalBinWidth/equalBinWidth.C +++ b/src/functionObjects/field/histogram/histogramModels/equalBinWidth/equalBinWidth.C @@ -155,8 +155,8 @@ bool Foam::histogramModels::equalBinWidth::write(const bool log) dataCount[bini]++; } } - Pstream::listCombineGather(dataNormalised, plusEqOp<scalar>()); - Pstream::listCombineGather(dataCount, plusEqOp<label>()); + Pstream::listGather(dataNormalised, sumOp<scalar>()); + Pstream::listGather(dataCount, sumOp<label>()); // Write histogram data diff --git a/src/functionObjects/field/histogram/histogramModels/unequalBinWidth/unequalBinWidth.C b/src/functionObjects/field/histogram/histogramModels/unequalBinWidth/unequalBinWidth.C index 658c54bd135806c335160d08724ae39ccb5f02f6..aec3f84f0b1e65d1fe9a78a6c23713ff6a85f364 100644 --- a/src/functionObjects/field/histogram/histogramModels/unequalBinWidth/unequalBinWidth.C +++ b/src/functionObjects/field/histogram/histogramModels/unequalBinWidth/unequalBinWidth.C @@ -129,8 +129,8 @@ bool Foam::histogramModels::unequalBinWidth::write(const bool log) } } } - Pstream::listCombineGather(dataNormalised, plusEqOp<scalar>()); - Pstream::listCombineGather(dataCount, plusEqOp<label>()); + Pstream::listGather(dataNormalised, sumOp<scalar>()); + Pstream::listGather(dataCount, sumOp<label>()); // Write histogram data diff --git a/src/functionObjects/forces/propellerInfo/propellerInfo.C b/src/functionObjects/forces/propellerInfo/propellerInfo.C index b080d929a36f502667bb78ac1fb0ffd9533d562f..18a47b728a05ce1465c4c978a8555e225fedf588 100644 --- a/src/functionObjects/forces/propellerInfo/propellerInfo.C +++ b/src/functionObjects/forces/propellerInfo/propellerInfo.C @@ -791,7 +791,7 @@ Foam::tmp<Foam::Field<Type>> Foam::functionObjects::propellerInfo::interpolate } } - Pstream::listCombineReduce(field, maxEqOp<Type>()); + Pstream::listReduce(field, maxOp<Type>()); return tfield; } diff --git a/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleZoneInfo/ParticleZoneInfo.C b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleZoneInfo/ParticleZoneInfo.C index 522e94c35bcd0eccaaeef03ab4009b4f68ea6b78..dcd6e8effecd5d2a83818bb5176551c43c3d782c 100644 --- a/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleZoneInfo/ParticleZoneInfo.C +++ b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleZoneInfo/ParticleZoneInfo.C @@ -365,7 +365,7 @@ void Foam::ParticleZoneInfo<CloudType>::write() { // Find number of particles per proc labelList allMaxIDs(maxIDs_); - Pstream::listCombineReduce(allMaxIDs, maxEqOp<label>()); + Pstream::listReduce(allMaxIDs, maxOp<label>()); // Combine into single list label n = returnReduce(data_.size(), sumOp<label>()); diff --git a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/CellZoneInjection/CellZoneInjection.C b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/CellZoneInjection/CellZoneInjection.C index 5ee1a9e6ff77be4ac6064cb19b2ceb9b71bb9745..5e2ed632cc9c8bbb9f3eaf81a08ca3fc31798e1b 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/CellZoneInjection/CellZoneInjection.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/InjectionModel/CellZoneInjection/CellZoneInjection.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2015-2023 OpenCFD Ltd. + Copyright (C) 2015-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -121,7 +121,7 @@ void Foam::CellZoneInjection<CloudType>::setPositions globalPositions.range(myProci) ) = positions; - Pstream::listCombineReduce(allPositions, minEqOp<point>()); + Pstream::listReduce(allPositions, minOp<point>()); // Gather local cell tet and tet-point Ids, but leave non-local ids set -1 SubList<label> diff --git a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/LocalInteraction/LocalInteraction.C b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/LocalInteraction/LocalInteraction.C index 440103171a753c35acd36ce7845b15a4c91adcd4..5a52be2cb19339ec49c536adc68103680278c2fb 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/LocalInteraction/LocalInteraction.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/LocalInteraction/LocalInteraction.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2015-2020 OpenCFD Ltd. + Copyright (C) 2015-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -372,28 +372,28 @@ void Foam::LocalInteraction<CloudType>::info() labelListList npe(nEscape_); forAll(npe, i) { - Pstream::listCombineGather(npe[i], plusEqOp<label>()); + Pstream::listGather(npe[i], sumOp<label>()); npe[i] = npe[i] + npe0[i]; } scalarListList mpe(massEscape_); forAll(mpe, i) { - Pstream::listCombineGather(mpe[i], plusEqOp<scalar>()); + Pstream::listGather(mpe[i], sumOp<scalar>()); mpe[i] = mpe[i] + mpe0[i]; } labelListList nps(nStick_); forAll(nps, i) { - Pstream::listCombineGather(nps[i], plusEqOp<label>()); + Pstream::listGather(nps[i], sumOp<label>()); nps[i] = nps[i] + nps0[i]; } scalarListList mps(massStick_); forAll(nps, i) { - Pstream::listCombineGather(mps[i], plusEqOp<scalar>()); + Pstream::listGather(mps[i], sumOp<scalar>()); mps[i] = mps[i] + mps0[i]; } diff --git a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/RecycleInteraction/RecycleInteraction.C b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/RecycleInteraction/RecycleInteraction.C index 78501a00a22a731c7101135fe8e9c966d37166e6..e185e16034a2c72861165281aea32cb4c142da09 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/RecycleInteraction/RecycleInteraction.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/RecycleInteraction/RecycleInteraction.C @@ -379,28 +379,28 @@ void Foam::RecycleInteraction<CloudType>::info() forAll(npr, i) { - Pstream::listCombineGather(npr[i], plusEqOp<label>()); + Pstream::listGather(npr[i], sumOp<label>()); npr[i] = npr[i] + npr0[i]; } scalarListList mpr(massRemoved_); forAll(mpr, i) { - Pstream::listCombineGather(mpr[i], plusEqOp<scalar>()); + Pstream::listGather(mpr[i], sumOp<scalar>()); mpr[i] = mpr[i] + mpr0[i]; } labelListList npi(nInjected_); forAll(npi, i) { - Pstream::listCombineGather(npi[i], plusEqOp<label>()); + Pstream::listGather(npi[i], sumOp<label>()); npi[i] = npi[i] + npi0[i]; } scalarListList mpi(massInjected_); forAll(mpi, i) { - Pstream::listCombineGather(mpi[i], plusEqOp<scalar>()); + Pstream::listGather(mpi[i], sumOp<scalar>()); mpi[i] = mpi[i] + mpi0[i]; } diff --git a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/StandardWallInteraction/StandardWallInteraction.C b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/StandardWallInteraction/StandardWallInteraction.C index 5f9f1033a7e523860dee5154eab2180613bc3b00..00ca30c613cd93d744124b98f43fe51c566596f3 100644 --- a/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/StandardWallInteraction/StandardWallInteraction.C +++ b/src/lagrangian/intermediate/submodels/Kinematic/PatchInteractionModel/StandardWallInteraction/StandardWallInteraction.C @@ -285,28 +285,28 @@ void Foam::StandardWallInteraction<CloudType>::info() forAll(npe, i) { - Pstream::listCombineGather(npe[i], plusEqOp<label>()); + Pstream::listGather(npe[i], sumOp<label>()); npe[i] = npe[i] + npe0[i]; } scalarListList mpe(massEscape_); forAll(mpe, i) { - Pstream::listCombineGather(mpe[i], plusEqOp<scalar>()); + Pstream::listGather(mpe[i], sumOp<scalar>()); mpe[i] = mpe[i] + mpe0[i]; } labelListList nps(nStick_); forAll(nps, i) { - Pstream::listCombineGather(nps[i], plusEqOp<label>()); + Pstream::listGather(nps[i], sumOp<label>()); nps[i] = nps[i] + nps0[i]; } scalarListList mps(massStick_); forAll(nps, i) { - Pstream::listCombineGather(mps[i], plusEqOp<scalar>()); + Pstream::listGather(mps[i], sumOp<scalar>()); mps[i] = mps[i] + mps0[i]; } diff --git a/src/lumpedPointMotion/movement/lumpedPointMovement.C b/src/lumpedPointMotion/movement/lumpedPointMovement.C index 524e2be769fd92fd4f754f9f23c95aa6ad2f1f15..f31f4dc907e52a191a1406ecc53770f8cff4097b 100644 --- a/src/lumpedPointMotion/movement/lumpedPointMovement.C +++ b/src/lumpedPointMotion/movement/lumpedPointMovement.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2024 OpenCFD Ltd. + Copyright (C) 2016-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -878,7 +878,7 @@ Foam::List<Foam::scalar> Foam::lumpedPointMovement::areas } } - Pstream::listCombineReduce(zoneAreas, plusEqOp<scalar>()); + Pstream::listReduce(zoneAreas, sumOp<scalar>()); return zoneAreas; } @@ -1006,8 +1006,8 @@ bool Foam::lumpedPointMovement::forcesAndMoments Info<<"No pressure field" << endl; } - Pstream::listCombineReduce(forces, plusEqOp<vector>()); - Pstream::listCombineReduce(moments, plusEqOp<vector>()); + Pstream::listReduce(forces, sumOp<vector>()); + Pstream::listReduce(moments, sumOp<vector>()); return true; } diff --git a/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.C b/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.C index ed4e8cc9679a3023c0537c782d62715cebe5f83f..5e3bafccad8cc3d94cf57e1ad4800c61abec6ca6 100644 --- a/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.C +++ b/src/mesh/snappyHexMesh/meshRefinement/meshRefinement.C @@ -2050,7 +2050,7 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::meshRefinement::balance labelList nProcCells(distributor.countCells(distribution)); Pout<< "Wanted distribution:" << nProcCells << endl; - Pstream::listCombineReduce(nProcCells, plusEqOp<label>()); + Pstream::listReduce(nProcCells, sumOp<label>()); Pout<< "Wanted resulting decomposition:" << endl; forAll(nProcCells, proci) @@ -3611,7 +3611,7 @@ const nCells[cellLevel[celli]]++; } - Pstream::listCombineGather(nCells, plusEqOp<label>()); + Pstream::listGather(nCells, sumOp<label>()); /// Pstream::broadcast(nCells); if (Pstream::master()) diff --git a/src/mesh/snappyHexMesh/meshRefinement/meshRefinementBaffles.C b/src/mesh/snappyHexMesh/meshRefinement/meshRefinementBaffles.C index 3afa51b1e3741b43694666cd956d65a883a4ecae..2c92d2f05910370e8341348adc6cafca2b9a06eb 100644 --- a/src/mesh/snappyHexMesh/meshRefinement/meshRefinementBaffles.C +++ b/src/mesh/snappyHexMesh/meshRefinement/meshRefinementBaffles.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2014 OpenFOAM Foundation - Copyright (C) 2015-2024 OpenCFD Ltd. + Copyright (C) 2015-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -867,7 +867,7 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::createZoneBaffles if (nTotalBaffles > 0) { - Pstream::listCombineReduce(nBaffles, plusEqOp<label>()); + Pstream::listReduce(nBaffles, sumOp<label>()); Info<< nl << setf(ios_base::left) @@ -2001,7 +2001,7 @@ void Foam::meshRefinement::findCellZoneTopo // - region numbers are identical on all processors // - keepRegion is identical ,, // - cellZones are identical ,, - Pstream::listCombineReduce(regionToCellZone, maxEqOp<label>()); + Pstream::listReduce(regionToCellZone, maxOp<label>()); // Find the region containing the keepPoint @@ -2051,7 +2051,7 @@ void Foam::meshRefinement::findCellZoneTopo // - cellZones are identical ,, // This done at top of loop to account for geometric matching // not being synchronised. - Pstream::listCombineReduce(regionToCellZone, maxEqOp<label>()); + Pstream::listReduce(regionToCellZone, maxOp<label>()); bool changed = false; diff --git a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.C b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.C index bdb55c6faf16afb367b58550a65a7741606c9d9c..6381b3733c698bb18ac097652c3886d7db959ec1 100644 --- a/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.C +++ b/src/mesh/snappyHexMesh/snappyHexMeshDriver/snappyRefineDriver.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation - Copyright (C) 2015-2024 OpenCFD Ltd. + Copyright (C) 2015-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -3403,9 +3403,9 @@ void Foam::snappyRefineDriver::deleteSmallRegions nCellsPerRegion[regioni]++; nCellsPerZone[zonei]++; } - Pstream::listCombineReduce(nCellsPerRegion, plusEqOp<label>()); - Pstream::listCombineReduce(regionToZone, maxEqOp<label>()); - Pstream::listCombineReduce(nCellsPerZone, plusEqOp<label>()); + Pstream::listReduce(nCellsPerRegion, sumOp<label>()); + Pstream::listReduce(regionToZone, maxOp<label>()); + Pstream::listReduce(nCellsPerZone, sumOp<label>()); // Mark small regions. Note that all processors have the same information diff --git a/src/meshTools/topoSet/faceZoneSources/planeToFaceZone/planeToFaceZone.C b/src/meshTools/topoSet/faceZoneSources/planeToFaceZone/planeToFaceZone.C index 273cbfd8acc5bc6c9cda3fd71e77209440d5f7ad..e9132b3e5ae1beb325cdc23d1a84d7ccb9b8f31e 100644 --- a/src/meshTools/topoSet/faceZoneSources/planeToFaceZone/planeToFaceZone.C +++ b/src/meshTools/topoSet/faceZoneSources/planeToFaceZone/planeToFaceZone.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2020 OpenFOAM Foundation - Copyright (C) 2020-2022 OpenCFD Ltd. + Copyright (C) 2020-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -258,7 +258,7 @@ void Foam::planeToFaceZone::combine(faceZoneSet& fzSet, const bool add) const { ++ regionNFaces[regioni]; } - Pstream::listCombineReduce(regionNFaces, plusEqOp<label>()); + Pstream::listReduce(regionNFaces, sumOp<label>()); Info<< " Found " << nRegions << " contiguous regions with " << regionNFaces << " faces" << endl; @@ -281,8 +281,8 @@ void Foam::planeToFaceZone::combine(faceZoneSet& fzSet, const bool add) const regionWeights[regioni] += w; regionCentres[regioni] += w*c; } - Pstream::listCombineGather(regionWeights, plusEqOp<scalar>()); - Pstream::listCombineGather(regionCentres, plusEqOp<point>()); + Pstream::listGather(regionWeights, sumOp<scalar>()); + Pstream::listGather(regionCentres, sumOp<point>()); if (Pstream::master()) { diff --git a/src/optimisation/adjointOptimisation/adjoint/optimisation/updateMethod/MMA/MMA.C b/src/optimisation/adjointOptimisation/adjoint/optimisation/updateMethod/MMA/MMA.C index 4c29943d2d3c7d9712714a7871ecbea187e81800..2777f8d42579e18a1366c630236596f2e7adbe3a 100644 --- a/src/optimisation/adjointOptimisation/adjoint/optimisation/updateMethod/MMA/MMA.C +++ b/src/optimisation/adjointOptimisation/adjoint/optimisation/updateMethod/MMA/MMA.C @@ -597,7 +597,7 @@ void Foam::MMA::computeNewtonDirection() if (globalSum_) { reduce(lhs, sumOp<scalarSquareMatrix>()); - Pstream::listCombineAllGather(rhs, plusEqOp<scalar>()); + Pstream::listReduce(rhs, sumOp<scalar>()); } // Add remaining parts from deltaLamdaYTilda and the deltaZ eqn diff --git a/src/optimisation/adjointOptimisation/adjoint/parameterization/NURBS/NURBS3DVolume/NURBS3DVolume/NURBS3DVolume.C b/src/optimisation/adjointOptimisation/adjoint/parameterization/NURBS/NURBS3DVolume/NURBS3DVolume/NURBS3DVolume.C index e467948c4a63f46a6787106ec709e87da6861590..052396e975aacb98055ad7e4ade783207d3d96e2 100644 --- a/src/optimisation/adjointOptimisation/adjoint/parameterization/NURBS/NURBS3DVolume/NURBS3DVolume/NURBS3DVolume.C +++ b/src/optimisation/adjointOptimisation/adjoint/parameterization/NURBS/NURBS3DVolume/NURBS3DVolume/NURBS3DVolume.C @@ -1181,7 +1181,7 @@ Foam::vectorField Foam::NURBS3DVolume::computeControlPointSensitivities } // Sum contributions from all processors - Pstream::listCombineReduce(controlPointDerivs, plusEqOp<vector>()); + Pstream::listReduce(controlPointDerivs, sumOp<vector>()); return controlPointDerivs; } @@ -1266,7 +1266,7 @@ Foam::vectorField Foam::NURBS3DVolume::computeControlPointSensitivities } } // Sum contributions from all processors - Pstream::listCombineReduce(controlPointDerivs, plusEqOp<vector>()); + Pstream::listReduce(controlPointDerivs, sumOp<vector>()); return controlPointDerivs; } diff --git a/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.C b/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.C index fd04966eff9905c5ee35652e41f1593012adc9d1..602d31b07523501704673f08e2961ce73cf5cf57 100644 --- a/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.C +++ b/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2014-2023 OpenCFD Ltd. + Copyright (C) 2014-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -227,7 +227,7 @@ void Foam::cellCellStencils::cellVolumeWeight::findHoles { // Synchronise region status on processors // (could instead swap status through processor patches) - Pstream::listCombineReduce(regionType, maxEqOp<label>()); + Pstream::listReduce(regionType, maxOp<label>()); // Communicate region status through interpolative cells labelList cellRegionType(labelUIndList(regionType, cellRegion)); @@ -602,7 +602,7 @@ bool Foam::cellCellStencils::cellVolumeWeight::update() { nCellsPerZone[zoneID[cellI]]++; } - Pstream::listCombineReduce(nCellsPerZone, plusEqOp<label>()); + Pstream::listReduce(nCellsPerZone, sumOp<label>()); Info<< typeName << " : detected " << nZones << " mesh regions" << nl << endl; diff --git a/src/overset/cellCellStencil/inverseDistance/inverseDistanceCellCellStencil.C b/src/overset/cellCellStencil/inverseDistance/inverseDistanceCellCellStencil.C index f606f5bdd440b046afaa3ea44e462809e7e0db25..c09703ec5478dacba0ff170a5d955efa485f37f0 100644 --- a/src/overset/cellCellStencil/inverseDistance/inverseDistanceCellCellStencil.C +++ b/src/overset/cellCellStencil/inverseDistance/inverseDistanceCellCellStencil.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2017-2023 OpenCFD Ltd. + Copyright (C) 2017-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -1107,7 +1107,7 @@ void Foam::cellCellStencils::inverseDistance::findHoles { // Synchronise region status on processors // (could instead swap status through processor patches) - Pstream::listCombineReduce(regionType, maxEqOp<label>()); + Pstream::listReduce(regionType, maxOp<label>()); DebugInfo<< FUNCTION_NAME << " : Gathered region type" << endl; @@ -1801,7 +1801,7 @@ bool Foam::cellCellStencils::inverseDistance::update() { nCellsPerZone[zoneID[cellI]]++; } - Pstream::listCombineReduce(nCellsPerZone, plusEqOp<label>()); + Pstream::listReduce(nCellsPerZone, sumOp<label>()); const boundBox& allBb = mesh_.bounds(); diff --git a/src/overset/cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.C b/src/overset/cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.C index 73d421c58f5d03578a4e1f5578b85adf1f65ae44..07f3c25436206b5cef9da23c030200f215a306a7 100644 --- a/src/overset/cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.C +++ b/src/overset/cellCellStencil/trackingInverseDistance/trackingInverseDistanceCellCellStencil.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2017-2023 OpenCFD Ltd. + Copyright (C) 2017-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -519,7 +519,7 @@ Foam::cellCellStencils::trackingInverseDistance::trackingInverseDistance { nCellsPerZone[zoneID[celli]]++; } - Pstream::listCombineReduce(nCellsPerZone, plusEqOp<label>()); + Pstream::listReduce(nCellsPerZone, sumOp<label>()); meshParts_.setSize(nZones); forAll(meshParts_, zonei) diff --git a/src/overset/regionsToCell/findRefCells.C b/src/overset/regionsToCell/findRefCells.C index 0704f355ba093f907750dbb1099314a6bf8f8d7e..fc5f942847b979a68802f19579ac437a4e51c8f0 100644 --- a/src/overset/regionsToCell/findRefCells.C +++ b/src/overset/regionsToCell/findRefCells.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016 OpenCFD Ltd. + Copyright (C) 2016,2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -188,7 +188,7 @@ void Foam::setRefCells } } - Pstream::listCombineReduce(hasRef, plusEqOp<label>()); + Pstream::listReduce(hasRef, sumOp<label>()); forAll(hasRef, regionI) { diff --git a/src/parallel/decompose/decompositionMethods/multiLevelDecomp/multiLevelDecomp.C b/src/parallel/decompose/decompositionMethods/multiLevelDecomp/multiLevelDecomp.C index b91df7c6d69ee78770603c95ae7ef8d540be51d5..f1fa4f415cb8192db1e1d9acfd88316d1b22d4ae 100644 --- a/src/parallel/decompose/decompositionMethods/multiLevelDecomp/multiLevelDecomp.C +++ b/src/parallel/decompose/decompositionMethods/multiLevelDecomp/multiLevelDecomp.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2017-2024 OpenCFD Ltd. + Copyright (C) 2017-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -420,8 +420,8 @@ void Foam::multiLevelDecomp::decompose ); label nPoints = returnReduce(domainPoints.size(), sumOp<label>()); + Pstream::listReduce(nOutsideConnections, sumOp<label>()); - Pstream::listCombineReduce(nOutsideConnections, plusEqOp<label>()); label nPatches = 0; label nFaces = 0; for (const label nConnect : nOutsideConnections) @@ -528,11 +528,7 @@ void Foam::multiLevelDecomp::decompose } reduce(nPoints, sumOp<label>()); - Pstream::listCombineReduce - ( - nOutsideConnections, - plusEqOp<label>() - ); + Pstream::listReduce(nOutsideConnections, sumOp<label>()); label nPatches = 0; label nFaces = 0; diff --git a/src/regionModels/regionModel/singleLayerRegion/singleLayerRegion.C b/src/regionModels/regionModel/singleLayerRegion/singleLayerRegion.C index 94f659840043eccb87125cc83866e4528807e5d9..207d1c0a486ce4c3ed3b7476ddd0a6e067dd11e0 100644 --- a/src/regionModels/regionModel/singleLayerRegion/singleLayerRegion.C +++ b/src/regionModels/regionModel/singleLayerRegion/singleLayerRegion.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2020 OpenCFD Ltd. + Copyright (C) 2020-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -144,7 +144,7 @@ void Foam::regionModels::singleLayerRegion::initialise() } } - Pstream::listCombineReduce(passivePatchIDs_, maxEqOp<label>()); + Pstream::listReduce(passivePatchIDs_, maxOp<label>()); magSf.field() = 0.5*(magSf + passiveMagSf); magSf.correctBoundaryConditions(); diff --git a/src/sampling/sampledSet/cloud/cloudSet.C b/src/sampling/sampledSet/cloud/cloudSet.C index 42045d473ce83c5fbf58c4eea4ab914407c21748..3447facc9b8ae662246223d60d971ba1b54f0d2f 100644 --- a/src/sampling/sampledSet/cloud/cloudSet.C +++ b/src/sampling/sampledSet/cloud/cloudSet.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016 OpenCFD Ltd. + Copyright (C) 2016-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -84,8 +84,8 @@ void Foam::cloudSet::calcSamples minFoundProc[i] = foundProc[i]; } } - Pstream::listCombineReduce(minFoundProc, minEqOp<label>()); - Pstream::listCombineReduce(maxFoundProc, maxEqOp<label>()); + Pstream::listReduce(minFoundProc, minOp<label>()); + Pstream::listReduce(maxFoundProc, maxOp<label>()); DynamicField<point> missingPoints(sampleCoords_.size()); diff --git a/src/sampling/surface/distanceSurface/distanceSurfaceFilter.C b/src/sampling/surface/distanceSurface/distanceSurfaceFilter.C index 58d3892748a161150d5688f935812ec07932b034..739a802f4eea684d653be62997343d96fd0ce63c 100644 --- a/src/sampling/surface/distanceSurface/distanceSurfaceFilter.C +++ b/src/sampling/surface/distanceSurface/distanceSurfaceFilter.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2020-2022 OpenCFD Ltd. + Copyright (C) 2020-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -142,8 +142,8 @@ void Foam::distanceSurface::filterKeepLargestRegion } } - // Sum totals from all processors - Pstream::listCombineGather(nCutsPerRegion, plusEqOp<label>()); + // Sum totals from all processors (onto the master) + Pstream::listGather(nCutsPerRegion, sumOp<label>()); // Define which regions to keep @@ -242,8 +242,8 @@ void Foam::distanceSurface::filterKeepNearestRegions } } - // Sum totals from all processors - Pstream::listCombineGather(nCutsPerRegion, plusEqOp<label>()); + // Sum totals from all processors (onto the master) + Pstream::listGather(nCutsPerRegion, sumOp<label>()); // Get nearest Pstream::listCombineGather(nearest, minFirstEqOp<scalar>()); @@ -355,8 +355,8 @@ void Foam::distanceSurface::filterRegionProximity areaRegion[regioni] += (faceArea); } - Pstream::listCombineGather(distRegion, plusEqOp<scalar>()); - Pstream::listCombineGather(areaRegion, plusEqOp<scalar>()); + Pstream::listGather(distRegion, sumOp<scalar>()); + Pstream::listGather(areaRegion, sumOp<scalar>()); if (Pstream::master()) { diff --git a/src/sampling/surface/isoSurface/isoSurfacePoint.C b/src/sampling/surface/isoSurface/isoSurfacePoint.C index 020a0465a2b266ffb00dc90a59f97238d7947646..b450c9b0f51405c4042afb7bb3391d60cffc2d4e 100644 --- a/src/sampling/surface/isoSurface/isoSurfacePoint.C +++ b/src/sampling/surface/isoSurface/isoSurfacePoint.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2017 OpenFOAM Foundation - Copyright (C) 2015-2024 OpenCFD Ltd. + Copyright (C) 2015-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -256,7 +256,7 @@ void Foam::isoSurfacePoint::syncUnseparatedPoints } // Globally consistent - Pstream::listCombineReduce(sharedPts, minEqOp<point>()); + Pstream::listReduce(sharedPts, minOp<point>()); // Now we will all have the same information. Merge it back with // my local information. diff --git a/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceReflecting/faceReflecting.C b/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceReflecting/faceReflecting.C index 32fa503e548ca5469a3caa62b63391b94d846513..53236148ec1ef28d3bea2816a88dacedf0d5614a 100644 --- a/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceReflecting/faceReflecting.C +++ b/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceReflecting/faceReflecting.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018-2022 OpenCFD Ltd. + Copyright (C) 2018-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -327,7 +327,7 @@ void Foam::faceReflecting::calculate() // Distribute ray indexes to all proc's // Make sure all the processors have the same information - Pstream::listCombineReduce(refDisDirsIndex, maxEqOp<label>()); + Pstream::listReduce(refDisDirsIndex, maxOp<label>()); Pstream::mapCombineReduce(refFacesDirIndex, minEqOp<label>()); const scalar maxBounding = diff --git a/src/thermophysicalModels/radiation/radiationModels/viewFactor/viewFactor.C b/src/thermophysicalModels/radiation/radiationModels/viewFactor/viewFactor.C index d434b37a90ffe0efa8dc17d8aaacd1b625a4c598..79267e4c80cbb58f95b0364df79a38b0c91521d5 100644 --- a/src/thermophysicalModels/radiation/radiationModels/viewFactor/viewFactor.C +++ b/src/thermophysicalModels/radiation/radiationModels/viewFactor/viewFactor.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016-2022 OpenCFD Ltd. + Copyright (C) 2016-2025 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -969,9 +969,9 @@ void Foam::radiation::viewFactor::calculate() qrExt[compactGlobalIds[i]] = compactCoarseHo[i]; } - Pstream::listCombineReduce(T4, maxEqOp<scalar>()); - Pstream::listCombineReduce(E, maxEqOp<scalar>()); - Pstream::listCombineReduce(qrExt, maxEqOp<scalar>()); + Pstream::listReduce(T4, maxOp<scalar>()); + Pstream::listReduce(E, maxOp<scalar>()); + Pstream::listReduce(qrExt, maxOp<scalar>()); if (Pstream::master()) {