Compare commits

..

69 Commits

Author SHA1 Message Date
256dafeea5 ENH: fvMatrix: adding setValues for patch
Speedup in offloading
2025-03-05 09:11:47 +00:00
56c52fd69e COMP: fix up merg e 2025-02-27 12:04:58 +00:00
34c933c1ce ENH: AMIInterpolation: use local communicator
- allocate communicator with only those ranks that have
patch faces
- use this communicator everywhere
- communicator preserved during mesh motion
2025-02-27 12:04:58 +00:00
f276016896 SUBMODULE: runTime postProcessing updated for change in minMaxOp 2025-02-27 12:48:34 +01:00
e3703c7626 Merge branch 'pstream-types' into 'develop'
add compile-time type system for MPI data/ops

See merge request Development/openfoam!729
2025-02-25 14:51:21 +00:00
dccdb263e8 ENH: add UPstreamTraits support to map data types and opcodes
The front-end traits:

- 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.

- UPstream_opType trait:
  Provides a mapping of OpenFOAM ops to their MPI equivalent.
  The \c opcode_id is the corresponding internal representation.

The lower-level traits (not normally used within coding)

- 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

- UPstream_alias_dataType trait:
  Provides mapping for <int/long/long long,...> to the fundamental 32/64
  integrals, since <int/long/long long,...> may not otherwise directly map
  on all systems.

NOTE: can use the updates Test-machine-sizes test application to
determine if all data types and aliases are properly defined on
different systems
2025-02-25 10:09:38 +01:00
bf60a124ab ENH: add mapping for fundamental and OpenFOAM types -> MPI data types
- this will allow send/recv/broadcast of various data types directly
  without reinterpreting as bytes. No performance benefit, but makes
  programming more flexible. In addition to the normal MPI types, also
  provide some convenient groupings such as double[3], double[9] etc.

- the additional user-defined data types are created on the start of
  MPI and removed before shutdown
2025-02-25 09:52:12 +01:00
c448ea2a11 ENH: add simple handling for point-to-point barriers
- provides an additional means of process synchronization
2025-02-25 09:44:44 +01:00
d41c644a49 Merge branch 'pstream-cleanups' into 'develop'
various cleanup and add support for non-worldComm reduction of DimensionedField, GeometricField

See merge request Development/openfoam!728
2025-02-24 12:38:40 +00:00
d2dfd115be ENH: provide isolated "*_algorithm" versions of Pstream gather routines
- enables better selection of linear vs tree and improves future reuse.

ENH: optimize listReduce/listCombineReduce for single-value lists
2025-02-24 09:06:21 +01:00
8f3d29c1b7 ENH: retain linear vs tree state in commsStructList
- previously there were two places that used nProcsSimpleSum for
  defining the communication pattern. However, this meant in practice
  that filling of linearCommunication_ and treeCommunication_ themselves
  where globally controlled.

  Now retain the state within commsStructList and use linear/tree
  when populating.
2025-02-24 09:06:12 +01:00
e67fffac3f STYLE: use UPstream::reduceAnd(), UPstream::reduceOr() instead of longer forms 2025-02-24 09:04:04 +01:00
2783e78ae2 STYLE: unify some handling of warn communicator, minor code cleanup 2025-02-24 09:03:56 +01:00
e041af9481 DEFEATURE: remove non-blocking reduce() with global request tracking
- deprecated and replaced (JAN-2023) with a version that uses
  UPstream::Request to track the request. This avoids placing a
  request on the global list and then having difficulty isolating it
  later (or having it cleared out by someone else).

ENH: UPstream::addRequest() now ignores null requests

- avoids placing useless requests on the global list
2025-02-24 09:03:47 +01:00
e8e90a8de3 ENH: support non-worldComm for Dimensioned/Geometric field functions 2025-02-24 09:03:31 +01:00
0aecb25024 ENH: update MinMax to accept multiple values for add()
- now also provide its own member data (previously inherited from
  Tuple2) to provide better isolation from future changes
2025-02-24 09:03:19 +01:00
14b2302b38 COMP: remove 'special purpose' minMaxOp (#3326)
- replace with plusOp for reductions. The old use didn't necessarily work
  well with compiler resolution in all cases.
  Simplify to use plusOp (and removed the old version).
  [Does not affect very much code...]

COMP: incorrect include ordering for GeometricFieldFunctions

- header was included after the template code

REGRESSION: combineAllGather mapped to incorrect method (81fa7d08ee)

STYLE: use UPstream::commWarn(...) setter method
2025-02-24 08:57:36 +01:00
d655c2d343 ENH: print node/topology information in human-readable form at startup 2025-02-24 08:56:25 +01:00
533d3b58f8 TUT: backwardFacingStep2D: add missing probes (fixes #3319) 2025-02-21 16:49:36 +00:00
0c282bda65 Merge branch 'pstream-adjustments' into 'develop'
Additional refinements for Pstream and minor restructuring of combine vs reduce operations

See merge request Development/openfoam!727
2025-02-19 14:47:27 +00:00
4720b61313 REGRESSION: globalIndex::gatherInplaceOp was not forwarding to gatherInplace
- regression introduced by 512ec01328 (recent develop only)
2025-02-17 13:40:44 +01:00
a66be057c2 GIT: relocate Pstream template '.C' files to '.txx' prior to further changes
- reduces confusion about 'real' code vs template code
2025-02-17 13:40:44 +01:00
eae448c7aa CONFIG: handle embedded WM_COMPILE_CONTROL flags in wmakeLnInclude
- with WM_COMPILE_CONTROL="... lnInclude-extra ..." will treat like
  'wmakeLnInclude -extra' and include all source files into the
  lnInclude/ directory
2025-02-17 13:40:44 +01:00
81fa7d08ee ENH: extend Pstream gather templates to support combine or assign operation
- eliminates nearly identical code between 'gather' and 'combineGather'

  * Normal gather updates by assigning the result of the binary operation.
  * Combine gather updates by using a binary operator that modifies
    its first parameter in-place

  By-product of this refactoring are these new variants:

      listGather(), listGatherReduce()
      mapGather(), mapGatherReduce()

  that mirror the previously existing ones

      listCombineGather(), listCombineReduce()
      mapCombineGather(), mapCombineReduce()

  except that they use the 'regular' binary operator
2025-02-17 13:40:44 +01:00
0ce5053c75 ENH: mpiGather/mpiScatter now also support in-place use
- the general OpenFOAM way of collecting data often looks like this:

      List<scalar> allValues(numProcs);
      allValues[myProc] = localValue;

      Pstream::gatherList(allValues);

      // Now possible like this

      List<scalar> allValues(numProcs);
      allValues[myProc] = localValue;

      UPstream::mpiGather(nullptr, allValues.data_bytes(), sizeof(scalar));

- adjusted Pstream::gatherList accordingly.
  Split out the manual implementations, give them new names
  (..._tree_algorithm) and make them private.

STYLE: rename UPstream::gather -> UPstream::mpiGatherv

- easier to identify and establishes the connection to the MPI call
2025-02-17 13:40:44 +01:00
eb4345ed44 ENH: misc Pstream adjustments
- additional startup guard for inter-node/local-node queries (UPstream)

- impose linear communication tree for inter-node/local-node
  communicators. Was previously defaulted to a basic tree, but more
  consistent to have flat addressing for these types of connections.

- demand-driven UPstream::interNode_offsets() for walking
  inter-node ranges instead of creating it manually in various places.

- (style): List<int> instead of labelList for internal commsStruct
  since the communication structures are tied to MPI sizes
  and not to the OpenFOAM label sizes

- reduce the number of intermediate buffer allocations within
  gatherList, scatterList.
2025-02-17 13:40:44 +01:00
15ac0bc30b BUG: GAMG: processor agglomeration. Fixes #3323 2025-02-17 12:33:14 +00:00
21f36b18e5 Merge branch 'feature-UPstream-startup' into 'develop'
enhance UPstream communicator support

See merge request Development/openfoam!725
2025-02-13 15:12:42 +00:00
3852f7c5b7 ENH: add node-based globalIndex::gather (topology-aware handling) 2025-02-13 12:31:16 +01:00
a3e1376117 ENH: combine gathers of sizes in GAMGAgglomeration
- replace two listGatherValues with listGatherValues of labelPair and
  calculate offsets from the corresponding tuple members.
2025-02-13 12:31:16 +01:00
512ec01328 ENH: rationalize some globalIndex gather routines
- replace gatherValues() with listGatherValues(), which returns the
  gathered values instead of passing by argument. This makes it less
  fragile and more convenient. Naming as per
  Pstream::listGatherValues(), but still retaining the original
  parameter order.

- rename inplace 'gather' variant as 'gatherInplace' for clarity.

- changed signature of lowest-level globalIndex::gather routines from
  List<Type> to UList<Type> for the output and removed any resizing.
  This means that the caller is responsible for ensuring that the
  receiving field is adequately sized (on master). This change allows
  potential reuse of 'work' arrays etc.

  The only code change for using this low-level gather was in
  GAMGAgglomeration.
2025-02-13 12:31:16 +01:00
3e8b0a2c73 ENH: introduce UPstream::commsStructList class
- was previously simply a List<commsStruct>, but now wrap it into a
  class so that the associated communicator index can be easily
  recovered etc.
2025-02-13 12:31:16 +01:00
831a55f1ba ENH: expand UPstream communicator support
- split/duplicate functionality

- rework inter-node/intra-node handling to allow selection of
  splitting based on 'shared' or hostname (default).

- always creates node communicators at startup:
  * commInterNode() - between nodes
  * commLocalNode() - within a node

- world-comm is now always a duplicate of MPI_COMM_WORLD to provide
  better separation from other processes.

NB:
   the inter-node comm is a slight exception to other communicators
   in that we always retain its list of (global) ranks, even if the
   local process is not in that communicator.
   This can help when constructing topology-aware patterns.

FIX: non-participating ranks still had knowledge of their potential siblings

- after create by group, the procIDs_ of non-participating ranks
  should be empty (except for the inter-node exception)
2025-02-13 12:31:12 +01:00
579f8ef7c6 ENH: respect stdout/stderr preference for "Finalising parallel run" info
STYLE: namespace qualify macros use of Info, InfoErr, ...
2025-02-13 11:28:06 +01:00
0ba4f36c60 ENH: use List containers for Pstream read/write calls
- using the List containers, and not their low-level data_bytes(),
  size_bytes() methods is more convenient and allows future
  adjustments to be centralized

ENH: trivial intptr_t wrapper for MPI_Win

STYLE: minor adjustments to mpirunDebug
2025-02-11 11:09:30 +01:00
0adc745b50 CONFIG: mpirunDebug 2025-02-10 14:27:51 +01:00
3b40dd8c29 ENH: add prescan handling of -debug-switch etc
- allows use of registered switches before startup of UPstream etc.
2025-02-10 14:27:51 +01:00
6f2fadb48f ENH: extrudeToRegionMesh: ignore zone boundaries. Fixes #3318 2025-02-10 12:01:48 +00:00
559ed6c464 SUBMODULE: update adios module (fixes compilation change) 2025-02-07 14:49:28 +01:00
0cb812f6ac Merge branch 'feature-assignable' into 'develop'
ENH: assignable: extend to pointPatchFields and fvsPatchFields

See merge request Development/openfoam!726
2025-02-05 15:47:55 +00:00
4ae8ce3f0c ENH: assignable: extend to pointPatchFields and fvsPatchFields 2025-02-05 15:47:55 +00:00
9f0d1c7121 Merge branch 'style-demand-driven-memory' into 'develop'
ENH: use unique_ptr instead of raw pointers for demand-driven data

See merge request Development/openfoam!697
2025-02-05 09:44:26 +00:00
e1d40646cc ENH: use unique_ptr instead of raw pointers for demand-driven data
- simplifies construct/destruct and any later code extensions
2025-02-05 09:43:52 +00:00
9013c9941d STYLE: mark SHA1Digest as having is_contiguous content
- send/recv List<SHA1Digest> without serialization
2025-02-04 11:21:11 +01:00
0cc5273d0a GIT: cleanup old 'removed' files (ones left only for dependency checks)
GIT: minor directory structure cleanup
2025-02-04 08:27:55 +01:00
8f83ed786c Merge branch 'c++17-updates' into 'develop'
upgrade code to use some C++17 constructs

See merge request Development/openfoam!724
2025-01-31 14:17:34 +00:00
cf2b305b4f ENH: upgrade to use some C++17 constructs
- 'if constexpr (...)'
   * instead of std::enable_if
   * terminate template recursion
   * compile-time elimination of code

- use C++14 '_t', '_v' versions,
  eg, std::is_integral_v<T> instead of std::is_integral<T>::value

- std::begin, std::end, std::void_t instead of prev stdFoam versions

- provide is_contiguous_v<..> as short form of is_contiguous<..>::value
  with the additional benefit of removing any cv qualifiers.

ENH: include is_rotational_vectorspace trait

- tests for vector-space and nComponents > 1 (ie, not sphericalTensor)

ENH: improve robustness of pTraits_.. tests by removing cv qualifiers
2025-01-31 09:51:44 +01:00
b9f05bdc01 ENH: refineMesh: user-specified coordinate system 2025-01-29 09:25:40 +00:00
0b831572f3 ENH: refineMesh: tutorial to demo directional refinement 2025-01-27 17:24:35 +00:00
6dc57a1a8b STYLE: consistent parameter naming 2025-01-27 15:41:06 +00:00
a18c15a4cf ENH: add VectorSpace component fill() method
- as per std::array and FixedList

STYLE: rename Scalar.[CH] -> scalarImpl.[CH] (these are internal files)

- added inclusion guards to protect against bad use
2025-01-27 10:31:09 +01:00
39e1eb9dc6 Merge remote-tracking branch 'origin/master' into develop 2025-01-27 09:45:18 +01:00
97c8e62fe4 COMP: disambiguate some reactingEuler/multiphaseSystem file names
- poor naming (eg, 'exponential.[CH]') within the same set of library
  files means that the lnInclude/ contents are inconsistent or partly
  meaningless (related to #2520 and !542).
  Remedied by adding model-type qualifiers to the file names.
2025-01-27 09:39:18 +01:00
297fee00f1 COMP: adjustments for nvc++ compiler
- remove unneeded -Wno-old-style flags with boost/cgal elements
- add nvc equivalent to gcc/clang -Wno-invalid-offsetof
- avoid warnings about set-but-unused variable and change of scoping

STYLE: remove wmake 'CGAL' rule
- was a transitional forward to 'cgal' rule since DEC-2020
2025-01-24 10:46:06 +00:00
c987ac228c SUBMODULE: update visualization for v2412 (with c++17 standand) 2025-01-24 11:40:32 +01:00
c77b0e14a1 MISC: extend foamGrep...Targets tools 2025-01-16 16:30:37 +01:00
77cdf22eac STYLE: cellDecomposer: print operand fields in rows 2025-01-13 11:29:44 +00:00
4fe3f55e4d BUG: Fixes bug in plicRDF interface reconstruction across cyclic boundaries (fixes #3279)
Description:
The plicRDF interface reconstruction scheme calculates a reconstructed distance
function (RDF) in all interface cells and their point neighbours.
In point neighbours to interface cells, the RDF is calculated as a weighted
average of the distances to all adjacent interface cell centres with the weight
being the inverse distance to the cell centre.
By using the zoneDistribute class written by Henning Scheufler, the required
stencil data is communicated efficiently for stencil cells living on different
sides of one or more processor patches.
Some of the data required for the RDF reconstruction are cell centre and
interface centre positions. When a stencil extends across a cyclic patch these
positions have so far not been properly transformed in OpenFOAM. This issue is
fixed by the current contribution.
The fix is done by modifying the zoneDistribute class to hold the required
information about zone cells adjacent to cyclic patches. Positions are then
communicated with a new getPosition function which replaces getValue for
position data in the reconstructedDistanceFunction and plicRDF classes.
The implementation does not change the behaviour for cells not on
a cyclic patch and should have insignificant effect on efficiency for these.
The implementation can probably be optimised in terms of efficiency for zone
cells on cyclic patches, but we note that there are generally only very few of
these (interface cells and their point neighbours on cyclic patches) and so
the potential for speedup is expected to be limited.

Current limitations:

- In parallel, the user must constrain the decomposition to preserve cyclic
patches on the same processor, for the implementation to work properly.
  - See an example here: tutorials/discInConstantFlowCyclicBCs/system/decomposeParDict
- In the case of parallel rotational cyclics that are split by the decomposition
the current bugfix does not work and therefore throws an error. This is ongoing
work and should be reported and fixed by a future patch.

For further details, please see the modified files and the comments therein:
- $FOAM_SRC/finiteVolume/fvMesh/zoneDistribute/zoneDistribute.H
- $FOAM_SRC/finiteVolume/fvMesh/zoneDistribute/zoneDistribute.C
- $FOAM_SRC/finiteVolume/fvMesh/zoneDistribute/zoneDistributeI.H
- $FOAM_SRC/transportModels/geometricVoF/reconstructedDistanceFunction/reconstructedDistanceFunction.C
- $FOAM_SRC/src/transportModels/geometricVoF/reconstructionSchemes/plicSchemes/plicRDF/plicRDF.C

Co-authored-by: David Müller <> KIT
Co-authored-by: Konstantinos Missios <> Roskilde University
Co-authored-by: Johan Roenby <> Roskilde University and STROMNING
2025-01-10 15:52:52 +00:00
cb1aa273fd SUBMODULE: update external-solver, OpenQBMM for v2412 2025-01-09 11:45:11 +01:00
2e1552dd30 Merge branch 'style-pointSmoothing' into 'develop'
STYLE: update code style for point-smoothing

See merge request Development/openfoam!723
2025-01-08 19:32:21 +00:00
d072ad0e3f STYLE: update code style for point-smoothing 2025-01-08 15:04:12 +01:00
0a99702f9e ENH: lowerCSR: ignore lowerCSR for matrix type.
Reverting 267bd1af36 since makes it hard
to run cell-based algorithm on symmetric matrix.

- might become a problem if all discretisation
becomes lowerCSR based and lower() is never
constructed ...
2025-01-08 11:53:16 +00:00
5aa40389c2 BUG: snappyHexMesh: update dependent vars. Fixes #3297 2025-01-06 17:40:45 +00:00
7904a2734f BUG: twoPhaseEuler: incorrect phase. Fixes #3295. 2025-01-06 11:30:02 +00:00
b86ba60d35 ENH: lduMatrix: pass through dictionary 2025-01-03 14:48:38 +00:00
392aa56f23 COMP: dllexport symbols for conversion/ccm (fixes #3199)
- normally mingw will export *all* symbols, but since the ADF library
  explicitly uses __declspec(dllexport) itself we must do the same
  otherwise none of our library symbols are exported and linking fails.

- update some code style for conversion/ccm
2025-01-02 12:38:22 +01:00
6520d8e061 BUG: jumpCyclic: avoid neighbourField cache. Fixes #3292
- no caching of neighbour field
- no overlap of comms so not as efficient as cyclicAMI
2024-12-31 15:50:30 +00:00
45e7c4a005 Merge branch 'develop' into 'master'
RELEASE: develop branch to master

Closes #3291, #3278, #3286, #3193, #3276, #2457, #3269, #3271, #3267, #3265, #3258, #3259, #3218, #3255, #3088, #3241, #3192, #3204, #3217, and #3191

See merge request Development/openfoam!722
2024-12-24 11:57:24 +00:00
71d3f2344a Merge branch 'openfoam-v2412-rc' into 'develop'
Openfoam v2412 rc

See merge request Development/openfoam!721
2024-12-24 11:50:24 +00:00
458 changed files with 13245 additions and 8202 deletions

View File

@ -50,7 +50,7 @@
+ (
he2.name() == thermo2.phasePropertyName("e")
? fvc::div(fvc::absolute(alphaPhi2, alpha2, U2), p)
+ p*fvc::ddt(alpha1)
+ p*fvc::ddt(alpha2)
: -alpha2*dpdt
)

View File

@ -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.
@ -25,9 +25,12 @@ License
Description
Test the sizeof for basic types.
Also tests how the data mapping of OpenFOAM types to UPstream (MPI)
type ids are handled.
Can be compiled and run without any OpenFOAM libraries.
g++ -std=c++11 -oTest-machine-sizes Test-machine-sizes.cpp
g++ -std=c++17 -oTest-machine-sizes Test-machine-sizes.cpp
\*---------------------------------------------------------------------------*/
@ -37,6 +40,114 @@ Description
#include <iostream>
#include <limits>
#include <typeinfo>
#include <type_traits>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Partial copy from UPstream.H
//- Some MPI data types
//
//- 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
type_int32,
type_int64,
type_uint32,
type_uint64,
type_float,
type_double,
type_long_double,
invalid
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Partial copy from UPstreamTraits.H
//- A supported UPstream data type (intrinsic or user-defined)
template<class T>
struct UPstream_base_dataType : std::false_type
{
static constexpr auto datatype_id = dataTypes::invalid;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Specializations of the above,
// each to match the elements of UPstream::dataTypes
#undef defineUPstreamDataTraits
#define defineUPstreamDataTraits(TypeId, Type) \
template<> struct UPstream_base_dataType<Type> : std::true_type \
{ \
static constexpr auto datatype_id = dataTypes::TypeId; \
};
defineUPstreamDataTraits(type_byte, char);
defineUPstreamDataTraits(type_byte, unsigned char);
defineUPstreamDataTraits(type_int32, int32_t);
defineUPstreamDataTraits(type_int64, int64_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
//- 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
template<class T>
struct UPstream_alias_dataType
:
std::bool_constant
<
// Base type (no alias needed)
UPstream_base_dataType<std::remove_cv_t<T>>::value ||
(
// Or some int 32/64 type to re-map
std::is_integral_v<T>
&& (sizeof(T) == sizeof(int32_t) || sizeof(T) == sizeof(int64_t))
)
>
{
// 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
<
(
std::is_integral_v<T>
&& (sizeof(T) == sizeof(int32_t) || sizeof(T) == sizeof(int64_t))
),
std::conditional_t
<
(sizeof(T) == sizeof(int32_t)),
std::conditional_t<std::is_signed_v<T>, int32_t, uint32_t>,
std::conditional_t<std::is_signed_v<T>, int64_t, uint64_t>
>,
char // Fallback value (assuming it is contiguous)
>
>;
static constexpr auto datatype_id =
UPstream_base_dataType<base>::datatype_id;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class T>
void print(const char* name, bool showLimits = true)
@ -47,28 +158,78 @@ void print(const char* name, bool showLimits = true)
if (showLimits)
{
std::cout
<< " \"max\"=" << std::numeric_limits<T>::max();
<< " max=<";
if constexpr (sizeof(T) == 1)
{
std::cout << int(std::numeric_limits<T>::max());
}
else
{
std::cout << std::numeric_limits<T>::max();
}
std::cout << '>';
}
// 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 (UPstream_alias_dataType<T>::value)
{
if (UPstream_alias_dataType<T>::is_base)
{
std::cout<< " is_base";
}
else
{
std::cout<< " is_alias ("
<< int(UPstream_alias_dataType<T>::datatype_id) << ")";
}
}
else
{
std::cout<< " no_alias";
}
std::cout<< '\n';
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
std::cout<< "c++ = " << __cplusplus << '\n';
std::cout<< "machine sizes\n---\n\n";
std::cout<< "machine sizes (and some MPI traits)\n---\n\n";
print<int8_t>("int8_t");
print<uint8_t>("uint8_t");
print<int16_t>("int16_t");
print<uint16_t>("uint16_t");
print<int32_t>("int32_t");
print<uint32_t>("uint32_t");
print<int64_t>("int64_t");
print<uint64_t>("uint64_t");
std::cout << '\n';
print<char>("char");
print<unsigned char>("unsigned char");
print<short>("short");
print<int>("int");
print<unsigned>("unsigned");
print<long>("long");
print<unsigned long>("unsigned long");
print<std::size_t>("std::size_t");
print<long long>("long long");
std::cout << '\n';
print<std::size_t>("std::size_t");
print<std::streamsize>("std::streamsize");
std::cout << '\n';
print<float>("float");
print<double>("double");
print<long double>("long double");

View File

@ -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.
@ -38,12 +38,11 @@ Description
\*---------------------------------------------------------------------------*/
#include "complex.H"
#include "Tensor.H"
#include "SymmTensor.H"
#include "SphericalTensor.H"
#include "DiagTensor.H"
#include "scalar.H"
#include "complex.H"
using namespace Foam;
@ -57,45 +56,11 @@ unsigned nTest_ = 0;
unsigned nFail_ = 0;
// Compare two floating point types, and print output.
// Do ++nFail_ if values of two objects are not equal within a given tolerance.
// The function is converted from PEP-485.
template<class Type>
typename std::enable_if<pTraits<Type>::rank == 0, void>::type
cmp
(
const word& msg,
const Type& x,
const Type& y,
const scalar relTol = 1e-8, //<! are values the same within 8 decimals
const scalar absTol = 0 //<! useful for cmps near zero
)
{
Info<< msg << x << endl;
unsigned nFail = 0;
if (max(absTol, relTol*max(mag(x), mag(y))) < mag(x - y))
{
++nFail;
}
if (nFail)
{
Info<< nl
<< " #### Fail in " << nFail << " comps ####" << nl << endl;
++nFail_;
}
++nTest_;
}
// Compare two containers elementwise, and print output.
// Do ++nFail_ if two components are not equal within a given tolerance.
// The function is converted from PEP-485
template<class Type>
typename std::enable_if<pTraits<Type>::rank != 0, void>::type
cmp
void cmp
(
const word& msg,
const Type& x,
@ -104,18 +69,37 @@ cmp
const scalar absTol = 0
)
{
Info<< msg << x << endl;
const auto notEqual = [=](const auto& a, const auto& b) -> bool
{
return
(
Foam::max(absTol, relTol*Foam::max(Foam::mag(a), Foam::mag(b)))
< Foam::mag(a - b)
);
};
unsigned nFail = 0;
for (direction i = 0; i < pTraits<Type>::nComponents; ++i)
if constexpr (is_vectorspace_v<Type>)
{
if (max(absTol, relTol*max(mag(x[i]), mag(y[i]))) < mag(x[i] - y[i]))
for (direction i = 0; i < pTraits<Type>::nComponents; ++i)
{
if (notEqual(x[i], y[i]))
{
++nFail;
}
}
}
else
{
if (notEqual(x, y))
{
++nFail;
}
}
Info<< msg << x << endl;
if (nFail)
{
Info<< nl
@ -368,27 +352,26 @@ void test_global_opers(Type)
// Do compile-time recursion over the given types
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID){}
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID)
void run_tests(const std::tuple<Tp...>& types, const List<word>& names)
{
Info<< nl << " ## Test constructors: "<< typeID[I] <<" ##" << nl;
test_constructors(std::get<I>(types));
if constexpr (I < sizeof...(Tp))
{
const auto& name = names[I];
Info<< nl << " ## Test member functions: "<< typeID[I] <<" ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test constructors: " << name << " ##" << nl;
test_constructors(std::get<I>(types));
Info<< nl << " ## Test global functions: "<< typeID[I] << " ##" << nl;
test_global_funcs(std::get<I>(types));
Info<< nl << " ## Test member functions: " << name << " ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test global operators: "<< typeID[I] <<" ##" << nl;
test_global_opers(std::get<I>(types));
Info<< nl << " ## Test global functions: " << name << " ##" << nl;
test_global_funcs(std::get<I>(types));
run_tests<I + 1, Tp...>(types, typeID);
Info<< nl << " ## Test global operators: " << name << " ##" << nl;
test_global_opers(std::get<I>(types));
run_tests<I + 1, Tp...>(types, names);
}
}
@ -403,8 +386,8 @@ int main()
const List<word> typeID
({
"DiagTensor<floatScalar>",
"DiagTensor<doubleScalar>",
"DiagTensor<float>",
"DiagTensor<double>",
"DiagTensor<complex>"
});

View File

@ -1,3 +0,0 @@
Test-Dictionary.C
EXE = $(FOAM_USER_APPBIN)/Test-Dictionary

View File

@ -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.
@ -85,8 +85,7 @@ void compileInfo()
template<class FixedListType>
typename std::enable_if
<(FixedListType::max_size() == 2), bool>::type
std::enable_if_t<(FixedListType::max_size() == 2), bool>
is_pair()
{
return true;
@ -94,7 +93,7 @@ is_pair()
template<class FixedListType>
typename std::enable_if<(FixedListType::max_size() != 2), std::string>::type
std::enable_if_t<(FixedListType::max_size() != 2), std::string>
is_pair()
{
return "not really at all";

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 OpenCFD Ltd.
Copyright (C) 2021-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -42,9 +42,11 @@ Note
#include "Hash.H"
#ifdef FULLDEBUG
#define HashTypeInfo(Args) void info() { std::cerr<< "" Args << "\n"; }
#define HashTypeInfo(Name) \
static constexpr const char* name() noexcept { return Name; } \
void info() const { std::cerr<< name() << " hashing\n"; }
#else
#define HashTypeInfo(Args) void info() {}
#define HashTypeInfo(Name) void info() const {}
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -53,20 +55,36 @@ namespace Foam
{
/*---------------------------------------------------------------------------*\
Class Hash Declaration
Class HashFunc Declaration
\*---------------------------------------------------------------------------*/
template<class T, class SFINAEType=bool>
template<class T>
struct HashFun
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "default"; }
#endif
HashTypeInfo("plain hash")
void info() const
{
#ifdef FULLDEBUG
if constexpr (std::is_base_of_v<std::string, T>)
{
std::cerr<< "std::string hashing\n";
}
else
{
std::cerr<< "default hashing\n";
}
#endif
}
unsigned operator()(const T& obj, unsigned seed=0) const
{
return Foam::Hasher(&obj, sizeof(obj), seed);
if constexpr (std::is_base_of_v<std::string, T>)
{
return Foam::Hasher(obj.data(), obj.size(), seed);
}
else
{
return Foam::Hasher(&obj, sizeof(obj), seed);
}
}
};
@ -76,45 +94,17 @@ struct HashFun
//- Hashing for label
template<> struct HashFun<Foam::label> : Hash<label>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "label"; }
#endif
HashTypeInfo("hash label")
HashTypeInfo("label")
};
//- Hashing for pointers, interpret pointer as a integer type
template<> struct HashFun<void*> : Hash<void *>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "pointer"; }
#endif
HashTypeInfo("hash ptr")
HashTypeInfo("pointer")
};
//- Hashing for string types
template<class StringType>
struct HashFun
<
StringType,
typename std::enable_if
<
std::is_base_of<std::string, StringType>::value, bool
>::type
>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "string"; }
#endif
HashTypeInfo("hash string")
unsigned operator()(const std::string& obj, unsigned seed=0) const
{
return Foam::Hasher(obj.data(), obj.size(), seed);
}
};
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -133,83 +123,56 @@ namespace Foam
template<> struct HashFun<edge> : Hash<edge>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "edge"; }
#endif
HashTypeInfo("hash edge")
HashTypeInfo("edge")
};
template<> struct HashFun<face> : Hash<face>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "face"; }
#endif
HashTypeInfo("hash face")
HashTypeInfo("face")
};
template<> struct HashFun<triFace> : Hash<triFace>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "triFace"; }
#endif
HashTypeInfo("hash triFace")
HashTypeInfo("triFace")
};
template<class T>
struct HashFun<Pair<T>> : Hash<Pair<T>>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "Pair"; }
#endif
HashTypeInfo("hash Pair")
HashTypeInfo("Pair")
};
template<class T1, class T2>
struct HashFun<Tuple2<T1, T2>> : Hash<Tuple2<T1, T2>>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "Tuple2"; }
#endif
HashTypeInfo("hash Tuple2")
HashTypeInfo("Tuple2")
};
template<class T>
struct HashFun<List<T>> : Hash<List<T>>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "List"; }
#endif
HashTypeInfo("hash List")
HashTypeInfo("List")
};
template<class T> struct HashFun<UList<T>> : Hash<UList<T>>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "UList"; }
#endif
HashTypeInfo("hash UList")
HashTypeInfo("UList")
};
template<class T, int SizeMin>
struct HashFun<DynamicList<T, SizeMin>> : Hash<DynamicList<T, SizeMin>>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "DynamicList"; }
#endif
HashTypeInfo("hash DynamicList")
HashTypeInfo("DynamicList")
};
template<class T, unsigned N>
struct HashFun<FixedList<T, N>> : Hash<FixedList<T, N>>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "FixedList"; }
#endif
HashTypeInfo("hash FixedList")
HashTypeInfo("FixedList")
};

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2021 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -81,7 +81,7 @@ void infoHashString
void reportHashList(const UList<string>& list)
{
Info<< "contiguous = " << is_contiguous<string>::value << nl << nl;
Info<< "contiguous = " << is_contiguous_v<string> << nl << nl;
for (const string& val : list)
{
@ -94,7 +94,7 @@ void reportHashList(const UList<string>& list)
void reportHashList(const UList<label>& list)
{
Info<<"contiguous = " << is_contiguous<label>::value << nl << nl;
Info<<"contiguous = " << is_contiguous_v<label> << nl << nl;
for (const label val : list)
{
@ -113,7 +113,7 @@ void reportHashList(const UList<label>& list)
void reportHashList(const UList<face>& list)
{
Info<<"contiguous = " << is_contiguous<label>::value << nl << nl;
Info<<"contiguous = " << is_contiguous_v<label> << nl << nl;
for (const face& f : list)
{
@ -154,7 +154,7 @@ void reportHashList(const UList<labelList>& list)
void reportHashList(const UList<wordPair>& list)
{
Info<<"contiguous = " << is_contiguous<wordPair>::value << nl << nl;
Info<<"contiguous = " << is_contiguous_v<wordPair> << nl << nl;
for (const wordPair& pr : list)
{
@ -179,7 +179,7 @@ void reportHashList(const UList<wordPair>& list)
void reportHashList(const UList<labelPair>& list)
{
Info<<"contiguous = " << is_contiguous<labelPair>::value << nl << nl;
Info<<"contiguous = " << is_contiguous_v<labelPair> << nl << nl;
for (const labelPair& pr : list)
{
@ -200,7 +200,7 @@ void reportHashList(const UList<labelPair>& list)
void reportHashList(const UList<labelPairPair>& list)
{
Info<<"contiguous = " << is_contiguous<labelPairPair>::value << nl << nl;
Info<<"contiguous = " << is_contiguous_v<labelPairPair> << nl << nl;
for (const labelPairPair& pr : list)
{
@ -221,7 +221,7 @@ void reportHashList(const UList<labelPairPair>& list)
void reportHashList(const UList<edge>& list)
{
Info<<"contiguous = " << is_contiguous<edge>::value << nl << nl;
Info<<"contiguous = " << is_contiguous_v<edge> << nl << nl;
for (const edge& e : list)
{
@ -242,7 +242,7 @@ void reportHashList(const UList<edge>& list)
void reportHashList(const UList<triFace>& list)
{
Info<<"contiguous = " << is_contiguous<triFace>::value << nl << nl;
Info<<"contiguous = " << is_contiguous_v<triFace> << nl << nl;
for (const triFace& f : list)
{

View File

@ -213,11 +213,10 @@ int main(int argc, char *argv[])
mesh
);
Info<< "points path: " << io.typeFilePath<labelIOList>() << nl;
Info<< "points path: " << io.typeFilePath<void>() << nl;
Info<< "points path: " << io.typeFilePath<pointIOField>() << nl;
io.resetHeader("bad-points");
Info<< "bad path: " << io.typeFilePath<void>() << nl;
Info<< "bad path: " << io.typeFilePath<labelIOList>() << nl;
}
IOobject io

View File

@ -45,7 +45,7 @@ using namespace Foam;
template<class Type>
word report()
{
if (is_globalIOobject<Type>::value)
if constexpr (is_globalIOobject<Type>::value)
{
return "global";
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2023 OpenCFD Ltd.
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -118,7 +118,7 @@ Ostream& printListOutputType(const char* what)
{
Info<< what
<< " (contiguous="
<< is_contiguous<T>::value << " no_linebreak="
<< is_contiguous_v<T> << " no_linebreak="
<< Detail::ListPolicy::no_linebreak<T>::value
<< " short_length="
<< Detail::ListPolicy::short_length<T>::value << ')';

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 OpenCFD Ltd.
Copyright (C) 2021-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -128,18 +128,17 @@ void test_member_funcs(Type)
// Do compile-time recursion over the given types
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID){}
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID)
void run_tests(const std::tuple<Tp...>& types, const List<word>& names)
{
Info<< nl << " ## Test member functions: "<< typeID[I] <<" ##" << nl;
test_member_funcs(std::get<I>(types));
if constexpr (I < sizeof...(Tp))
{
const auto& name = names[I];
run_tests<I + 1, Tp...>(types, typeID);
Info<< nl << " ## Test member functions: " << name << " ##" << nl;
test_member_funcs(std::get<I>(types));
run_tests<I + 1, Tp...>(types, names);
}
}

View File

@ -0,0 +1,3 @@
Test-PtrDictionary1.C
EXE = $(FOAM_USER_APPBIN)/Test-PtrDictionary1

View File

@ -25,10 +25,10 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
Test-Dictionary
Test-PtrDictionary1
Description
Tests for Dictionary (not dictionary)
Tests for Dictionary (not dictionary) and PtrDictionary
\*---------------------------------------------------------------------------*/
@ -185,7 +185,7 @@ int main(int argc, char *argv[])
}
std::cout<< "iter type: "
<< typeid(stdFoam::begin(scalarDict2)).name() << '\n';
<< typeid(std::begin(scalarDict2)).name() << '\n';
scalarDict.transfer(scalarDict2);

View File

@ -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.
@ -38,12 +38,11 @@ Description
\*---------------------------------------------------------------------------*/
#include "complex.H"
#include "Tensor.H"
#include "SymmTensor.H"
#include "SphericalTensor.H"
#include "DiagTensor.H"
#include "scalar.H"
#include "complex.H"
using namespace Foam;
@ -57,65 +56,50 @@ unsigned nTest_ = 0;
unsigned nFail_ = 0;
// Compare two floating point types, and print output.
// Compare two containers elementwise, and print output.
// Do ++nFail_ if values of two objects are not equal within a given tolerance.
// The function is converted from PEP-485.
template<class Type>
typename std::enable_if<pTraits<Type>::rank == 0, void>::type
cmp
template<class Type, class Type2 = Type>
void cmp
(
const word& msg,
const Type& x,
const Type& y,
const Type2& y,
const scalar relTol = 1e-8, //<! are values the same within 8 decimals
const scalar absTol = 0 //<! useful for cmps near zero
)
{
Info<< msg << x << endl;
const auto notEqual = [=](const auto& a, const auto& b) -> bool
{
return
(
Foam::max(absTol, relTol*Foam::max(Foam::mag(a), Foam::mag(b)))
< Foam::mag(a - b)
);
};
unsigned nFail = 0;
if (max(absTol, relTol*max(mag(x), mag(y))) < mag(x - y))
if constexpr (is_vectorspace_v<Type>)
{
++nFail;
for (direction i = 0; i < pTraits<Type>::nComponents; ++i)
{
if (notEqual(x[i], y[i]))
{
++nFail;
}
}
}
if (nFail)
else
{
Info<< nl
<< " #### Fail in " << nFail << " comps ####" << nl << endl;
++nFail_;
}
++nTest_;
}
// Compare two containers elementwise, and print output.
// Do ++nFail_ if two components are not equal within a given tolerance.
// The function is converted from PEP-485
template<class Type>
typename std::enable_if<pTraits<Type>::rank != 0, void>::type
cmp
(
const word& msg,
const Type& x,
const Type& y,
const scalar relTol = 1e-8,
const scalar absTol = 0
)
{
Info<< msg << x << endl;
unsigned nFail = 0;
for (direction i = 0; i < pTraits<Type>::nComponents; ++i)
{
if (max(absTol, relTol*max(mag(x[i]), mag(y[i]))) < mag(x[i] - y[i]))
if (notEqual(x, y))
{
++nFail;
}
}
Info<< msg << x << endl;
if (nFail)
{
Info<< nl
@ -277,27 +261,26 @@ void test_global_opers(Type)
// Do compile-time recursion over the given types
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID){}
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID)
void run_tests(const std::tuple<Tp...>& types, const List<word>& names)
{
Info<< nl << " ## Test constructors: "<< typeID[I] <<" ##" << nl;
test_constructors(std::get<I>(types));
if constexpr (I < sizeof...(Tp))
{
const auto& name = names[I];
Info<< nl << " ## Test member functions: "<< typeID[I] <<" ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test constructors: " << name << " ##" << nl;
test_constructors(std::get<I>(types));
Info<< nl << " ## Test global functions: "<< typeID[I] << " ##" << nl;
test_global_funcs(std::get<I>(types));
Info<< nl << " ## Test member functions: " << name << " ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test global operators: "<< typeID[I] <<" ##" << nl;
test_global_opers(std::get<I>(types));
Info<< nl << " ## Test global functions: " << name << " ##" << nl;
test_global_funcs(std::get<I>(types));
run_tests<I + 1, Tp...>(types, typeID);
Info<< nl << " ## Test global operators: " << name << " ##" << nl;
test_global_opers(std::get<I>(types));
run_tests<I + 1, Tp...>(types, names);
}
}
@ -312,8 +295,8 @@ int main()
const List<word> typeID
({
"SphericalTensor<floatScalar>",
"SphericalTensor<doubleScalar>",
"SphericalTensor<float>",
"SphericalTensor<double>",
"SphericalTensor<complex>"
});

View File

@ -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.
@ -38,11 +38,10 @@ Description
\*---------------------------------------------------------------------------*/
#include "complex.H"
#include "Tensor2D.H"
#include "SymmTensor2D.H"
#include "SphericalTensor2D.H"
#include "scalar.H"
#include "complex.H"
using namespace Foam;
@ -56,12 +55,11 @@ unsigned nTest_ = 0;
unsigned nFail_ = 0;
// Compare two floating point types, and print output.
// Compare two containers elementwise, and print output.
// Do ++nFail_ if values of two objects are not equal within a given tolerance.
// The function is converted from PEP-485.
template<class Type>
typename std::enable_if<pTraits<Type>::rank == 0, void>::type
cmp
void cmp
(
const word& msg,
const Type& x,
@ -70,51 +68,37 @@ cmp
const scalar absTol = 0 //<! useful for cmps near zero
)
{
Info<< msg << x << endl;
const auto notEqual = [=](const auto& a, const auto& b) -> bool
{
return
(
Foam::max(absTol, relTol*Foam::max(Foam::mag(a), Foam::mag(b)))
< Foam::mag(a - b)
);
};
unsigned nFail = 0;
if (max(absTol, relTol*max(mag(x), mag(y))) < mag(x - y))
if constexpr (is_vectorspace_v<Type>)
{
++nFail;
for (direction i = 0; i < pTraits<Type>::nComponents; ++i)
{
if (notEqual(x[i], y[i]))
{
++nFail;
}
}
}
if (nFail)
else
{
Info<< nl
<< " #### Fail in " << nFail << " comps ####" << nl << endl;
++nFail_;
}
++nTest_;
}
// Compare two containers elementwise, and print output.
// Do ++nFail_ if two components are not equal within a given tolerance.
// The function is converted from PEP-485
template<class Type>
typename std::enable_if<pTraits<Type>::rank != 0, void>::type
cmp
(
const word& msg,
const Type& x,
const Type& y,
const scalar relTol = 1e-8,
const scalar absTol = 0
)
{
Info<< msg << x << endl;
unsigned nFail = 0;
for (direction i = 0; i < pTraits<Type>::nComponents; ++i)
{
if (max(absTol, relTol*max(mag(x[i]), mag(y[i]))) < mag(x[i] - y[i]))
if (notEqual(x, y))
{
++nFail;
}
}
Info<< msg << x << endl;
if (nFail)
{
Info<< nl
@ -260,27 +244,26 @@ void test_global_opers(Type)
// Do compile-time recursion over the given types
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID){}
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID)
void run_tests(const std::tuple<Tp...>& types, const List<word>& names)
{
Info<< nl << " ## Test constructors: "<< typeID[I] <<" ##" << nl;
test_constructors(std::get<I>(types));
if constexpr (I < sizeof...(Tp))
{
const auto& name = names[I];
Info<< nl << " ## Test member functions: "<< typeID[I] <<" ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test constructors: " << name << " ##" << nl;
test_constructors(std::get<I>(types));
Info<< nl << " ## Test global functions: "<< typeID[I] << " ##" << nl;
test_global_funcs(std::get<I>(types));
Info<< nl << " ## Test member functions: " << name << " ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test global operators: "<< typeID[I] <<" ##" << nl;
test_global_opers(std::get<I>(types));
Info<< nl << " ## Test global functions: " << name << " ##" << nl;
test_global_funcs(std::get<I>(types));
run_tests<I + 1, Tp...>(types, typeID);
Info<< nl << " ## Test global operators: " << name << " ##" << nl;
test_global_opers(std::get<I>(types));
run_tests<I + 1, Tp...>(types, names);
}
}
@ -295,8 +278,8 @@ int main()
const List<word> typeID
({
"SphericalTensor2D<floatScalar>",
"SphericalTensor2D<doubleScalar>",
"SphericalTensor2D<float>",
"SphericalTensor2D<double>",
"SphericalTensor2D<complex>"
});

View File

@ -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.
@ -40,11 +40,10 @@ Description
\*---------------------------------------------------------------------------*/
#include "complex.H"
#include "symmTensor.H"
#include "transform.H"
#include "Random.H"
#include "scalar.H"
#include "complex.H"
using namespace Foam;
@ -69,12 +68,12 @@ symmTensor makeRandomContainer(Random& rnd)
// Create a symmTensor based on a given value
template<class Type>
typename std::enable_if
std::enable_if_t
<
std::is_same<floatScalar, Type>::value ||
std::is_same<doubleScalar, Type>::value,
std::is_floating_point_v<Type> || std::is_same_v<complex, Type>,
symmTensor
>::type makeContainer(const Type val)
>
makeContainer(const Type val)
{
symmTensor T(Zero);
std::fill(T.begin(), T.end(), val);
@ -82,12 +81,11 @@ typename std::enable_if
}
// Compare two floating point types, and print output.
// Compare two containers elementwise, and print output.
// Do ++nFail_ if values of two objects are not equal within a given tolerance.
// The function is converted from PEP-485.
template<class Type>
typename std::enable_if<pTraits<Type>::rank == 0, void>::type
cmp
void cmp
(
const word& msg,
const Type& x,
@ -96,51 +94,37 @@ cmp
const scalar relTol = 1e-8 //<! are values the same within 8 decimals
)
{
Info<< msg << x << "?=" << y << endl;
const auto notEqual = [=](const auto& a, const auto& b) -> bool
{
return
(
Foam::max(absTol, relTol*Foam::max(Foam::mag(a), Foam::mag(b)))
< Foam::mag(a - b)
);
};
unsigned nFail = 0;
if (max(absTol, relTol*max(mag(x), mag(y))) < mag(x - y))
if constexpr (is_vectorspace_v<Type>)
{
++nFail;
for (direction i = 0; i < pTraits<Type>::nComponents; ++i)
{
if (notEqual(x[i], y[i]))
{
++nFail;
}
}
}
if (nFail)
else
{
Info<< nl
<< " #### Fail in " << nFail << " comps ####" << nl << endl;
++nFail_;
}
++nTest_;
}
// Compare two containers elementwise, and print output.
// Do ++nFail_ if two components are not equal within a given tolerance.
// The function is converted from PEP-485
template<class Type>
typename std::enable_if<pTraits<Type>::rank != 0, void>::type
cmp
(
const word& msg,
const Type& x,
const Type& y,
const scalar absTol = 0,
const scalar relTol = 1e-8
)
{
Info<< msg << x << "?=" << y << endl;
unsigned nFail = 0;
for (direction i = 0; i < pTraits<Type>::nComponents; ++i)
{
if (max(absTol, relTol*max(mag(x[i]), mag(y[i]))) < mag(x[i] - y[i]))
if (notEqual(x, y))
{
++nFail;
}
}
Info<< msg << x << "?=" << y << endl;
if (nFail)
{
Info<< nl
@ -588,27 +572,26 @@ void test_eigen_funcs(const symmTensor& T)
// Do compile-time recursion over the given types
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID){}
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID)
void run_tests(const std::tuple<Tp...>& types, const List<word>& names)
{
Info<< nl << " ## Test constructors: "<< typeID[I] <<" ##" << nl;
test_constructors(std::get<I>(types));
if constexpr (I < sizeof...(Tp))
{
const auto& name = names[I];
Info<< nl << " ## Test member functions: "<< typeID[I] <<" ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test constructors: " << name << " ##" << nl;
test_constructors(std::get<I>(types));
Info<< nl << " ## Test global functions: "<< typeID[I] << " ##" << nl;
test_global_funcs(std::get<I>(types));
Info<< nl << " ## Test member functions: " << name << " ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test global operators: "<< typeID[I] <<" ##" << nl;
test_global_opers(std::get<I>(types));
Info<< nl << " ## Test global functions: " << name << " ##" << nl;
test_global_funcs(std::get<I>(types));
run_tests<I + 1, Tp...>(types, typeID);
Info<< nl << " ## Test global operators: " << name << " ##" << nl;
test_global_opers(std::get<I>(types));
run_tests<I + 1, Tp...>(types, names);
}
}
@ -623,8 +606,8 @@ int main()
const List<word> typeID
({
"SymmTensor<floatScalar>",
"SymmTensor<doubleScalar>",
"SymmTensor<float>",
"SymmTensor<double>",
"SymmTensor<complex>"
});

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2022 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -40,11 +40,10 @@ Description
\*---------------------------------------------------------------------------*/
#include "complex.H"
#include "symmTensor2D.H"
#include "transform.H"
#include "Random.H"
#include "scalar.H"
#include "complex.H"
using namespace Foam;
@ -67,45 +66,11 @@ symmTensor2D makeRandomContainer(Random& rnd)
}
// Compare two floating point types, and print output.
// Do ++nFail_ if values of two objects are not equal within a given tolerance.
// The function is converted from PEP-485.
template<class Type>
typename std::enable_if<pTraits<Type>::rank == 0, void>::type
cmp
(
const word& msg,
const Type& x,
const Type& y,
const scalar absTol = 0, //<! useful for cmps near zero
const scalar relTol = 1e-8 //<! are values the same within 8 decimals
)
{
Info<< msg << x << "?=" << y << endl;
unsigned nFail = 0;
if (max(absTol, relTol*max(mag(x), mag(y))) < mag(x - y))
{
++nFail;
}
if (nFail)
{
Info<< nl
<< " #### Fail in " << nFail << " comps ####" << nl << endl;
++nFail_;
}
++nTest_;
}
// Compare two containers elementwise, and print output.
// Do ++nFail_ if two components are not equal within a given tolerance.
// The function is converted from PEP-485
template<class Type>
typename std::enable_if<pTraits<Type>::rank != 0, void>::type
cmp
void cmp
(
const word& msg,
const Type& x,
@ -114,18 +79,37 @@ cmp
const scalar relTol = 1e-8
)
{
Info<< msg << x << "?=" << y << endl;
const auto notEqual = [=](const auto& a, const auto& b) -> bool
{
return
(
Foam::max(absTol, relTol*Foam::max(Foam::mag(a), Foam::mag(b)))
< Foam::mag(a - b)
);
};
unsigned nFail = 0;
for (direction i = 0; i < pTraits<Type>::nComponents; ++i)
if constexpr (is_vectorspace_v<Type>)
{
if (max(absTol, relTol*max(mag(x[i]), mag(y[i]))) < mag(x[i] - y[i]))
for (direction i = 0; i < pTraits<Type>::nComponents; ++i)
{
if (notEqual(x[i], y[i]))
{
++nFail;
}
}
}
else
{
if (notEqual(x, y))
{
++nFail;
}
}
Info<< msg << x << "?=" << y << endl;
if (nFail)
{
Info<< nl
@ -538,27 +522,26 @@ void test_eigen_funcs(const symmTensor2D& T)
// Do compile-time recursion over the given types
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID){}
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID)
void run_tests(const std::tuple<Tp...>& types, const List<word>& names)
{
Info<< nl << " ## Test constructors: "<< typeID[I] <<" ##" << nl;
test_constructors(std::get<I>(types));
if constexpr (I < sizeof...(Tp))
{
const auto& name = names[I];
Info<< nl << " ## Test member functions: "<< typeID[I] <<" ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test constructors: " << name << " ##" << nl;
test_constructors(std::get<I>(types));
Info<< nl << " ## Test global functions: "<< typeID[I] << " ##" << nl;
test_global_funcs(std::get<I>(types));
Info<< nl << " ## Test member functions: " << name << " ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test global operators: "<< typeID[I] <<" ##" << nl;
test_global_opers(std::get<I>(types));
Info<< nl << " ## Test global functions: " << name << " ##" << nl;
test_global_funcs(std::get<I>(types));
run_tests<I + 1, Tp...>(types, typeID);
Info<< nl << " ## Test global operators: " << name << " ##" << nl;
test_global_opers(std::get<I>(types));
run_tests<I + 1, Tp...>(types, names);
}
}
@ -573,8 +556,8 @@ int main(int argc, char *argv[])
const List<word> typeID
({
"SymmTensor2D<floatScalar>",
"SymmTensor2D<doubleScalar>",
"SymmTensor2D<float>",
"SymmTensor2D<double>",
"SymmTensor2D<complex>"
});

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018 OpenFOAM Foundation
Copyright (C) 2019-2020 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -41,11 +41,10 @@ Description
\*---------------------------------------------------------------------------*/
#include "complex.H"
#include "tensor.H"
#include "transform.H"
#include "Random.H"
#include "scalar.H"
#include "complex.H"
using namespace Foam;
@ -68,45 +67,11 @@ tensor makeRandomContainer(Random& rnd)
}
// Compare two floating point types, and print output.
// Do ++nFail_ if values of two objects are not equal within a given tolerance.
// The function is converted from PEP-485.
template<class Type>
typename std::enable_if<pTraits<Type>::rank == 0, void>::type
cmp
(
const word& msg,
const Type& x,
const Type& y,
const scalar absTol = 0, //<! useful for cmps near zero
const scalar relTol = 1e-8 //<! are values the same within 8 decimals
)
{
Info<< msg << x << "?=" << y << endl;
unsigned nFail = 0;
if (max(absTol, relTol*max(mag(x), mag(y))) < mag(x - y))
{
++nFail;
}
if (nFail)
{
Info<< nl
<< " #### Fail in " << nFail << " comps ####" << nl << endl;
++nFail_;
}
++nTest_;
}
// Compare two containers elementwise, and print output.
// Do ++nFail_ if two components are not equal within a given tolerance.
// The function is converted from PEP-485
template<class Type>
typename std::enable_if<pTraits<Type>::rank != 0, void>::type
cmp
void cmp
(
const word& msg,
const Type& x,
@ -115,18 +80,37 @@ cmp
const scalar relTol = 1e-8
)
{
Info<< msg << x << "?=" << y << endl;
const auto notEqual = [=](const auto& a, const auto& b) -> bool
{
return
(
Foam::max(absTol, relTol*Foam::max(Foam::mag(a), Foam::mag(b)))
< Foam::mag(a - b)
);
};
unsigned nFail = 0;
for (direction i = 0; i < pTraits<Type>::nComponents; ++i)
if constexpr (is_vectorspace_v<Type>)
{
if (max(absTol, relTol*max(mag(x[i]), mag(y[i]))) < mag(x[i] - y[i]))
for (direction i = 0; i < pTraits<Type>::nComponents; ++i)
{
if (notEqual(x[i], y[i]))
{
++nFail;
}
}
}
else
{
if (notEqual(x, y))
{
++nFail;
}
}
Info<< msg << x << "?=" << y << endl;
if (nFail)
{
Info<< nl
@ -987,27 +971,26 @@ void test_eigen_funcs(const tensor& T, const bool prod = true)
// Do compile-time recursion over the given types
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID){}
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID)
void run_tests(const std::tuple<Tp...>& types, const List<word>& names)
{
Info<< nl << " ## Test constructors: "<< typeID[I] <<" ##" << nl;
test_constructors(std::get<I>(types));
if constexpr (I < sizeof...(Tp))
{
const auto& name = names;
Info<< nl << " ## Test member functions: "<< typeID[I] <<" ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test constructors: " << name << " ##" << nl;
test_constructors(std::get<I>(types));
Info<< nl << " ## Test global functions: "<< typeID[I] << " ##" << nl;
test_global_funcs(std::get<I>(types));
Info<< nl << " ## Test member functions: " << name << " ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test global operators: "<< typeID[I] <<" ##" << nl;
test_global_opers(std::get<I>(types));
Info<< nl << " ## Test global functions: " << name <<" ##" << nl;
test_global_funcs(std::get<I>(types));
run_tests<I + 1, Tp...>(types, typeID);
Info<< nl << " ## Test global operators: " << name <<" ##" << nl;
test_global_opers(std::get<I>(types));
run_tests<I + 1, Tp...>(types, names);
}
}
@ -1022,8 +1005,8 @@ int main()
const List<word> typeID
({
"Tensor<floatScalar>",
"Tensor<doubleScalar>",
"Tensor<float>",
"Tensor<double>",
"Tensor<complex>"
});

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2014 OpenFOAM Foundation
Copyright (C) 2019-2022 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -41,13 +41,13 @@ Description
\*---------------------------------------------------------------------------*/
#include "scalar.H"
#include "complex.H"
#include "vector2DField.H"
#include "tensor2D.H"
#include "symmTensor2D.H"
#include "transform.H"
#include "Random.H"
#include "scalar.H"
#include "complex.H"
using namespace Foam;
@ -70,12 +70,11 @@ tensor2D makeRandomContainer(Random& rnd)
}
// Compare two floating point types, and print output.
// Do ++nFail_ if values of two objects are not equal within a given tolerance.
// The function is converted from PEP-485.
// Compare two containers elementwise, and print output.
// Do ++nFail_ if two components are not equal within a given tolerance.
// The function is converted from PEP-485
template<class Type>
typename std::enable_if<pTraits<Type>::rank == 0, void>::type
cmp
void cmp
(
const word& msg,
const Type& x,
@ -84,51 +83,37 @@ cmp
const scalar relTol = 1e-8 //<! are values the same within 8 decimals
)
{
Info<< msg << x << "?=" << y << endl;
const auto notEqual = [=](const auto& a, const auto& b) -> bool
{
return
(
Foam::max(absTol, relTol*Foam::max(Foam::mag(a), Foam::mag(b)))
< Foam::mag(a - b)
);
};
unsigned nFail = 0;
if (max(absTol, relTol*max(mag(x), mag(y))) < mag(x - y))
if constexpr (is_vectorspace_v<Type>)
{
++nFail;
for (direction i = 0; i < pTraits<Type>::nComponents; ++i)
{
if (notEqual(x[i], y[i]))
{
++nFail;
}
}
}
if (nFail)
else
{
Info<< nl
<< " #### Fail in " << nFail << " comps ####" << nl << endl;
++nFail_;
}
++nTest_;
}
// Compare two containers elementwise, and print output.
// Do ++nFail_ if two components are not equal within a given tolerance.
// The function is converted from PEP-485
template<class Type>
typename std::enable_if<pTraits<Type>::rank != 0, void>::type
cmp
(
const word& msg,
const Type& x,
const Type& y,
const scalar absTol = 0,
const scalar relTol = 1e-8
)
{
Info<< msg << x << "?=" << y << endl;
unsigned nFail = 0;
for (direction i = 0; i < pTraits<Type>::nComponents; ++i)
{
if (max(absTol, relTol*max(mag(x[i]), mag(y[i]))) < mag(x[i] - y[i]))
if (notEqual(x, y))
{
++nFail;
}
}
Info<< msg << x << "?=" << y << endl;
if (nFail)
{
Info<< nl
@ -795,27 +780,26 @@ void test_eigen_funcs(const tensor2D& T)
// Do compile-time recursion over the given types
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID){}
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID)
void run_tests(const std::tuple<Tp...>& types, const List<word>& names)
{
Info<< nl << " ## Test constructors: "<< typeID[I] <<" ##" << nl;
test_constructors(std::get<I>(types));
if constexpr (I < sizeof...(Tp))
{
const auto& name = names[I];
Info<< nl << " ## Test member functions: "<< typeID[I] <<" ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test constructors: " << name << " ##" << nl;
test_constructors(std::get<I>(types));
Info<< nl << " ## Test global functions: "<< typeID[I] << " ##" << nl;
test_global_funcs(std::get<I>(types));
Info<< nl << " ## Test member functions: " << name << " ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test global operators: "<< typeID[I] <<" ##" << nl;
test_global_opers(std::get<I>(types));
Info<< nl << " ## Test global functions: " << name << " ##" << nl;
test_global_funcs(std::get<I>(types));
run_tests<I + 1, Tp...>(types, typeID);
Info<< nl << " ## Test global operators: " << name << " ##" << nl;
test_global_opers(std::get<I>(types));
run_tests<I + 1, Tp...>(types, names);
}
}
@ -831,8 +815,8 @@ int main(int argc, char *argv[])
const List<word> typeID
({
"Tensor2D<floatScalar>",
"Tensor2D<doubleScalar>",
"Tensor2D<float>",
"Tensor2D<double>",
"Tensor2D<complex>"
});

View File

@ -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.
@ -67,13 +67,9 @@ doubleScalar getTol(complex)
}
// Create a non-complex random Matrix.
// Create a random Matrix (real or complex)
template<class MatrixType>
typename std::enable_if
<
!std::is_same<complex, typename MatrixType::cmptType>:: value,
MatrixType
>::type makeRandomMatrix
MatrixType makeRandomMatrix
(
const labelPair& dims,
Random& rndGen
@ -81,34 +77,22 @@ typename std::enable_if
{
MatrixType mat(dims);
std::generate
(
mat.begin(),
mat.end(),
[&]{return rndGen.GaussNormal<scalar>();}
);
return mat;
}
// Create a complex random Matrix.
template<class MatrixType>
typename std::enable_if
<
std::is_same<complex, typename MatrixType::cmptType>:: value,
MatrixType
>::type makeRandomMatrix
(
const labelPair& dims,
Random& rndGen
)
{
MatrixType mat(dims);
for (auto& x : mat)
if constexpr (std::is_same_v<complex, typename MatrixType::cmptType>)
{
x = complex(rndGen.GaussNormal<scalar>(), rndGen.GaussNormal<scalar>());
for (auto& x : mat)
{
x.real(rndGen.GaussNormal<scalar>());
x.imag(rndGen.GaussNormal<scalar>());
}
}
else
{
std::generate
(
mat.begin(),
mat.end(),
[&]{ return rndGen.GaussNormal<scalar>(); }
);
}
return mat;
@ -179,128 +163,57 @@ List<Type> flt
}
// Compare two floating point types, and print output.
// Compare two values or two containers (elementwise), and print output.
// Do ++nFail_ if values of two objects are not equal within a given tolerance.
// The function is converted from PEP-485.
template<class Type>
typename std::enable_if
<
std::is_same<floatScalar, Type>::value ||
std::is_same<doubleScalar, Type>::value ||
std::is_same<complex, Type>::value,
void
>::type cmp
template<class Type1, class Type2 = Type1>
void cmp
(
const word& msg,
const Type& x,
const Type& y,
const Type1& x,
const Type2& y,
const scalar absTol = 0, //<! useful for cmps near zero
const scalar relTol = 1e-8, //<! are values the same within 8 decimals
const bool verbose = false
)
{
if (verbose)
const auto notEqual = [=](const auto& a, const auto& b) -> bool
{
Info<< msg << x << "?=" << y << endl;
}
return
(
Foam::max(absTol, relTol*Foam::max(Foam::mag(a), Foam::mag(b)))
< Foam::mag(a - b)
);
};
unsigned nFail = 0;
if (max(absTol, relTol*max(mag(x), mag(y))) < mag(x - y))
if constexpr
(
std::is_floating_point_v<Type1> || std::is_same_v<complex, Type1>
)
{
++nFail;
}
if (nFail)
{
Info<< nl
<< " #### Fail in " << nFail << " comps ####" << nl << endl;
++nFail_;
}
++nTest_;
}
// Compare two containers elementwise, and print output.
// Do ++nFail_ if two components are not equal within a given tolerance.
// The function is converted from PEP-485
template<class Type>
typename std::enable_if
<
!std::is_same<floatScalar, Type>::value &&
!std::is_same<doubleScalar, Type>::value &&
!std::is_same<complex, Type>::value,
void
>::type cmp
(
const word& msg,
const Type& x,
const Type& y,
const scalar absTol = 0,
const scalar relTol = 1e-8,
const bool verbose = false
)
{
if (verbose)
{
Info<< msg << x << "?=" << y << endl;
}
unsigned nFail = 0;
for (label i = 0; i < x.size(); ++i)
{
if (max(absTol, relTol*max(mag(x[i]), mag(y[i]))) < mag(x[i] - y[i]))
if (notEqual(x, y))
{
++nFail;
}
}
if (nFail)
else
{
Info<< nl
<< " #### Fail in " << nFail << " comps ####" << nl << endl;
++nFail_;
for (label i = 0; i < x.size(); ++i)
{
if (notEqual(x[i], y[i]))
{
++nFail;
}
}
}
++nTest_;
}
// Compare two containers elementwise, and print output.
// Do ++nFail_ if two components are not equal within a given tolerance.
// The function is converted from PEP-485
template<class Type1, class Type2>
typename std::enable_if
<
!std::is_same<floatScalar, Type1>::value &&
!std::is_same<doubleScalar, Type1>::value &&
!std::is_same<complex, Type1>::value,
void
>::type cmp
(
const word& msg,
const Type1& x,
const Type2& y,
const scalar absTol = 0,
const scalar relTol = 1e-8,
const bool verbose = false
)
{
if (verbose)
{
Info<< msg << x << "?=" << y << endl;
}
unsigned nFail = 0;
for (label i = 0; i < x.size(); ++i)
{
if (max(absTol, relTol*max(mag(x[i]), mag(y[i]))) < mag(x[i] - y[i]))
{
++nFail;
}
}
if (nFail)
{
Info<< nl
@ -321,11 +234,6 @@ void cmp
const bool verbose = false
)
{
if (verbose)
{
Info<< msg << x << "?=" << y << endl;
}
unsigned nFail = 0;
if (x != y)
@ -333,6 +241,11 @@ void cmp
++nFail;
}
if (verbose)
{
Info<< msg << x << "?=" << y << endl;
}
if (nFail)
{
Info<< nl

View File

@ -1,3 +1,3 @@
Test-Tuple2.C
Test-Tuple2.cxx
EXE = $(FOAM_USER_APPBIN)/Test-Tuple2

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2019-2020 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -32,6 +32,7 @@ Description
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "labelPair.H"
#include "Tuple2.H"
#include "label.H"
@ -102,8 +103,12 @@ void printTuple2(const Pair<word>& t)
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main()
int main(int argc, char *argv[])
{
argList::noCheckProcessorDirectories();
#include "setRootCase.H"
typedef Tuple2<label, scalar> indexedScalar;
Info<< "Default constructed Tuple: " << indexedScalar() << nl;

View File

@ -0,0 +1,3 @@
Test-UPstreamTraits.cxx
EXE = $(FOAM_USER_APPBIN)/Test-UPstreamTraits

View File

@ -0,0 +1,2 @@
/* EXE_INC = */
/* EXE_LIBS = */

View File

@ -0,0 +1,267 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Description
Simple compilation tests and access for UPstream types
\*---------------------------------------------------------------------------*/
#include "pTraits.H"
#include "contiguous.H"
#include "FixedList.H"
#include "boolVector.H" // A FixedList pretending to be a vector
#include "barycentric.H"
#include "complex.H"
#include "vector.H"
#include "tensor.H"
#include "uLabel.H"
#include "Switch.H"
#include "IOstreams.H"
#include "UPstream.H"
#include <type_traits>
using namespace Foam;
// Just for debugging
const List<std::string> dataType_names
({
"byte",
"int32",
"int64",
"uint32",
"uint64",
"float",
"double",
"long_double",
"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>
struct check_has_typeName : std::false_type {};
//- Test for pTraits zero
template<class T>
struct check_has_typeName
<
T,
std::void_t<decltype(pTraits<std::remove_cv_t<T>>::typeName)>
>
:
std::true_type
{};
// 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)
{
// Both float and double have pTraits typeName = "scalar"!
if constexpr (std::is_same_v<float, std::remove_cv_t<T>>)
{
Info<< "<float>";
}
else if constexpr (std::is_same_v<double, std::remove_cv_t<T>>)
{
Info<< "<double>";
}
else if constexpr (check_has_typeName<T>::value)
{
Info<< pTraits<std::remove_cv_t<T>>::typeName;
}
else
{
Info<< typeid(T).name();
}
if (showSize)
{
Info<< " (" << sizeof(T) << " bytes)";
}
}
template<class Type, bool UseTypeName = true>
void printPstreamTraits(const std::string_view name = std::string_view())
{
Info<< "========" << nl;
Info<< "type: ";
if (!name.empty())
{
Info<< name << ' ';
}
if constexpr (UseTypeName)
{
printTypeName<Type>(true);
}
else
{
Info<< typeid(Type).name();
Info<< " (" << sizeof(Type) << " 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;
{
int index = int(UPstream_base_dataType<Type>::datatype_id);
Info<< "datatype: " << index;
if (index < dataType_names.size())
{
Info<< ' ' << dataType_names[index];
}
Info<< nl;
}
{
// 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;
}
}
template<class BinaryOp>
void printOpCodeTraits(BinaryOp bop, std::string_view name)
{
Info<< "op: " << name << ' ';
if constexpr (UPstream_opType<BinaryOp>::value)
{
Info<< "supported";
}
else
{
Info<< "unknown";
}
Info<< ": " << int(UPstream_opType<BinaryOp>::opcode_id) << nl;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main()
{
printPstreamTraits<bool>();
printPstreamTraits<label>();
printPstreamTraits<int>("<int>");
printPstreamTraits<long>("<long>");
printPstreamTraits<unsigned>("<unsigned>");
printPstreamTraits<unsigned int>("<unsigned int>");
printPstreamTraits<unsigned long>("<long long>");
printPstreamTraits<const float>();
printPstreamTraits<floatVector>();
printPstreamTraits<scalar>();
printPstreamTraits<double>();
printPstreamTraits<doubleVector>();
// Avoid typeName for barycentric. It is declared, but not defined
printPstreamTraits<barycentric, false>("barycentric");
printPstreamTraits<complex>(); // Uses specialized pTraits_...
printPstreamTraits<boolVector>(); // Uses specialized pTraits_...
printPstreamTraits<floatVector>();
printPstreamTraits<doubleVector>();
printPstreamTraits<tensor>();
printPstreamTraits<word>();
printPstreamTraits<std::string>();
// This will not identify properly at the moment...
printPstreamTraits<FixedList<doubleVector, 4>>();
printPstreamTraits<labelPair>();
Info<< nl
<< "========" << nl
<< "Mapping of binary reduction ops" << nl;
printOpCodeTraits(minOp<scalar>{}, "min");
printOpCodeTraits(maxOp<vector>{}, "max");
printOpCodeTraits(sumOp<vector>{}, "sum");
printOpCodeTraits(plusOp<vector>{}, "plus");
printOpCodeTraits(multiplyOp<scalar>{}, "multiply");
printOpCodeTraits(divideOp<vector>{}, "divide");
printOpCodeTraits(minMagSqrOp<vector>{}, "minMagSqr");
printOpCodeTraits(bitAndOp<vector>{}, "bitAnd<vector>");
printOpCodeTraits(bitOrOp<vector>{}, "bitOr<vector>");
printOpCodeTraits(bitOrOp<float>{}, "bitOr<float>");
printOpCodeTraits(bitAndOp<unsigned>{}, "bitAnd<unsigned>");
printOpCodeTraits(bitOrOp<unsigned>{}, "bitOr<unsigned>");
Info<< nl << "End\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -123,15 +123,12 @@ int main(int argc, char *argv[])
argList::addDryRunOption("Just for testing");
argList::addVerboseOption("Increase verbosity");
// Check -verbose before initialisation
UPstream::debug = argList::verbose(argc, argv);
#include "setRootCase.H"
Pout<< "command-line ("
<< args.options().size() << " options, "
<< args.args().size() << " args)" << nl
<< " " << args.commandLine().c_str() << nl << nl;
<< " " << args.commandLine().data() << nl << nl;
Pout<< "rootPath: " << args.rootPath() << nl
<< "globalCase: " << args.globalCaseName() << nl

View File

@ -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.
@ -54,7 +54,7 @@ int main(int argc, char *argv[])
{
Info<< "boolVector" << nl
<< " size = " << boolVector::size() << nl
<< " contiguous = " << is_contiguous<boolVector>::value << nl
<< " contiguous = " << is_contiguous_v<boolVector> << nl
<< nl;
{

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018-2019 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -72,13 +72,14 @@ void printInfo(const char* const name = nullptr)
Info<< name;
}
Info<< " contiguous=" << Switch(is_contiguous<T>::value);
Info<< " contiguous=" << Switch(is_contiguous<T>::value)
<< " / " << Switch(is_contiguous_v<T>);
if (is_contiguous_label<T>::value)
if constexpr (is_contiguous_label<T>::value)
{
Info<< " label";
}
if (is_contiguous_scalar<T>::value)
if constexpr (is_contiguous_scalar<T>::value)
{
Info<< " scalar";
}
@ -96,10 +97,11 @@ int main(int argc, char *argv[])
argList::noParallel();
argList::noFunctionObjects();
printInfo<label>();
printInfo<label>();
printInfo<double>();
printInfo<FixedList<double, 4>>();
printInfo<Pair<long>>();
printInfo<const Pair<long>>();
printInfo<FixedList<word, 2>>();
printInfo<Pair<word>>();

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021-2024 OpenCFD Ltd.
Copyright (C) 2021-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
@ -122,7 +122,7 @@ int main(int argc, char *argv[])
// Regular broadcast doesn't work
Info<< "exprValue"
<< " sizeof:" << sizeof(expressions::exprValue)
<< " contiguous:" << is_contiguous<expressions::exprValue>::value
<< " contiguous:" << is_contiguous_v<expressions::exprValue>
<< nl << nl;
{

View File

@ -3,4 +3,5 @@ EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \
-lfiniteVolume
-lfiniteVolume \
-lmeshTools

View File

@ -3,4 +3,5 @@ EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \
-lfiniteVolume
-lfiniteVolume \
-lmeshTools

View File

@ -48,7 +48,7 @@ word toString(const fileOperation::procRangeType& group)
{
return word::null;
}
return Foam::name(group.first()) + "-" + Foam::name(group.last());
return Foam::name(group.min()) + "-" + Foam::name(group.max());
}

View File

@ -0,0 +1,3 @@
Test-globalIndex3.cxx
EXE = $(FOAM_USER_APPBIN)/Test-globalIndex3

View File

@ -0,0 +1,4 @@
include $(GENERAL_RULES)/mpi-rules
EXE_INC = $(PFLAGS) $(PINC)
EXE_LIBS = $(PLIBS)

View File

@ -0,0 +1,578 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Application
Test-globalIndex3
Description
Tests for globalIndex with node-wise splitting
\*---------------------------------------------------------------------------*/
#include "globalIndex.H"
#include "globalMeshData.H"
#include "argList.H"
#include "Time.H"
#include "polyMesh.H"
#include "IndirectList.H"
#include "IOstreams.H"
#include "Random.H"
#include "openfoam_mpi.H"
// pre-scan for "-split-size NUM"
int option_splitsize(int argc, char *argv[])
{
int ivalue = -1;
for (int argi = 1; argi < argc-1; ++argi)
{
if (strcmp(argv[argi], "-split-size") == 0)
{
++argi;
ivalue = atoi(argv[argi]);
}
}
return ivalue;
}
using namespace Foam;
template<class T>
void printList(Ostream& os, const UList<T>& list)
{
os << list.size() << " " << flatOutput(list) << nl;
}
void printGlobalIndex(Ostream& os, const globalIndex& gi)
{
printList(os, gi.offsets());
}
template<class ProcIDsContainer, class Type>
void globalIndexGather
(
const labelUList& off, // needed on master only
const label comm,
const ProcIDsContainer& procIDs,
const UList<Type>& fld,
UList<Type>& allFld, // must be adequately sized on master
const int tag,
UPstream::commsTypes commsType,
bool useWindow = false
)
{
// low-level: no parRun guard
const int masterProci = procIDs.size() ? procIDs[0] : 0;
// Protection for disjoint calls
if (FOAM_UNLIKELY(!UPstream::is_rank(comm)))
{
FatalErrorInFunction
<< "Calling with process not on the communicator"
<< Foam::abort(FatalError);
}
// Require contiguous data for non-blocking
if constexpr (!is_contiguous_v<Type>)
{
if (commsType == UPstream::commsTypes::nonBlocking)
{
commsType = UPstream::commsTypes::scheduled;
}
}
const label startOfRequests = UPstream::nRequests();
// Very hard-coded at the moment
int returnCode = MPI_SUCCESS;
const int nCmpts = pTraits<Type>::nComponents;
MPI_Win win;
MPI_Datatype dataType = MPI_DOUBLE;
if (useWindow)
{
using cmptType = typename pTraits<Type>::cmptType;
if (std::is_same<float, cmptType>::value)
{
dataType = MPI_FLOAT;
}
else if (std::is_same<double, cmptType>::value)
{
dataType = MPI_DOUBLE;
}
else
{
// Not supported
useWindow = false;
}
}
if (useWindow)
{
MPI_Comm mpiComm =
PstreamUtils::Cast::to_mpi(UPstream::Communicator::lookup(comm));
char commName[MPI_MAX_OBJECT_NAME];
int nameLen = 0;
if
(
MPI_COMM_NULL != mpiComm
&& MPI_SUCCESS == MPI_Comm_get_name(mpiComm, commName, &nameLen)
&& (nameLen > 0)
)
{
Pout<< "window on " << commName << nl;
}
if (UPstream::myProcNo(comm) == masterProci || fld.empty())
{
// Collective
returnCode = MPI_Win_create
(
nullptr,
0,
1, // disp_units
MPI_INFO_NULL,
mpiComm,
&win
);
}
else
{
// Collective
returnCode = MPI_Win_create
(
const_cast<char *>(fld.cdata_bytes()),
fld.size_bytes(),
sizeof(Type), // disp_units
MPI_INFO_NULL,
mpiComm,
&win
);
}
if (MPI_SUCCESS != returnCode || MPI_WIN_NULL == win)
{
FatalErrorInFunction
<< "MPI_Win_create() failed"
<< Foam::abort(FatalError);
// return nullptr;
}
}
if (UPstream::myProcNo(comm) == masterProci)
{
const label total = off.back(); // == totalSize()
if (allFld.size() < total)
{
FatalErrorInFunction
<< "[out] UList size=" << allFld.size()
<< " too small to receive " << total << nl
<< Foam::abort(FatalError);
}
// Assign my local data - respect offset information
// so that we can request 0 entries to be copied.
// Also handle the case where we have a slice of the full
// list.
{
SubList<Type> dst(allFld, off[1]-off[0], off[0]);
SubList<Type> src(fld, off[1]-off[0]);
if (!dst.empty() && (dst.data() != src.data()))
{
dst = src;
}
}
if (useWindow)
{
MPI_Win_lock_all(MPI_MODE_NOCHECK, win);
}
for (label i = 1; i < procIDs.size(); ++i)
{
SubList<Type> slot(allFld, off[i+1]-off[i], off[i]);
if (slot.empty())
{
// Nothing to do
}
else if (useWindow)
{
returnCode = MPI_Get
(
// origin
slot.data(),
slot.size()*(nCmpts),
dataType,
// target
procIDs[i],
0, // displacement
slot.size()*(nCmpts),
dataType,
win
);
if (MPI_SUCCESS != returnCode)
{
FatalErrorInFunction
<< "MPI_Get failed"
<< Foam::abort(FatalError);
// return nullptr;
}
}
else if constexpr (is_contiguous_v<Type>)
{
UIPstream::read
(
commsType,
procIDs[i],
slot,
tag,
comm
);
}
else
{
IPstream::recv(slot, procIDs[i], tag, comm);
}
}
if (useWindow)
{
MPI_Win_unlock_all(win);
}
}
else if (!useWindow)
{
if (fld.empty())
{
// Nothing to do
}
else if constexpr (is_contiguous_v<Type>)
{
UOPstream::write
(
commsType,
masterProci,
fld,
tag,
comm
);
}
else
{
OPstream::send(fld, commsType, masterProci, tag, comm);
}
}
if (useWindow)
{
// Collective
MPI_Win_free(&win);
}
if (commsType == UPstream::commsTypes::nonBlocking)
{
// Wait for outstanding requests
UPstream::waitRequests(startOfRequests);
}
}
// Report inter-node/intra-node offsets
static void reportOffsets(const globalIndex& gi)
{
labelList interNodeOffsets;
labelList localNodeOffsets;
labelRange nodeRange;
const label numProc = UPstream::nProcs(UPstream::commConstWorld());
gi.splitNodeOffsets
(
interNodeOffsets,
localNodeOffsets,
UPstream::worldComm
);
const auto interNodeComm = UPstream::commInterNode();
// Only communicate to the node leaders
labelList allOffsets;
if (UPstream::is_rank(interNodeComm))
{
// Send top-level offsets to the node leaders
if (UPstream::master(interNodeComm))
{
allOffsets = gi.offsets();
}
else // ie, UPstream::is_subrank(interNodeComm)
{
allOffsets.resize_nocopy(numProc+1);
}
UPstream::broadcast
(
allOffsets.data_bytes(),
allOffsets.size_bytes(),
interNodeComm
);
}
// Ranges (node leaders only)
if (UPstream::is_rank(interNodeComm))
{
const auto& procIds = UPstream::procID(interNodeComm);
const int ranki = UPstream::myProcNo(interNodeComm);
// For reporting
nodeRange.reset
(
procIds[ranki],
(
(ranki+1 < procIds.size() ? procIds[ranki+1] : numProc)
- procIds[ranki]
)
);
}
Pout<< "node-range: " << nodeRange << nl;
Pout<< "all-offset: "; printList(Pout, allOffsets);
Pout<< "inter-offset: "; printList(Pout, interNodeOffsets);
Pout<< "intra-offset: "; printList(Pout, localNodeOffsets);
}
template<class Type>
void globalIndexGather
(
const globalIndex& gi,
const UList<Type>& sendData,
List<Type>& allData,
const int tag,
const UPstream::commsTypes commsType,
const label comm = UPstream::worldComm,
bool useWindow = false
)
{
if (!UPstream::parRun())
{
// Serial: direct copy
allData = sendData;
return;
}
if (UPstream::master(comm))
{
allData.resize_nocopy(gi.offsets().back()); // == totalSize()
}
else
{
allData.clear(); // zero-size on non-master
}
const auto& offsets = gi.offsets(); // needed on master only
Info<< "Using node-comms: " << UPstream::usingNodeComms(comm) << nl;
const auto interNodeComm = UPstream::commInterNode();
const auto localNodeComm = UPstream::commLocalNode();
if (UPstream::usingNodeComms(comm))
{
// Stage 0 : The inter-node/intra-node offsets
labelList interNodeOffsets;
labelList localNodeOffsets;
gi.splitNodeOffsets(interNodeOffsets, localNodeOffsets, comm);
// The first node re-uses the output (allData) when collecting
// content. All other nodes require temporary node-local storage.
List<Type> tmpNodeData;
if (UPstream::is_subrank(interNodeComm))
{
tmpNodeData.resize(localNodeOffsets.back());
}
List<Type>& nodeData =
(
UPstream::master(interNodeComm) ? allData : tmpNodeData
);
// Stage 1 : Gather data within the node
{
globalIndexGather
(
localNodeOffsets, // (master only)
localNodeComm,
UPstream::allProcs(localNodeComm),
sendData,
nodeData,
tag,
commsType,
useWindow
);
}
// Stage 2 : Gather data between nodes
if (UPstream::is_rank(interNodeComm))
{
globalIndexGather
(
interNodeOffsets, // (master only)
interNodeComm,
UPstream::allProcs(interNodeComm),
nodeData,
allData,
tag,
commsType,
useWindow
);
}
}
else
{
globalIndexGather
(
offsets, // needed on master only
comm,
UPstream::allProcs(comm), // All communicator ranks
sendData,
allData,
tag,
commsType,
useWindow
);
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::noCheckProcessorDirectories();
argList::addVerboseOption("Set UPstream::debug level");
argList::addOption("split-size", "NUM", "split with ncores/node");
argList::addBoolOption("builtin", "only use builtin globalIndex::gather");
argList::addBoolOption("window", "get data via window");
// Check -verbose before initialisation
UPstream::debug = argList::verbose(argc, argv);
// Check -split-size before initialisation
{
int splitSize = option_splitsize(argc, argv);
if (splitSize >= 0)
{
UPstream::nodeCommsControl_ = splitSize;
}
}
#include "setRootCase.H"
const bool useLocalComms = UPstream::usingNodeComms();
bool useWindow = args.found("window");
bool useBuiltin = args.found("builtin");
Info<< nl
<< "Getting local-comms: " << Switch::name(useLocalComms) << nl
<< "Getting data with window: " << Switch::name(useWindow) << nl
<< nl;
if (useWindow && useBuiltin)
{
Info<< "Selected '-window' and '-builtin' : ignoring -builtin'"
<< nl;
useBuiltin = false;
}
Random rng(31 + 2*UPstream::myProcNo());
const label localSize = (5*rng.position<label>(1, 15));
globalIndex globIndex
(
globalIndex::gatherOnly{},
localSize,
UPstream::commWorld()
);
Info<< "global-index: ";
printGlobalIndex(Info, globIndex);
reportOffsets(globIndex);
Field<scalar> allData;
Field<scalar> localFld(localSize, scalar(UPstream::myProcNo()));
if (useBuiltin)
{
globIndex.gather
(
localFld,
allData,
UPstream::msgType(),
UPstream::commsTypes::nonBlocking,
UPstream::commWorld()
);
}
else
{
globalIndexGather
(
globIndex,
localFld,
allData,
UPstream::msgType(),
UPstream::commsTypes::nonBlocking,
UPstream::commWorld(),
useWindow
);
}
Pout<< "local: " << flatOutput(localFld) << nl;
Info<< "field: " << flatOutput(allData) << nl;
Info<< "\nEnd\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -31,13 +31,12 @@ Description
\*---------------------------------------------------------------------------*/
#include "complex.H"
#include "tensor.H"
#include "symmTensor.H"
#include "transform.H"
#include "unitConversion.H"
#include "Random.H"
#include "scalar.H"
#include "complex.H"
#include "sigFpe.H"
using namespace Foam;

View File

@ -3,4 +3,5 @@ EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude
EXE_LIBS = \
-lfiniteVolume
-lfiniteVolume \
-lmeshTools

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 OpenCFD Ltd.
Copyright (C) 2020-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -36,10 +36,9 @@ Description
\*---------------------------------------------------------------------------*/
#include "complex.H"
#include "DiagonalMatrix.H"
#include "RectangularMatrix.H"
#include "scalar.H"
#include "complex.H"
#include "TestTools.H"
using namespace Foam;
@ -173,24 +172,23 @@ void test_global_funcs(Type)
// Do compile-time recursion over the given types
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID){}
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID)
void run_tests(const std::tuple<Tp...>& types, const List<word>& names)
{
Info<< nl << " ## Test constructors: "<< typeID[I] <<" ##" << nl;
test_constructors(std::get<I>(types));
if constexpr (I < sizeof...(Tp))
{
const auto& name = names[I];
Info<< nl << " ## Test member functions: "<< typeID[I] <<" ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test constructors: " << name << " ##" << nl;
test_constructors(std::get<I>(types));
Info<< nl << " ## Test global functions: "<< typeID[I] << " ##" << nl;
test_global_funcs(std::get<I>(types));
Info<< nl << " ## Test member functions: " << name << " ##" << nl;
test_member_funcs(std::get<I>(types));
run_tests<I + 1, Tp...>(types, typeID);
Info<< nl << " ## Test global functions: " << name << " ##" << nl;
test_global_funcs(std::get<I>(types));
run_tests<I + 1, Tp...>(types, names);
}
}
@ -205,8 +203,8 @@ int main()
const List<word> typeID
({
"DiagonalMatrix<floatScalar>",
"DiagonalMatrix<doubleScalar>",
"DiagonalMatrix<float>",
"DiagonalMatrix<double>",
"DiagonalMatrix<complex>"
});

View File

@ -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 derivative work of OpenFOAM.
@ -36,10 +36,10 @@ Description
\*---------------------------------------------------------------------------*/
#include "complex.H"
#include "scalarMatrices.H"
#include "RectangularMatrix.H"
#include "SquareMatrix.H"
#include "complex.H"
#include "IOmanip.H"
#include "EigenMatrix.H"
#include "TestTools.H"
@ -335,27 +335,26 @@ void test_eigenvectors(Type)
// Do compile-time recursion over the given types
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID){}
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID)
void run_tests(const std::tuple<Tp...>& types, const List<word>& names)
{
Info<< nl << " ## Test constructors: "<< typeID[I] <<" ##" << nl;
test_constructors(std::get<I>(types));
if constexpr (I < sizeof...(Tp))
{
const auto& name = names[I];
Info<< nl << " ## Test member functions: "<< typeID[I] <<" ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test constructors: " << name << " ##" << nl;
test_constructors(std::get<I>(types));
Info<< nl << " ## Test eigenvalues: "<< typeID[I] <<" ##" << nl;
test_eigenvalues(std::get<I>(types));
Info<< nl << " ## Test member functions: " << name << " ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test eigenvectors: "<< typeID[I] <<" ##" << nl;
test_eigenvectors(std::get<I>(types));
Info<< nl << " ## Test eigenvalues: " << name << " ##" << nl;
test_eigenvalues(std::get<I>(types));
run_tests<I + 1, Tp...>(types, typeID);
Info<< nl << " ## Test eigenvectors: " << name << " ##" << nl;
test_eigenvectors(std::get<I>(types));
run_tests<I + 1, Tp...>(types, names);
}
}
@ -372,8 +371,8 @@ int main()
const List<word> typeID
({
"SquareMatrix<floatScalar>",
"SquareMatrix<doubleScalar>"
"SquareMatrix<float>",
"SquareMatrix<double>"
});
run_tests(types, typeID);
@ -539,3 +538,6 @@ int main()
Info<< nl << " #### Passed all " << nTest_ <<" tests ####\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -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.
@ -32,9 +32,9 @@ Description
\*---------------------------------------------------------------------------*/
#include "complex.H"
#include "MatrixTools.H"
#include "QRMatrix.H"
#include "complex.H"
#include "IOmanip.H"
#include "TestTools.H"
@ -533,21 +533,20 @@ void test_decomposition(MatrixType)
// Do compile-time recursion over the given types
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID){}
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID)
void run_tests(const std::tuple<Tp...>& types, const List<word>& names)
{
Info<< nl << " ## Test constructors: "<< typeID[I] <<" ##" << nl;
test_constructors(std::get<I>(types));
if constexpr (I < sizeof...(Tp))
{
const auto& name = names[I];
Info<< nl << " ## Test decomposition: "<< typeID[I] <<" ##" << nl;
test_decomposition(std::get<I>(types));
Info<< nl << " ## Test constructors: " << name << " ##" << nl;
test_constructors(std::get<I>(types));
run_tests<I + 1, Tp...>(types, typeID);
Info<< nl << " ## Test decomposition: " << name << " ##" << nl;
test_decomposition(std::get<I>(types));
run_tests<I + 1, Tp...>(types, names);
}
}
@ -570,9 +569,9 @@ int main()
const List<word> typeID
({
"RectangularMatrix<doubleScalar>",
"RectangularMatrix<double>",
"RectangularMatrix<complex>",
"SquareMatrix<doubleScalar>",
"SquareMatrix<double>",
"SquareMatrix<complex>"
});

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 OpenCFD Ltd.
Copyright (C) 2020-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -42,10 +42,9 @@ Note
\*---------------------------------------------------------------------------*/
#include "complex.H"
#include "RectangularMatrix.H"
#include "SquareMatrix.H"
#include "scalar.H"
#include "complex.H"
#include "IOmanip.H"
#include "TestTools.H"
@ -809,36 +808,34 @@ void test_global_opers(Type)
// Do compile-time recursion over the given types
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID){}
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID)
void run_tests(const std::tuple<Tp...>& types, const List<word>& names)
{
Info<< nl << " ## Test constructors: "<< typeID[I] <<" ##" << nl;
test_constructors(std::get<I>(types));
if constexpr (I < sizeof...(Tp))
{
const auto& name = names[I];
Info<< nl << " ## Test member functions: "<< typeID[I] <<" ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test constructors: " << name << " ##" << nl;
test_constructors(std::get<I>(types));
Info<< nl << " ## Test member opers: "<< typeID[I] <<" ##" << nl;
test_member_opers(std::get<I>(types));
Info<< nl << " ## Test member functions: " << name << " ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test global functions: "<< typeID[I] << " ##" << nl;
test_global_funcs(std::get<I>(types));
Info<< nl << " ## Test member opers: " << name << " ##" << nl;
test_member_opers(std::get<I>(types));
Info<< nl << " ## Test global operators: "<< typeID[I] << " ##" << nl;
test_global_opers(std::get<I>(types));
Info<< nl << " ## Test global functions: " << name << " ##" << nl;
test_global_funcs(std::get<I>(types));
Info<< nl << " ## Test friend funcs: "<< typeID[I] <<" ##" << nl;
test_friend_funcs(std::get<I>(types));
Info<< nl << " ## Test global operators: " << name << " ##" << nl;
test_global_opers(std::get<I>(types));
run_tests<I + 1, Tp...>(types, typeID);
Info<< nl << " ## Test friend funcs: " << name << " ##" << nl;
test_friend_funcs(std::get<I>(types));
run_tests<I + 1, Tp...>(types, names);
}
}
// * * * * * * * * * * * * * * * Main Program * * * * * * * * * * * * * * * //
int main()
@ -852,8 +849,8 @@ int main()
const List<word> typeID
({
"RectangularMatrix<floatScalar>",
"RectangularMatrix<doubleScalar>",
"RectangularMatrix<float>",
"RectangularMatrix<double>",
"RectangularMatrix<complex>"
});

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 OpenCFD Ltd.
Copyright (C) 2020-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -42,11 +42,10 @@ Note
\*---------------------------------------------------------------------------*/
#include "complex.H"
#include "scalarMatrices.H"
#include "RectangularMatrix.H"
#include "SquareMatrix.H"
#include "scalar.H"
#include "complex.H"
#include "IOmanip.H"
#include "TestTools.H"
@ -932,33 +931,32 @@ void test_global_opers(Type)
// Do compile-time recursion over the given types
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID){}
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID)
void run_tests(const std::tuple<Tp...>& types, const List<word>& names)
{
Info<< nl << " ## Test constructors: "<< typeID[I] <<" ##" << nl;
test_constructors(std::get<I>(types));
if constexpr (I < sizeof...(Tp))
{
const auto& name = names[I];
Info<< nl << " ## Test member functions: "<< typeID[I] <<" ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test constructors: " << name << " ##" << nl;
test_constructors(std::get<I>(types));
Info<< nl << " ## Test member opers: "<< typeID[I] <<" ##" << nl;
test_member_opers(std::get<I>(types));
Info<< nl << " ## Test member functions: " << name << " ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test global functions: "<< typeID[I] << " ##" << nl;
test_global_funcs(std::get<I>(types));
Info<< nl << " ## Test member opers: " << name << " ##" << nl;
test_member_opers(std::get<I>(types));
Info<< nl << " ## Test global operators: "<< typeID[I] << " ##" << nl;
test_global_opers(std::get<I>(types));
Info<< nl << " ## Test global functions: " << name << " ##" << nl;
test_global_funcs(std::get<I>(types));
Info<< nl << " ## Test friend funcs: "<< typeID[I] <<" ##" << nl;
test_friend_funcs(std::get<I>(types));
Info<< nl << " ## Test global operators: " << name << " ##" << nl;
test_global_opers(std::get<I>(types));
run_tests<I + 1, Tp...>(types, typeID);
Info<< nl << " ## Test friend funcs: " << name << " ##" << nl;
test_friend_funcs(std::get<I>(types));
run_tests<I + 1, Tp...>(types, names);
}
}
@ -975,8 +973,8 @@ int main()
const List<word> typeID
({
"SquareMatrix<floatScalar>",
"SquareMatrix<doubleScalar>",
"SquareMatrix<float>",
"SquareMatrix<double>",
"SquareMatrix<complex>"
});

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 OpenCFD Ltd.
Copyright (C) 2020-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -42,12 +42,11 @@ Note
\*---------------------------------------------------------------------------*/
#include "complex.H"
#include "scalarMatrices.H"
#include "RectangularMatrix.H"
#include "SquareMatrix.H"
#include "SymmetricSquareMatrix.H"
#include "scalar.H"
#include "complex.H"
#include "IOmanip.H"
#include "Random.H"
#include "TestTools.H"
@ -138,33 +137,32 @@ void test_global_opers(Type)
// Do compile-time recursion over the given types
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID){}
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
run_tests(const std::tuple<Tp...>& types, const List<word>& typeID)
void run_tests(const std::tuple<Tp...>& types, const List<word>& names)
{
Info<< nl << " ## Test constructors: "<< typeID[I] <<" ##" << nl;
test_constructors(std::get<I>(types));
if constexpr (I < sizeof...(Tp))
{
const auto& name = names[I];
Info<< nl << " ## Test member functions: "<< typeID[I] <<" ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test constructors: " << name << " ##" << nl;
test_constructors(std::get<I>(types));
Info<< nl << " ## Test member opers: "<< typeID[I] <<" ##" << nl;
test_member_opers(std::get<I>(types));
Info<< nl << " ## Test member functions: " << name << " ##" << nl;
test_member_funcs(std::get<I>(types));
Info<< nl << " ## Test global functions: "<< typeID[I] << " ##" << nl;
test_global_funcs(std::get<I>(types));
Info<< nl << " ## Test member opers: " << name << " ##" << nl;
test_member_opers(std::get<I>(types));
Info<< nl << " ## Test global operators: "<< typeID[I] << " ##" << nl;
test_global_opers(std::get<I>(types));
Info<< nl << " ## Test global functions: " << name << " ##" << nl;
test_global_funcs(std::get<I>(types));
Info<< nl << " ## Test friend funcs: "<< typeID[I] <<" ##" << nl;
test_friend_funcs(std::get<I>(types));
Info<< nl << " ## Test global operators: " << name << " ##" << nl;
test_global_opers(std::get<I>(types));
run_tests<I + 1, Tp...>(types, typeID);
Info<< nl << " ## Test friend funcs: " << name << " ##" << nl;
test_friend_funcs(std::get<I>(types));
run_tests<I + 1, Tp...>(types, names);
}
}
@ -181,8 +179,8 @@ int main()
const List<word> typeID
({
"SymmetricSquareMatrix<floatScalar>",
"SymmetricSquareMatrix<doubleScalar>",
"SymmetricSquareMatrix<float>",
"SymmetricSquareMatrix<double>",
"SymmetricSquareMatrix<complex>"
});

View File

@ -1,3 +1,3 @@
Test-minMax1.C
Test-minMax1.cxx
EXE = $(FOAM_USER_APPBIN)/Test-minMax1

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2023 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -170,8 +170,19 @@ int main(int argc, char *argv[])
values1 *= (Pstream::myProcNo()+1);
Pout<<"min-max of " << flatOutput(values1) << " = "
<< minMax(values1) << endl;
{
auto limits = minMax(values1);
Pout<<"min-max of " << flatOutput(values1) << " = "
<< limits << endl;
// add in some more values
limits.add(-100, 10, 1000, 500, 800);
limits.add(-120, 1200);
Pout<<"with more values: " << limits << endl;
}
// Construct from values
MinMax<scalar> minmax1(values1);
@ -182,10 +193,7 @@ int main(int argc, char *argv[])
minmax1 += values1;
Pout<<"range: " << minmax1 << endl;
Info<< "Reduced: "<< returnReduce(minmax1, plusOp<scalarMinMax>()) << nl;
Info<< "Reduced: "<< returnReduce(minmax1, minMaxOp<scalar>()) << nl;
// Info<< "gMinMax: "<< gMinMax(values1v) << nl;

View File

@ -1,3 +1,3 @@
Test-minMax2.C
Test-minMax2.cxx
EXE = $(FOAM_USER_APPBIN)/Test-minMax2

View File

@ -0,0 +1,3 @@
Test-nodeTopology.cxx
EXE = $(FOAM_USER_APPBIN)/Test-nodeTopology

View File

@ -0,0 +1,2 @@
/* EXE_INC = */
/* EXE_LIBS = */

View File

@ -0,0 +1,165 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Application
Test-nodeTopology
Description
Simple reporting of node topology
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "IOstreams.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::noBanner();
argList::noCheckProcessorDirectories();
argList::addOption
(
"numProcs",
"int",
"Num of ranks to simulate (default: 16)"
);
argList::addOption
(
"cores",
"int",
"Num of cores to simulate (default: 4)"
);
#include "setRootCase.H"
label nProcs = UPstream::nProcs(UPstream::worldComm);
DynamicList<int> fake_interNode_offsets;
if (UPstream::parRun())
{
if (args.found("numProcs"))
{
InfoErr<< "ignoring -numProcs option in parallel" << nl;
}
if (args.found("cores"))
{
InfoErr<< "ignoring -cores option in parallel" << nl;
}
}
else
{
// serial
nProcs = args.getOrDefault<label>("numProcs", 16);
label nCores = args.getOrDefault<label>("cores", 4);
auto& interNode_offsets = fake_interNode_offsets;
if (nCores > 1 && nCores < nProcs)
{
// Build the inter-node offsets
interNode_offsets.reserve((nProcs/nCores) + 4);
interNode_offsets.push_back(0);
for
(
int count = interNode_offsets.back() + nCores;
count < nProcs;
count += nCores
)
{
interNode_offsets.push_back(count);
}
interNode_offsets.push_back(nProcs);
}
else
{
// Some fallback
interNode_offsets.reserve(2);
interNode_offsets.push_back(0);
interNode_offsets.push_back(nProcs);
}
}
const List<int>& interNodeOffsets =
(
UPstream::parRun()
? UPstream::interNode_offsets()
: fake_interNode_offsets
);
// Generate the graph
if (UPstream::master(UPstream::worldComm))
{
auto& os = Info.stream();
os << "// node topology graph:" << nl;
os.beginBlock("graph");
// Prefer left-to-right layout for large graphs
os << indent << "rankdir=LR" << nl;
const label numNodes = interNodeOffsets.size()-1;
// First level are the inter-node connections
{
os << indent << 0 << " -- " << token::LBRACE;
for (label nodei = 1; nodei < numNodes; ++nodei)
{
os << ' ' << interNodeOffsets[nodei];
}
os << token::SPACE << token::RBRACE
<< " // inter-node: " << flatOutput(interNodeOffsets)
<< nl;
}
// Next level are the local-node connections
for (label nodei = 0; nodei < numNodes; ++nodei)
{
const auto firstProc = interNodeOffsets[nodei];
const auto lastProc = interNodeOffsets[nodei+1];
os << indent << firstProc << " -- " << token::DQUOTE
<< (firstProc+1) << ".." << (lastProc-1)
<< token::DQUOTE << nl;
}
os.endBlock();
os << "// end graph" << nl;
}
InfoErr << "\nDone" << nl;
return 0;
}
// ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2023 OpenCFD Ltd.
Copyright (C) 2023-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -32,9 +32,11 @@ Description
#include "pTraits.H"
#include "contiguous.H"
#include "boolVector.H" // A FixedList pretending to be a vector
#include "complex.H"
#include "vector.H"
#include "tensor.H"
#include "complex.H"
#include "sphericalTensor.H"
#include "symmTensor.H"
#include "uLabel.H"
#include "Switch.H"
@ -50,26 +52,37 @@ template<class T, class = void>
struct has_typeName : std::false_type {};
//- Test if Type has typeName member
template<class T>
struct has_typeName<T, stdFoam::void_t<decltype(pTraits<T>::typeName)>>
struct has_typeName
<
T,
std::void_t<decltype(pTraits<std::remove_cv_t<T>>::typeName)>
>
:
std::true_type
{};
template<class T>
typename std::enable_if<has_typeName<T>::value, void>::type
printTypeName()
void printTypeName()
{
Info<< pTraits<T>::typeName;
}
template<class T>
typename std::enable_if<!has_typeName<T>::value, void>::type
printTypeName()
{
Info<< typeid(T).name();
// Both float and double have pTraits typeName = "scalar"!
if constexpr (std::is_same_v<float, std::remove_cv_t<T>>)
{
Info<< "<float>";
}
else if constexpr (std::is_same_v<double, std::remove_cv_t<T>>)
{
Info<< "<double>";
}
else if constexpr (has_typeName<T>::value)
{
Info<< pTraits<std::remove_cv_t<T>>::typeName;
}
else
{
Info<< typeid(T).name();
}
}
@ -80,23 +93,24 @@ template<class T>
struct has_zero_one
<
T,
stdFoam::void_t<decltype(pTraits<T>::zero), decltype(pTraits<T>::one)>
std::void_t
<
decltype(pTraits<std::remove_cv_t<T>>::zero),
decltype(pTraits<std::remove_cv_t<T>>::one)
>
> : std::true_type {};
template<class T>
typename std::enable_if<has_zero_one<T>::value, void>::type
printMinMaxRange()
void printMinMaxRange()
{
Info<< " zero=" << pTraits<T>::zero
<< " one=" << pTraits<T>::one;
if constexpr (has_zero_one<T>::value)
{
Info<< " zero=" << pTraits<std::remove_cv_t<T>>::zero
<< " one=" << pTraits<std::remove_cv_t<T>>::one;
}
}
template<class T>
typename std::enable_if<!has_zero_one<T>::value, void>::type
printMinMaxRange()
{}
template<class T>
void printTraits()
@ -104,11 +118,12 @@ void printTraits()
printTypeName<T>();
printMinMaxRange<T>();
Info<< " integral=" << std::is_integral<T>::value
<< " floating=" << std::is_floating_point<T>::value
Info<< " integral=" << std::is_integral_v<T>
<< " floating=" << std::is_floating_point_v<T>
<< " rank=" << pTraits_rank<T>::value
<< " nComponents=" << pTraits_nComponents<T>::value
<< " vector-space=" << Switch::name(is_vectorspace<T>::value)
<< " vector-space=" << Switch::name(is_vectorspace_v<T>)
<< " rotate=" << Switch::name(is_rotational_vectorspace_v<T>)
<< " is_label=" << Switch::name(is_contiguous_label<T>::value)
<< " is_scalar=" << Switch::name(is_contiguous_scalar<T>::value)
<< " cmptType=" << typeid(typename pTraits_cmptType<T>::type).name()
@ -137,9 +152,11 @@ int main()
printTraits<bool>();
printTraits<label>();
printTraits<scalar>();
printTraits<complex>(); // Uses specialized pTraits_...
printTraits<const complex>(); // Uses specialized pTraits_...
printTraits<floatVector>();
printTraits<doubleVector>();
printTraits<sphericalTensor>();
printTraits<symmTensor>();
printTraits<tensor>();
printTraits<boolVector>(); // Uses specialized pTraits_...
printTraits<word>();

View File

@ -0,0 +1,3 @@
Test-parallel-barrier1.cxx
EXE = $(FOAM_USER_APPBIN)/Test-parallel-barrier1

View File

@ -0,0 +1,2 @@
/* EXE_INC = */
/* EXE_LIBS = */

View File

@ -0,0 +1,125 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Application
Test-parallel-barrier1
Description
Simple test of local barriers communication
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "clockTime.H"
#include "IPstream.H"
#include "OPstream.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::noCheckProcessorDirectories();
argList::addVerboseOption();
argList::addOption("delay", "sec", "Seconds to sleep (default 2)");
#include "setRootCase.H"
if (!UPstream::parRun())
{
Info<< "###############" << nl
<< "Not running in parallel. Stopping now" << nl
<< "###############" << endl;
return 1;
}
const auto delay = args.getOrDefault<label>("delay", 2);
Info<< nl
<< "Testing local barrier, sleep=" << delay << endl;
const auto myProci = UPstream::myProcNo(UPstream::worldComm);
const auto numProc = UPstream::nProcs(UPstream::worldComm);
constexpr int uniqTag = 1516;
clockTime timing;
if (UPstream::master(UPstream::worldComm))
{
// Wait for the last rank
UPstream::wait_done(numProc-1, UPstream::worldComm);
// Wait for any other rank
if (numProc > 2)
{
int from = UPstream::wait_done(-1, UPstream::worldComm, uniqTag);
Pout<< "done signal from: " << from << endl;
}
}
else if (myProci == numProc-1)
{
Foam::sleep(delay);
UPstream::send_done(UPstream::masterNo(), UPstream::worldComm);
}
// Cascade sequencing (and delays)
if (numProc > 7)
{
if (myProci == 2)
{
Foam::sleep(2*delay);
UPstream::send_done(4, UPstream::worldComm);
}
else if (myProci == 4)
{
UPstream::wait_done(2, UPstream::worldComm);
Foam::sleep(2*delay);
UPstream::send_done(5, UPstream::worldComm);
}
else if (myProci == 5)
{
UPstream::wait_done(4, UPstream::worldComm);
}
}
// Some arbitrary signaling rank
if ((numProc > 2) && (myProci == numProc/2))
{
Pout<< "send done signal " << myProci << " -> 0" << endl;
UPstream::send_done(UPstream::masterNo(), UPstream::worldComm, uniqTag);
}
Pout<< "done: " << timing.elapsedTime() << " s" << endl;
Info<< "\nEnd\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -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.
@ -46,7 +46,7 @@ using namespace Foam;
template<class T>
void printPre(const T& value)
{
Info<< nl << "is_contiguous:" << is_contiguous<T>::value << endl;
Info<< nl << "is_contiguous:" << is_contiguous_v<T> << endl;
Pout<< "pre-broadcast: " << value << endl;
}
@ -68,7 +68,7 @@ void testBroadcast(T& value)
template<class T>
void testBroadcast(List<T>& values)
{
Info<< nl << "is_contiguous:" << is_contiguous<T>::value << endl;
Info<< nl << "is_contiguous:" << is_contiguous_v<T> << endl;
Pout<< "pre-broadcast: " << flatOutput(values) << endl;
Pstream::broadcast(values);
Pout<< "post-broadcast: " << flatOutput(values) << endl;

View File

@ -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.
@ -44,55 +44,17 @@ Description
using namespace Foam;
//- Number of elements corresponding to max byte transfer.
// Normal upper limit is INT_MAX since MPI sizes are limited to <int>.
template<class Type>
inline std::size_t maxTransferCount
(
const std::size_t max_bytes = std::size_t(0)
) noexcept
{
return
(
(max_bytes == 0) // ie, unlimited
? (std::size_t(0)) //
: (max_bytes > std::size_t(INT_MAX)) // MPI limit is <int>
? (std::size_t(INT_MAX) / sizeof(Type)) //
: (max_bytes > sizeof(Type)) // require an integral number
? (max_bytes / sizeof(Type)) //
: (std::size_t(1)) // min of one element
);
}
//- Upper limit on number of transfer bytes.
// Max bytes is normally INT_MAX since MPI sizes are limited to <int>.
// Negative values indicate a subtraction from INT_MAX.
inline std::size_t PstreamDetail_maxTransferBytes
(
const int64_t max_bytes
) noexcept
{
return
(
(max_bytes < 0) // (numBytes fewer than INT_MAX)
? std::size_t(INT_MAX + max_bytes)
: std::size_t(max_bytes)
);
}
template<class Container, class Type>
void broadcast_chunks
(
Container& sendData,
const int tag = UPstream::msgType(),
const label comm = UPstream::worldComm
const label comm = UPstream::worldComm,
const int64_t maxComms_bytes = UPstream::maxCommsSize
)
{
// OR static_assert(is_contiguous<T>::value, "Contiguous data only!")
if (!is_contiguous<Type>::value)
// OR static_assert(is_contiguous_v<Type>, "Contiguous data only!")
if constexpr (!is_contiguous_v<Type>)
{
FatalErrorInFunction
<< "Contiguous data only." << sizeof(Type)
@ -119,9 +81,9 @@ void broadcast_chunks
// Is zero for non-chunked exchanges.
const std::size_t chunkSize
(
PstreamDetail_maxTransferCount<Type>
PstreamDetail::maxTransferCount<Type>
(
PstreamDetail_maxTransferBytes(maxComms_bytes)
PstreamDetail::maxTransferBytes(maxComms_bytes)
)
);

View File

@ -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.
@ -67,10 +67,6 @@ int main(int argc, char *argv[])
{
argList::noBanner();
argList::noCheckProcessorDirectories();
argList::addVerboseOption("Set UPstream::debug level");
// Check -verbose before initialisation
UPstream::debug = argList::verbose(argc, argv);
#include "setRootCase.H"

View File

@ -158,7 +158,7 @@ int main(int argc, char *argv[])
for (label count = 0; count < repeat; ++count)
{
label comm = UPstream::allocateCommunicator(UPstream::worldComm, top);
label comm = UPstream::newCommunicator(UPstream::worldComm, top);
scalar localValue = 111*UPstream::myProcNo(UPstream::worldComm);

View File

@ -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.
@ -66,20 +66,16 @@ int main(int argc, char *argv[])
{
argList::noBanner();
argList::noCheckProcessorDirectories();
argList::addVerboseOption("Set UPstream::debug level");
argList::addBoolOption("info", "information");
argList::addBoolOption("print-tree", "Report tree(s) as graph");
argList::addBoolOption("comm-split", "Test simple comm split");
argList::addBoolOption("mpi-host-comm", "Test DIY host-comm split");
argList::addBoolOption("no-test", "Disable general tests");
argList::addBoolOption("host-comm", "Test Pstream host-comm");
argList::addBoolOption("host-broadcast", "Test host-base broadcasts");
// Check -verbose before initialisation
UPstream::debug = argList::verbose(argc, argv);
#include "setRootCase.H"
const bool optPrintTree = args.found("print-tree");
bool generalTest = !args.found("no-test");
Info<< nl
<< "parallel:" << UPstream::parRun()
@ -89,10 +85,23 @@ int main(int argc, char *argv[])
if (UPstream::parRun() && optPrintTree)
{
Info<< "comms: " << UPstream::whichCommunication() << endl;
Info<< "comms: "
<< UPstream::whichCommunication(UPstream::worldComm) << nl;
UPstream::printCommTree(UPstream::commWorld());
}
if (UPstream::parRun())
{
Pout<< "world ranks: 0.."
<< UPstream::nProcs(UPstream::commWorld())-1 << nl;
Pout<< "inter-node ranks: " << UPstream::numNodes() << ' '
<< flatOutput(UPstream::procID(UPstream::commInterNode())) << nl;
Pout<< "local-node ranks: "
<< flatOutput(UPstream::procID(UPstream::commLocalNode())) << nl;
}
if (args.found("info"))
{
Info<< nl;
@ -108,334 +117,29 @@ int main(int argc, char *argv[])
Pout<< endl;
}
bool generalTest = true;
if (UPstream::parRun() && args.found("comm-split"))
{
generalTest = false;
int world_nprocs = 0;
int world_rank = -1;
MPI_Comm_size(MPI_COMM_WORLD, &world_nprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
int host_nprocs = 0;
int host_rank = -1;
MPI_Comm commIntraHost;
MPI_Comm_split_type
(
MPI_COMM_WORLD,
MPI_COMM_TYPE_SHARED, // OMPI_COMM_TYPE_NODE
0, MPI_INFO_NULL, &commIntraHost
);
MPI_Comm_size(commIntraHost, &host_nprocs);
MPI_Comm_rank(commIntraHost, &host_rank);
int leader_nprocs = 0;
int leader_rank = -1;
MPI_Comm commInterHost;
if (false)
{
// Easy enough to use MPI_Comm_split, but slightly annoying
// that it returns MPI_COMM_NULL for unused ranks...
MPI_Comm commInterHost;
MPI_Comm_split
(
MPI_COMM_WORLD,
(host_rank == 0) ? 0 : MPI_UNDEFINED,
0, &commInterHost
);
if (commInterHost != MPI_COMM_NULL)
{
MPI_Comm_size(commInterHost, &leader_nprocs);
MPI_Comm_rank(commInterHost, &leader_rank);
}
}
else
{
boolList isHostLeader(world_nprocs, false);
isHostLeader[world_rank] = (host_rank == 0);
MPI_Allgather
(
// recv is also send
MPI_IN_PLACE, 1, MPI_C_BOOL,
isHostLeader.data(), 1, MPI_C_BOOL,
MPI_COMM_WORLD
);
Pout<< "leaders: " << isHostLeader << endl;
DynamicList<int> subRanks(isHostLeader.size());
forAll(isHostLeader, proci)
{
if (isHostLeader[proci])
{
subRanks.push_back(proci);
}
}
// Starting from parent
MPI_Group parent_group;
MPI_Comm_group(MPI_COMM_WORLD, &parent_group);
MPI_Group active_group;
MPI_Group_incl
(
parent_group,
subRanks.size(),
subRanks.cdata(),
&active_group
);
// Create new communicator for this group
MPI_Comm_create_group
(
MPI_COMM_WORLD,
active_group,
UPstream::msgType(),
&commInterHost
);
// Groups not needed after this...
MPI_Group_free(&parent_group);
MPI_Group_free(&active_group);
MPI_Comm_size(commInterHost, &leader_nprocs);
MPI_Comm_rank(commInterHost, &leader_rank);
}
Pout<< nl << "[MPI_Comm_split_type]" << nl
<< "Host rank " << host_rank << " / " << host_nprocs
<< " on " << hostName()
<< " inter-rank: " << leader_rank << " / " << leader_nprocs
<< " host leader:" << (leader_rank == 0)
<< " sub-rank:" << (leader_rank > 0)
<< nl;
if (commInterHost != MPI_COMM_NULL)
{
MPI_Comm_free(&commInterHost);
}
if (commIntraHost != MPI_COMM_NULL)
{
MPI_Comm_free(&commIntraHost);
}
}
if (UPstream::parRun() && args.found("mpi-host-comm"))
{
generalTest = false;
// Host communicator, based on the current world communicator
// Use hostname
// Lowest rank per hostname is the IO rank
label numprocs = UPstream::nProcs(UPstream::commGlobal());
// Option 1: using hostnames
// - pro: trivial coding
// - con: unequal lengths, more allocations and 'hops'
stringList hosts(numprocs);
hosts[Pstream::myProcNo(UPstream::commGlobal())] = hostName();
Pstream::gatherList(hosts, UPstream::msgType(), UPstream::commGlobal());
// Option 2: using SHA1 of hostnames
// - con: uglier coding (but only needed locally!)
// - pro: fixed digest length enables direct MPI calls
// can avoid Pstream::gatherList() during setup...
List<SHA1Digest> digests;
if (UPstream::master(UPstream::commGlobal()))
{
digests.resize(numprocs);
}
{
const SHA1Digest myDigest(SHA1(hostName()).digest());
UPstream::mpiGather
(
myDigest.cdata_bytes(), // Send
digests.data_bytes(), // Recv
SHA1Digest::max_size(), // Num send/recv per rank
UPstream::commGlobal()
);
}
labelList hostIDs(numprocs);
DynamicList<label> subRanks(numprocs);
Info<< "digests: " << digests << nl;
// Compact numbering
if (UPstream::master(UPstream::commGlobal()))
{
DynamicList<word> hostNames(numprocs);
forAll(hosts, proci)
{
const word& host = hosts[proci];
hostIDs[proci] = hostNames.find(host);
if (hostIDs[proci] < 0)
{
// First appearance of host (encode as leader)
hostIDs[proci] = -(hostNames.size() + 1);
hostNames.push_back(host);
}
}
hostIDs = -1;
DynamicList<SHA1Digest> uniqDigests(numprocs);
forAll(digests, proci)
{
const SHA1Digest& dig = digests[proci];
hostIDs[proci] = uniqDigests.find(dig);
if (hostIDs[proci] < 0)
{
// First appearance of host (encode as leader)
hostIDs[proci] = -(uniqDigests.size() + 1);
uniqDigests.push_back(dig);
}
}
}
Info<< "hosts = " << hosts << endl;
Info<< "hostIDs = " << hostIDs << endl;
UPstream::broadcast
(
hostIDs.data_bytes(),
hostIDs.size_bytes(),
UPstream::commGlobal(),
UPstream::masterNo()
);
// Ranks for world to inter-host communicator
// - very straightforward
#if 0
subRanks.clear();
forAll(hostIDs, proci)
{
// Is host leader?
if (hostIDs[proci] < 0)
{
subRanks.push_back(proci);
// Flip back to generic host id
hostIDs[proci] = -(hostIDs[proci] + 1);
}
}
// From world to hostMaster
const label commInterHost =
UPstream::allocateCommunicator(UPstream::commGlobal(), subRanks);
#endif
const label myWorldProci = UPstream::myProcNo(UPstream::commGlobal());
label myHostId = hostIDs[myWorldProci];
if (myHostId < 0) myHostId = -(myHostId + 1); // Flip to generic id
// Ranks for within a host
subRanks.clear();
forAll(hostIDs, proci)
{
label id = hostIDs[proci];
if (id < 0) id = -(id + 1); // Flip to generic id
if (id == myHostId)
{
subRanks.push_back(proci);
}
}
// The intra-host ranks
const label commIntraHost =
UPstream::allocateCommunicator(UPstream::commGlobal(), subRanks);
// Test what if we have intra-host comm and we want host-master
List<bool> isHostMaster(numprocs, false);
if (UPstream::master(commIntraHost))
{
isHostMaster[myWorldProci] = true;
}
UPstream::mpiAllGather
(
isHostMaster.data_bytes(),
sizeof(bool),
UPstream::commGlobal()
);
// Ranks for world to hostMaster
// - very straightforward
subRanks.clear();
forAll(isHostMaster, proci)
{
if (isHostMaster[proci])
{
subRanks.push_back(proci);
}
}
// From world to hostMaster
const label commInterHost =
UPstream::allocateCommunicator(UPstream::commGlobal(), subRanks);
Pout<< nl << "[manual split]" << nl
<< nl << "Host rank " << UPstream::myProcNo(commIntraHost)
<< " / " << UPstream::nProcs(commIntraHost)
<< " on " << hostName()
<< ", inter-rank: " << UPstream::myProcNo(commInterHost)
<< " / " << UPstream::nProcs(commInterHost)
<< " host leader:" << UPstream::master(commInterHost)
<< " sub-rank:" << UPstream::is_subrank(commInterHost)
<< nl;
UPstream::freeCommunicator(commInterHost);
UPstream::freeCommunicator(commIntraHost);
}
if (UPstream::parRun() && args.found("host-comm"))
{
generalTest = false;
Info<< nl << "[pstream host-comm]" << nl << endl;
const label commInterHost = UPstream::commInterHost();
const label commIntraHost = UPstream::commIntraHost();
const label commInterNode = UPstream::commInterNode();
const label commLocalNode = UPstream::commLocalNode();
Pout<< "Host rank " << UPstream::myProcNo(commIntraHost)
<< " / " << UPstream::nProcs(commIntraHost)
Pout<< "Host rank " << UPstream::myProcNo(commLocalNode)
<< " / " << UPstream::nProcs(commLocalNode)
<< " on " << hostName()
<< ", inter-rank: " << UPstream::myProcNo(commInterHost)
<< " / " << UPstream::nProcs(commInterHost)
<< ", host leader:" << UPstream::master(commInterHost)
<< " sub-rank:" << UPstream::is_subrank(commInterHost)
<< ", inter-rank: " << UPstream::myProcNo(commInterNode)
<< " / " << UPstream::nProcs(commInterNode)
<< ", host leader:" << UPstream::master(commInterNode)
<< " sub-rank:" << UPstream::is_subrank(commInterNode)
<< endl;
{
Info<< "host-master: "
<< UPstream::whichCommunication(commInterHost) << endl;
<< UPstream::whichCommunication(commInterNode) << endl;
UPstream::printCommTree(commInterHost);
UPstream::printCommTree(commIntraHost);
UPstream::printCommTree(commInterNode);
UPstream::printCommTree(commLocalNode);
}
}
@ -444,32 +148,32 @@ int main(int argc, char *argv[])
generalTest = false;
Info<< nl << "[pstream host-broadcast]" << nl << endl;
const label commInterHost = UPstream::commInterHost();
const label commIntraHost = UPstream::commIntraHost();
const label commInterNode = UPstream::commInterNode();
const label commLocalNode = UPstream::commLocalNode();
Pout<< "world rank: " << UPstream::myProcNo(UPstream::commWorld())
<< " host-leader rank: "
<< UPstream::myProcNo(UPstream::commInterHost())
<< UPstream::myProcNo(UPstream::commInterNode())
<< " intra-host rank: "
<< UPstream::myProcNo(UPstream::commIntraHost())
<< UPstream::myProcNo(UPstream::commLocalNode())
<< endl;
label value1(0), value2(0), value3(0);
label hostIndex = UPstream::myProcNo(commInterHost);
label hostIndex = UPstream::myProcNo(commInterNode);
if (UPstream::master(commInterHost))
if (UPstream::master(commInterNode))
{
value1 = 100;
value2 = 200;
}
if (UPstream::master(commIntraHost))
if (UPstream::master(commLocalNode))
{
value3 = 300;
}
Pstream::broadcast(value1, commInterHost);
Pstream::broadcast(value2, commIntraHost);
Pstream::broadcast(hostIndex, commIntraHost);
Pstream::broadcast(value1, commInterNode);
Pstream::broadcast(value2, commLocalNode);
Pstream::broadcast(hostIndex, commLocalNode);
Pout<< "host: " << hostIndex
<< " broadcast 1: "
@ -478,7 +182,7 @@ int main(int argc, char *argv[])
<< value3 << endl;
// re-broadcast
Pstream::broadcast(value1, commIntraHost);
Pstream::broadcast(value1, commLocalNode);
Pout<< "host: " << hostIndex
<< " broadcast 2: "
<< value1 << endl;
@ -487,42 +191,42 @@ int main(int argc, char *argv[])
label reduced1 = value1;
label reduced2 = value1;
reduce
Foam::reduce
(
reduced1,
sumOp<label>(),
UPstream::msgType(),
commIntraHost
commLocalNode
);
reduce
Foam::reduce
(
reduced2,
sumOp<label>(),
UPstream::msgType(),
commInterHost
commInterNode
);
Pout<< "value1: (host) " << reduced1
<< " (leader) " << reduced2 << endl;
// Pout<< "ranks: " << UPstream::nProcs(commInterHost) << endl;
// Pout<< "ranks: " << UPstream::nProcs(commInterNode) << endl;
wordList strings;
if (UPstream::is_rank(commInterHost))
if (UPstream::is_rank(commInterNode))
{
strings.resize(UPstream::nProcs(commInterHost));
strings[UPstream::myProcNo(commInterHost)] = name(pid());
strings.resize(UPstream::nProcs(commInterNode));
strings[UPstream::myProcNo(commInterNode)] = name(pid());
}
// Some basic gather/scatter
Pstream::allGatherList(strings, UPstream::msgType(), commInterHost);
Pstream::allGatherList(strings, UPstream::msgType(), commInterNode);
Pout<< "pids " << flatOutput(strings) << endl;
Foam::reverse(strings);
Pstream::broadcast(strings, commIntraHost);
Pstream::broadcast(strings, commLocalNode);
Pout<< "PIDS " << flatOutput(strings) << endl;
}

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2023 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -125,13 +125,16 @@ int main(int argc, char *argv[])
argList::addVerboseOption("Set UPstream::debug level");
// Check -verbose before initialisation
UPstream::debug = argList::verbose(argc, argv);
if (!UPstream::debug)
{
UPstream::debug = argList::verbose(argc, argv);
}
startMPI();
#include "setRootCase.H"
Pout<< message().c_str();
Pout<< message().data();
stopMPI();

View File

@ -7,6 +7,7 @@ EXE_INC = \
EXE_LIBS = \
-lfiniteVolume \
-lmeshTools \
-ldynamicFvMesh \
-lsampling \
-loverset

View File

@ -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.
@ -44,19 +44,15 @@ using namespace Foam;
int main(int argc, char *argv[])
{
argList::noFunctionObjects();
argList::addVerboseOption("Set UPstream::debug level");
argList::addBoolOption("comm-graph", "Test simple graph communicator");
argList::addNote
(
"Create graph of OpenFOAM mesh connections"
);
// Check -verbose before initialisation
UPstream::debug = argList::verbose(argc, argv);
#include "setRootCase.H"
if (!Pstream::parRun())
if (!UPstream::parRun())
{
FatalErrorInFunction
<< "Only meaningful in parallel"

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020-2023 OpenCFD Ltd.
Copyright (C) 2020-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
@ -36,13 +36,13 @@ template<class T>
void constructInfo()
{
Info<< " move-constructible:"
<< std::is_move_constructible<T>::value
<< std::is_move_constructible_v<T>
<< " move-assignable:"
<< std::is_move_assignable<T>::value
<< std::is_move_assignable_v<T>
<< " nothrow:"
<< std::is_nothrow_move_assignable<T>::value
<< std::is_nothrow_move_assignable_v<T>
<< " trivially:"
<< std::is_trivially_move_assignable<T>::value
<< std::is_trivially_move_assignable_v<T>
<< nl;
}

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2021 OpenCFD Ltd.
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -322,12 +322,12 @@ int main(int argc, char *argv[])
Info<< "_GLIBCXX_RELEASE = " << (_GLIBCXX_RELEASE) << nl;
#endif
if (std::is_same<regExp, regExpCxx>::value)
if constexpr (std::is_same_v<regExp, regExpCxx>)
{
Info<< "Foam::regExp uses C++11 regex" << nl;
}
#ifndef _WIN32
if (std::is_same<regExp, regExpPosix>::value)
if constexpr (std::is_same_v<regExp, regExpPosix>)
{
Info<< "Foam::regExp uses POSIX regex" << nl;
}

View File

@ -53,6 +53,27 @@ namespace Foam
{}
};
// Test compilation with static_assert workaround
// (workaround before CWG2518)
template<class T>
inline unsigned sizeof_float()
{
if constexpr (std::is_floating_point_v<T>)
{
return sizeof(T);
}
else
{
// static_assert(false, "only use for floats");
static_assert
(
stdFoam::dependent_false_v<T>,
"only use for floats"
);
return 0u;
}
}
}

View File

@ -2,4 +2,4 @@ EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/mesh/blockMesh/lnInclude
EXE_LIBS = -lblockMesh
EXE_LIBS = -lblockMesh -lmeshTools

View File

@ -3,4 +3,5 @@ EXE_INC = \
-I$(LIB_SRC)/surfMesh/lnInclude
EXE_LIBS = \
-lfileFormats \
-lsurfMesh

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018-2023 OpenCFD Ltd.
Copyright (C) 2018-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
@ -45,13 +45,13 @@ void printInfo(const tmp<T>& item, const bool verbose = false)
}
Info<< " move-constructible:"
<< std::is_move_constructible<tmp<T>>::value
<< std::is_move_constructible_v<tmp<T>>
<< " move-assignable:"
<< std::is_move_assignable<tmp<T>>::value
<< std::is_move_assignable_v<tmp<T>>
<< " nothrow:"
<< std::is_nothrow_move_assignable<tmp<T>>::value
<< std::is_nothrow_move_assignable_v<tmp<T>>
<< " trivially:"
<< std::is_trivially_move_assignable<tmp<T>>::value
<< std::is_trivially_move_assignable_v<tmp<T>>
<< nl;
if (verbose && item)

View File

@ -51,7 +51,7 @@ void printConnection(Ostream& os, const label proci, const labelUList& below)
// The number of receives - as per gatherList (v2112)
void printRecvCount_gatherList
(
const UList<UPstream::commsStruct>& comms,
const UPstream::commsStructList& comms,
const label comm = UPstream::worldComm
)
{
@ -91,7 +91,7 @@ void printRecvCount_gatherList
// The number of sends - as per scatterList (v2112)
void printSendCount_scatterList
(
const UList<UPstream::commsStruct>& comms,
const UPstream::commsStructList& comms,
const label comm = UPstream::worldComm
)
{
@ -131,7 +131,7 @@ void printSendCount_scatterList
// Transmission widths (contiguous data)
void printWidths
(
const UList<UPstream::commsStruct>& comms,
const UPstream::commsStructList& comms,
const label comm = UPstream::worldComm
)
{

View File

@ -31,8 +31,9 @@ void test(const vector& a, const vector& b, const scalar tolerance)
int main()
{
vector a(1.0, 1.0, 1.0);
vector b(2.0, 2.0, 2.0);
vector a(vector::uniform(1));
vector b;
b.fill(2);
test(a, b, 0.0);
test(a, b, VSMALL);
@ -67,5 +68,9 @@ int main()
test(a, b, 1e-3);
test(a, b, 1e-1);
Info<< "\nEnd\n" << nl;
return 0;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -231,7 +231,7 @@ int main(int argc, char *argv[])
Info<< nl
<< "solverPerformanceDict: "
<< mesh.solverPerformanceDict() << endl;
<< mesh.data().solverPerformanceDict() << endl;
if (args.found("zip"))

View File

@ -8,5 +8,6 @@ EXE_INC = \
EXE_LIBS = \
-lfiniteVolume \
-lgenericPatchFields \
-lfileFormats \
-lmeshTools \
-lconversion -lccm

View File

@ -7,4 +7,6 @@ EXE_INC = \
EXE_LIBS = \
-lfiniteVolume \
-lgenericPatchFields \
-lfileFormats \
-lmeshTools \
-lconversion -lccm

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2015-2024 OpenCFD Ltd.
Copyright (C) 2015-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -1520,6 +1520,10 @@ int main(int argc, char *argv[])
const bool adaptMesh(dict.get<bool>("adaptMesh"));
const bool addSidePatches(dict.getOrDefault<bool>("addSidePatches", true));
if (hasZones)
{
Info<< "Extruding zones " << zoneNames
@ -1564,6 +1568,15 @@ int main(int argc, char *argv[])
}
if (addSidePatches && zoneNames.size() > 1)
{
Info<< "Extruding edges on more than one faceZone into boundary faces"
<< endl;
}
else
{
Info<< "Extruding internal edges into internal faces" << endl;
}
//// Read objects in time directory
@ -1918,7 +1931,12 @@ int main(int argc, char *argv[])
edgeMaxZoneID
);
if (!addSidePatches)
{
// Disabling inter-zone multiple boundary faces by setting 'left' and
// 'right' zone to be the same
edgeMaxZoneID = edgeMinZoneID;
}
DynamicList<polyPatch*> regionPatches(patches.size());
@ -2190,7 +2208,7 @@ int main(int argc, char *argv[])
label zone0 = zoneID[eFaces[0]];
label zone1 = zoneID[eFaces[1]];
if (zone0 != zone1) // || (cos(angle) > blabla))
if (addSidePatches && (zone0 != zone1)) // || (cos(angle) > blabla))
{
label minZone = min(zone0,zone1);
label maxZone = max(zone0,zone1);

View File

@ -4,7 +4,6 @@ include $(GENERAL_RULES)/cgal
EXE_INC = \
-DUNIX \
-Wno-old-style-cast \
/* -IMarchingCubes */ \
-I$(FASTDUALOCTREE_SRC_PATH) \
-I../conformalVoronoiMesh/lnInclude \

View File

@ -123,7 +123,7 @@ void Foam::printMeshStats(const polyMesh& mesh, const bool allTopology)
{
// Number of global patches and min-max range of total patches
Info<< mesh.boundaryMesh().nNonProcessor() << ' '
<< returnReduce(labelMinMax(nPatches), minMaxOp<label>()) << nl;
<< returnReduce(labelMinMax(nPatches), sumOp<labelMinMax>{}) << nl;
}
else
{

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016-2023 OpenCFD Ltd.
Copyright (C) 2016-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -232,7 +232,7 @@ vtk::outputOptions getOutputOptions(const argList& args)
if (!args.found("ascii"))
{
if (sizeof(float) != 4 || sizeof(label) != 4)
if constexpr (sizeof(float) != 4 || sizeof(label) != 4)
{
opts.ascii(true);

View File

@ -124,8 +124,8 @@ void Foam::PDRutils::one_d_overlap
}
// Ensure search is within the (point) bounds
xmin = grid.clip(xmin);
xmax = grid.clip(xmax);
xmin = grid.clamp(xmin);
xmax = grid.clamp(xmax);
// The begin/end of the obstacle
*cmin = grid.findCell(xmin);

View File

@ -1,7 +1,6 @@
include $(GENERAL_RULES)/cgal-header-only
EXE_INC = \
-Wno-old-style-cast \
$(COMP_FLAGS) \
${CGAL_INC} \
-I$(LIB_SRC)/finiteVolume/lnInclude \
@ -9,7 +8,6 @@ EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/parallel/distributed/lnInclude
EXE_LIBS = \
-lfiniteVolume \
-lsurfMesh \

View File

@ -1,8 +1,6 @@
EXE_NDEBUG = -DNDEBUG
/* EXE_NDEBUG = -g -O0 -DFULLDEBUG */
c++CGALWARN = -Wno-old-style-cast
/*-- Define CGAL_INEXACT to use inexact CGAL constructions */
include $(GENERAL_RULES)/cgal
@ -11,7 +9,6 @@ EXE_INC = \
${ROUNDING_MATH} \
${EXE_NDEBUG} \
${CGAL_INC} \
${c++LESSWARN} \
-I.. \
-I$(LIB_SRC)/surfMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude

View File

@ -7,7 +7,7 @@
# \\/ M anipulation |
#------------------------------------------------------------------------------
# Copyright (C) 2011-2015 OpenFOAM Foundation
# Copyright (C) 2017-2023 OpenCFD Ltd.
# Copyright (C) 2017-2025 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
@ -23,9 +23,7 @@
#------------------------------------------------------------------------------
. "${WM_PROJECT_DIR:?}"/bin/tools/RunFunctions # Run functions
usage() {
exec 1>&2
while [ "$#" -ge 1 ]; do echo "$1"; shift; done
printHelp() {
cat<<USAGE
Usage: ${0##*/} [OPTION] -np <N> <executable> <args>
@ -44,12 +42,13 @@ options:
-yes Start without additional prompting
-local Same as -spawn=1
-remote Same as -spawn=2
-clean Remove old processor*.{log,sh} files, mpirun.schema etc
-clean Remove log and startup files
-decompose-dict=<file> Specific decomposeParDict name
-help Print the usage
Invoke mpirun with separate per-processor log files or running in
separate XTerms.
Invoke mpirun with separate per-processor log files or with separate XTerms.
Also detects some OpenFOAM options:
-decomposeParDict <file> Use specified file for decomposePar dictionary
Common shortcuts. Sets default spawn to -local, add -yes.
-normal = -method=0
@ -58,9 +57,6 @@ Common shortcuts. Sets default spawn to -local, add -yes.
-valgrind = -method=5l (valgrind + log)
-xvalgrind = -method=5 (valgrind + xterm)
Also detects some OpenFOAM options:
-decomposeParDict <file> Use specified file for decomposePar dictionary
USAGE
exit 0 # A clean exit
}
@ -206,7 +202,7 @@ do
# Processing application arguments
case "$1" in
(-help* | --help*) usage ;;
(-help* | --help*) printHelp ;;
('') ;; ## Ignore junk
(-np)
@ -238,13 +234,16 @@ done
# Cleanup only
if [ -n "$optClean" ]
then
echo "Cleanup old mpirunDebug files..." 1>&2
rm -f gdbCommands mpirun.schema
exec 1>&2
echo "Cleanup old mpirunDebug files..."
rm -f gdbCommands mpirun.schema vgcore.*
rm -f processor*.log processor*.sh
echo " gdbCommands mpirun.schema" 1>&2
echo " processor*.log processor*.sh" 1>&2
echo "Done" 1>&2
exit 0
rm -rf mpirun.log mpirun.files
echo " gdbCommands mpirun.schema vgcore.*"
echo " processor*.{log,sh}"
echo " mpirun.{files,log}/"
echo "Done"
exit 0 # A clean exit
fi
@ -345,16 +344,22 @@ esac
echo "**sourceFoam: $sourceFoam" 1>&2
rm -f "$PWD"/mpirun.schema
touch "$PWD"/mpirun.schema
mkdir -p ./mpirun.files
mkdir -p ./mpirun.log
schema_file="$PWD/mpirun.files/mpirun.schema"
rm -f "$schema_file"
touch "$schema_file"
proc=0
xpos=0
ypos=0
for ((proc=0; proc<$nProcs; proc++))
do
procCmdFile="$PWD/processor${proc}.sh"
procLog="processor${proc}.log"
procCmdFile="$PWD/mpirun.files/processor${proc}.sh"
procLog="./mpirun.log/processor${proc}.log"
xterm="xterm -font fixed -title processor${proc} -geometry 120x15+$xpos+$ypos"
unset node
@ -372,8 +377,8 @@ COMMANDS
# Add to the mpirun.schema
case "$method" in
(*xterm*) echo "${node}${xterm} -e ${procCmdFile}" >> "$PWD"/mpirun.schema ;;
(*) echo "${node}${procCmdFile}" >> "$PWD"/mpirun.schema ;;
(*xterm*) echo "${node}${xterm} -e ${procCmdFile}" >> "$schema_file" ;;
(*) echo "${node}${procCmdFile}" >> "$schema_file" ;;
esac
case "$method" in
@ -419,17 +424,33 @@ COMMANDS
fi
done
for ((proc=0; proc<$nProcs; proc++))
do
procLog="processor${proc}.log"
echo " tail -f $procLog" 1>&2
done
if [ "$nProcs" -lt 10 ]
then
for ((proc = 0; proc < $nProcs; proc++))
do
procLog="mpirun.log/processor${proc}.log"
echo " tail -f $procLog" 1>&2
done
else
for ((proc = 0; proc < 4; proc++))
do
procLog="mpirun.log/processor${proc}.log"
echo " tail -f $procLog" 1>&2
done
echo " ..." 1>&2
for ((proc = $nProcs-2; proc < $nProcs; proc++))
do
procLog="mpirun.log/processor${proc}.log"
echo " tail -f $procLog" 1>&2
done
fi
unset cmd
case "$WM_MPLIB" in
*OPENMPI*)
cmd="mpirun --oversubscribe -app $PWD/mpirun.schema </dev/null"
cmd="mpirun --oversubscribe -app "$schema_file" </dev/null"
;;
MPICH)
cmd="mpiexec"
@ -437,16 +458,16 @@ MPICH)
do
read procCmd
procXtermCmdFile="$PWD/processor${proc}Xterm.sh"
echo "#!/bin/sh" > $procXtermCmdFile
echo "$procCmd" >> $procXtermCmdFile
chmod +x $procXtermCmdFile
if [ $proc -ne 0 ]
procXtermCmdFile="$PWD/mpirun.files/xterm-processor${proc}.sh"
echo "#!/bin/sh" > "$procXtermCmdFile"
echo "$procCmd" >> "$procXtermCmdFile"
chmod +x "$procXtermCmdFile"
if [ "$proc" -ne 0 ]
then
cmd="${cmd} :"
fi
cmd="${cmd} -n 1 ${procXtermCmdFile}"
done < "$PWD"/mpirun.schema
done < "$schema_file"
;;
*)
die "Unsupported WM_MPLIB setting : $WM_MPLIB"
@ -454,7 +475,7 @@ MPICH)
esac
echo 1>&2
echo "Constructed $PWD/mpirun.schema file:" 1>&2
echo "Constructed $schema_file file:" 1>&2
echo 1>&2
echo " $cmd" 1>&2
echo 1>&2

View File

@ -6,7 +6,7 @@
# \\ / A nd | www.openfoam.com
# \\/ M anipulation |
#------------------------------------------------------------------------------
# Copyright (C) 2016 OpenCFD Ltd.
# Copyright (C) 2016-2025 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
@ -22,22 +22,25 @@
# Confirm that all available EXE targets have actually been created:
#
# foamGrepExeTargets > targets-available
# foamGrepExeTargets -appbin > targets-created
# foamGrepExeTargets -bin > targets-created
# diff -uw targets-available targets-created
#
#------------------------------------------------------------------------------
usage() {
exec 1>&2
while [ "$#" -ge 1 ]; do echo "$1"; shift; done
cat<<USAGE
usage: ${0##*/}
-appbin list contents of \$FOAM_APPBIN (no git required)
-help
# Locations
FOAM_GIT_DIR="$WM_PROJECT_DIR/.git"
List available EXE= targets. Requires git.
printHelp() {
cat<<USAGE
usage: ${0##*/}
-bin List contents of \$FOAM_APPBIN (no git required)
-no-git Disable use of git for obtaining information
-help Print the usage
List exe targets (contains EXE). Uses git when possible
USAGE
exit 1
exit 0 # clean exit
}
# Report error and exit
@ -55,54 +58,63 @@ die()
#------------------------------------------------------------------------------
unset projectdir
for i in "./.git" "$WM_PROJECT_DIR/.git"
do
if [ -d "$i" ]
then
projectdir="${i%/*}"
break
fi
done
# Parse options
while [ "$#" -gt 0 ]
do
case "$1" in
-h | -help*)
usage
-h | -help* | --help*)
printHelp
;;
-appbin)
test -n "$FOAM_APPBIN" && cd "$FOAM_APPBIN" || \
-bin)
if [ -n "$FOAM_APPBIN" ] && cd "$FOAM_APPBIN"
then
/bin/ls -1
exit 0
else
die "FOAM_APPBIN is not valid"
/bin/ls -1
exit 0
fi
;;
-no-git)
unset FOAM_GIT_DIR
;;
*)
die "unknown option/argument: '$1'"
;;
esac
shift
done
# Default is grep (via git)
[ -d "$projectdir" ] || \
die "Cannot locate OpenFOAM project, or it does not have a git directory"
# Check environment variables
[ -d "$WM_PROJECT_DIR" ] || \
die "Bad or unset environment variable: \$WM_PROJECT_DIR"
cd "$WM_PROJECT_DIR" || die "No project directory: $WM_PROJECT_DIR"
# Run from top-level directory - otherwise the grep is quite difficult
# A version with 'find' is likewise possible, but not as fast.
# Check 'src' too, in case somehow something is there as well.
(
cd "$projectdir" && \
git grep --cached -P '^\s*EXE\s*=' \
applications/solvers \
applications/utilities \
src
) | sed -e 's@.*/@@' | sort | uniq
for dir in applications/solvers applications/utilities src
do
if [ -d "$dir" ]
then
echo "Checking: $dir" 1>&2
else
echo "No directory: $dir" 1>&2
continue
fi
if [ -d "$FOAM_GIT_DIR" ]
then
git grep --cached -H -P '^\s*EXE\s*=' "$dir" 2>/dev/null
else
# Filesystem find (not quite as fast)
for i in $(find "$dir" -name files)
do
grep -H -P '^\s*EXE\s*=' "$i" 2>/dev/null
done
fi
done | sed -ne 's@/Make/files:.*$@@p' | sed -e 's@.*/@@' | sort | uniq
# -----------------------------------------------------------------------------

125
bin/tools/foamGrepLibTargets Executable file
View File

@ -0,0 +1,125 @@
#!/bin/sh
#------------------------------------------------------------------------------
# ========= |
# \\ / 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, distributed under GPL-3.0-or-later.
#
# Script
# foamGrepLibTargets
#
# Description
# List library targets (contain "LIB_LIBS =")
#
#------------------------------------------------------------------------------
# Locations
FOAM_GIT_DIR="$WM_PROJECT_DIR/.git"
printHelp() {
cat<<USAGE
usage: ${0##*/}
-no-git Disable use of git for obtaining information
-app Search applications/solvers/ applications/utilities/
-src Search src/
-no-git Disable use of git for obtaining information
-help Print the usage
List library targets (contains LIB_LIBS). Uses git when possible
USAGE
exit 0 # clean exit
}
# Report error and exit
die()
{
exec 1>&2
echo
echo "Error encountered:"
while [ "$#" -ge 1 ]; do echo " $1"; shift; done
echo
echo "See '${0##*/} -help' for usage"
echo
exit 1
}
#------------------------------------------------------------------------------
unset locations
# Parse options
while [ "$#" -gt 0 ]
do
case "$1" in
-h | -help* | --help*)
printHelp
;;
-app)
locations="$locations applications/solvers applications/utilities"
;;
-src)
locations="$locations src"
;;
-no-git)
unset FOAM_GIT_DIR
;;
*)
die "unknown option/argument: '$1'"
;;
esac
shift
done
# Check environment variables
[ -d "$WM_PROJECT_DIR" ] || \
die "Bad or unset environment variable: \$WM_PROJECT_DIR"
# Fallback to all locations
if [ -z "$locations" ]
then
locations="applications/solvers applications/utilities src"
fi
set -- $locations
if [ "$#" -eq 0 ]
then
die "No search locations"
fi
# Run from top-level directory - otherwise the grep is quite difficult
cd "$WM_PROJECT_DIR" || die "No project directory: $WM_PROJECT_DIR"
for dir in "$@"
do
if [ -d "$dir" ]
then
echo "Checking: $dir" 1>&2
else
echo "No directory: $dir" 1>&2
continue
fi
if [ -d "$FOAM_GIT_DIR" ]
then
git grep --cached -H -P '^\s*LIB_LIBS\s*=' "$dir" 2>/dev/null
else
# Filesystem find (not quite as fast)
for i in $(find "$dir" -name options)
do
grep -H -P '^\s*LIB_LIBS\s*=' "$i" 2>/dev/null
done
fi
done | sed -ne 's@/Make/options:.*$@@p' | sort | uniq
# -----------------------------------------------------------------------------

View File

@ -137,15 +137,11 @@ cd $WM_THIRD_PARTY_DIR
Subequent compilation with Allwmake will now run largely without any
problems, except that the components linking against CGAL
(foamyMesh and surfaceBooleanFeatures) will also try to link against
a nonexistent mpfr library. As a workaround, the link-dependency can
be removed in wmake/rules/General/CGAL :
a nonexistent mpfr library. As a workaround, the link-dependency will
be removed in wmake/rules/General/cgal by specifying the `CGAL_FLAVOUR`
when compiling:
```
CGAL_LIBS = \
-L$(BOOST_ARCH_PATH)/lib \
-L$(BOOST_ARCH_PATH)/lib$(WM_COMPILER_LIB_ARCH) \
-L$(CGAL_ARCH_PATH)/lib \
-L$(CGAL_ARCH_PATH)/lib$(WM_COMPILER_LIB_ARCH) \
-lCGAL
no-cgal | cgal-header | cgal-header-no-mpfr | cgal-no-mpfr | cgal-mpfr
```
A robuster solution is still being sought.

View File

@ -96,6 +96,7 @@ export WM_COMPILE_OPTION=Opt
# +strict : more deprecation warnings (may generate *many* warnings)
# ccache=... : ccache command (unquoted, single/double or <> quoted)
# version=... : compiler suffix (eg, version=11 -> gcc-11)
# lnInclude-extra : add '-extra' option for wmakeLnInclude
#export WM_COMPILE_CONTROL="+strict"
# [WM_MPLIB] - MPI implementation:

View File

@ -28,6 +28,16 @@ faceZones (f0 f1);
//faceSets (f0 f1);
//faceSetsShadow (f0Shadow f1Shadow);
// Optional : if edge on multiple sets/zones :
// - addSidePatches false : extrude as an internal face (same as a zone-internal
// edge)
// - addSidePatches true : extrude each zone separately so creating multiple
// (default) boundary faces. These faces go into a cyclic type
// patch with corresponding transform.
addSidePatches false;
// Adapt the original mesh to have mapped patches at where the
// faceZones are?
// If true:

View File

@ -22,12 +22,15 @@ set c0;
// x,y,z axis. Specify in globalCoeffs section below.
// - patchLocal : coordinate system different for every cell. Specify in
// patchLocalCoeffs section below.
// - user : coordinate system provided. Usually cylindrical or spherical.
// Specify in userCoeffs section below.
// - fieldBased : uses the list of field names from the directions list for
// selecting the directions to cut. Meant to be used with geometricCut, but
// can also be used with useHexTopology.
coordinateSystem global;
//coordinateSystem patchLocal;
//coordinateSystem fieldBased;
//coordinateSystem user;
// .. and its coefficients. x,y in this case. (normal direction is calculated
// as tan1^tan2)
@ -43,6 +46,15 @@ patchLocalCoeffs
tan1 (1 0 0);
}
userCoeffs
{
type cylindrical;
origin (0 0 0);
e1 (1 0 0); // tan1 direction
e3 (0 1 0); // normal direction
}
// List of directions to refine, if global or patchLocal
directions
(

View File

@ -135,6 +135,18 @@ OptimisationSwitches
// Default communication type (nonBlocking | scheduled | buffered)
commsType nonBlocking;
// Use host/node topology-aware routines
// 0: disabled
// 1: split by hostname [default]
// 2: split by shared
// >=4: (debug/manual) split with given number per node
nodeComms 1;
// Minimum number of nodes before topology-aware routines are enabled
// <= 2 : always
// >= 3 : when there are more than N nodes
nodeComms.min 0;
// Transfer double as float for processor boundaries. Mostly defunct.
floatTransfer 0;
@ -228,6 +240,12 @@ OptimisationSwitches
// from all the individual wall patches. Set to 0/false to revert to
// <v2412 behaviour
//useCombinedWallPatch 0;
//- Use local communicator for AMI communication. Default for v2506.
//localAMIComm = 0; // old behaviour : all ranks included
//localAMIComm = 1; // (default) only ranks that have patch faces
//localAMIComm = 2; // like 1 but always include rank 0 so messages
// still come from processor0
}

View File

@ -96,6 +96,7 @@ setenv WM_COMPILE_OPTION Opt
# +strict : more deprecation warnings (may generate *many* warnings)
# ccache=... : ccache command (unquoted, single/double or <> quoted)
# version=... : compiler suffix (eg, version=11 -> gcc-11)
# lnInclude-extra : add '-extra' option for wmakeLnInclude
#setenv WM_COMPILE_CONTROL "+strict"
# [WM_MPLIB] - MPI implementation:

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019-2023 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -64,12 +64,11 @@ std::string pipeOpen(const std::string& cmd, const int lineNum = 0)
if (cnt == lineNum)
{
// Retain the last line, trimming trailing newline
str.assign(buf);
if (str.size())
if (nread > 0)
{
str.resize(str.size()-1);
buf[nread-1] = '\0';
}
str.assign(buf);
}
}

View File

@ -1,10 +0,0 @@
// Compatibility include. For v2112 and earlier
#ifndef FoamCompat_Swap_H
#define FoamCompat_Swap_H
#include "stdFoam.H"
#endif
// ************************************************************************* //

View File

@ -1,11 +0,0 @@
// ************************************************************************* //
// Compatibility include
#ifndef FoamCompat_endian_H
#define FoamCompat_endian_H
#include "foamEndian.H"
#endif
// ************************************************************************* //

View File

@ -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.
@ -188,12 +188,12 @@ Foam::PackedList<Width>::unpack() const
{
static_assert
(
std::is_integral<IntType>::value,
std::is_integral_v<IntType>,
"Integral required for output."
);
static_assert
(
std::numeric_limits<IntType>::digits >= Width,
Width < std::numeric_limits<IntType>::digits,
"Width of IntType is too small to hold result"
);
@ -244,12 +244,12 @@ Foam::PackedList<Width>::unpack(const labelRange& range) const
{
static_assert
(
std::is_integral<IntType>::value,
std::is_integral_v<IntType>,
"Integral required for unpack output."
);
static_assert
(
std::numeric_limits<IntType>::digits >= Width,
Width < std::numeric_limits<IntType>::digits,
"Width of IntType is too small to hold unpack output."
);
@ -278,12 +278,12 @@ Foam::PackedList<Width>::unpack(const labelUList& locations) const
{
static_assert
(
std::is_integral<IntType>::value,
std::is_integral_v<IntType>,
"Integral required for unpack output."
);
static_assert
(
std::numeric_limits<IntType>::digits >= Width,
Width < std::numeric_limits<IntType>::digits,
"Width of IntType is too small to hold unpack output."
);

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2023 OpenCFD Ltd.
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -648,7 +648,7 @@ inline std::streamsize Foam::PackedList<Width>::size_data() const noexcept
template<unsigned Width>
inline std::streamsize Foam::PackedList<Width>::size_bytes() const noexcept
{
return num_blocks(size()) * sizeof(block_type);
return size_data() * sizeof(block_type);
}

View File

@ -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.
@ -103,7 +103,7 @@ Foam::Ostream& Foam::CircularBuffer<T>::writeList
}
#endif
if (os.format() == IOstreamOption::BINARY && is_contiguous<T>::value)
if (os.format() == IOstreamOption::BINARY && is_contiguous_v<T>)
{
// Binary and contiguous
@ -136,11 +136,7 @@ Foam::Ostream& Foam::CircularBuffer<T>::writeList
||
(
(len <= shortLen)
&&
(
is_contiguous<T>::value
|| Detail::ListPolicy::no_linebreak<T>::value
)
&& (is_contiguous_v<T> || Detail::ListPolicy::no_linebreak<T>::value)
)
)
{

Some files were not shown because too many files have changed in this diff Show More