Compare commits

..

43 Commits

Author SHA1 Message Date
6b3e65d17d STYLE: ListExpression: copyright, indenting 2025-10-23 11:48:36 +01:00
572fa22bae Merge branch 'feature-grad_update' into 'develop'
Feature grad update

See merge request Development/openfoam!764
2025-10-22 15:46:53 +00:00
e100e4d084 Feature grad update 2025-10-22 15:46:53 +00:00
f186b0098b Merge branch 'feature-et' into 'develop'
ENH: Expressions: basic expression template support

See merge request Development/openfoam!763
2025-10-22 15:45:08 +00:00
b0066fc550 ENH: ListExpression: support par_unseq, multi-storage container
(ListsRefWrap etc. supplied by AMD)
2025-10-22 15:44:22 +00:00
7fb4e77583 ENH: expressions: Expression Templates 2025-10-22 15:44:22 +00:00
78cf2ce5db ENH: dynamicContactAngle: enable zonal input using persistent field storage
Temporary field creation is replaced with persistent field storage,
so that contact-angle can be input per zone using setFields utility.
2025-10-20 14:22:33 +01:00
f2793f2ac8 ENH: atmBoundaryLayer: extend range of applicability of displacement height, d (#3451) 2025-10-17 16:44:27 +01:00
013dbb8248 BUG: Pstream: incorrect indexing. Fixes #3452 2025-10-16 11:52:12 +01:00
e9fcd75ec4 ENH: add default "constant" name for fileOperations::findTimes()
- makes fileHandler calling resemble Time more closely

ENH: provide natural_sort less/greater functions

- more succinct than (compare < 0) or (compare > 0).
  The corresponding wrappers for UList renamed as list_less, etc
  but they were only used in unit tests

ENH: handle (-allRegions | -all-regions, ..) directly when retrieving args

- makes handling independent of aliasing order

STYLE: include <string_view> when including <string>

- the standard does not guarantee which headers (if any) actually
  include string_view
2025-10-12 15:53:26 +02:00
ac34d9fd29 ENH: allow delayed construction of regionFaModel in volume bcs (#3419)
Ideally wish to delay construction of the finite-area mesh until
  updateCoeffs(), when it is actually needed.

  This helps avoid difficult to trace errors and avoids inadvertent
  parallel communication during construction from a dictionary.

  However, lazy evaluation fails at the later stage while attempting
  to load the corresponding initial fields, since the timeIndex has
  already advanced.

  Use the newly introduced regionModels::allowFaModels() switch
  to locally enable or disable lazy evaluation as needed.

  This allows selective disabling (eg, in post-processing utilities)
  where loading the volume field should not activate the associated
  regionFaModel and loading a finite-area mesh too (which may not
  exist or be defined at that point).
2025-10-11 19:51:51 +02:00
14bece937b ENH: added clean up function remove0DirFields (RunFunctions)
- less typing than before and avoids relying on bash-specific behaviour
  (fixes #3448)

ENH: add -region support for cleanFaMesh and cleanPolyMesh

CONFIG: add bash completion help for -area-region

ENH: general improvements for regionProperties

- robustness and failsafe for foamListRegions, regionProperties
- additional global model switches for regionModels
2025-10-10 18:18:31 +02:00
2396828a60 ENH: increase some string_view coverage
- remove some stdFoam::span<char> handling, which was just a stop-gap
  measure
2025-10-10 09:05:23 +02:00
9223d238bd STYLE: surface/volume writing function objects
- further hide implementation (cxx ending)

STYLE: better distinction between code/templates for fileFormats/conversion

- for ensight and vtk, a large part of the code is header only.
  Make this easier to identify
2025-10-10 08:54:03 +02:00
4b92bb6533 ENH: update globalIndex::mpiGather to use MPI intrinsic/user types
- add provisional support for selecting MPI_Gatherv
  when merging fields in the surface writers.
  Uses the 'gatherv' keyword [experimental]

BUG: gatherv/scatterv wrappers used the incorrect data type

- incorrectly checked against UPstream_basic_dataType trait instead of
  UPstream_dataType, which resulted in a count mismatch for
  user-defined types (eg, vector, tensor,...).

  This was not visibly active bug, since previous internal uses of
  gatherv were restricted to primitive types.

COMP: make UPstream dataType traits size(...) constexpr

- allows static asserts and/or compile-time selection
  of code based on size(1)
2025-10-10 08:51:20 +02:00
55c81bce1b ENH: GAMGAgglomeration: increase repeatability. Fixes #3450 2025-10-09 11:55:06 +01:00
1cb0b7b6c9 Merge branch 'extend-field-distributors' into 'develop'
cleanup of decompose/reconstruct/redistribute, adding area-name support

See merge request Development/openfoam!761
2025-10-09 10:29:56 +00:00
7f939f6d2d ENH: increase coverage of bitSet support for field distributors 2025-10-08 21:26:37 +02:00
cbb66f7bc7 ENH: add area-name handling for faMesh decompose/reconstruct (#3419)
- using labelUList addressing

- support direct handling of pointers (as well as autoPtr)
2025-10-08 21:26:30 +02:00
5d7bd9c497 ENH: decompose/reconstruct using labelUList, UPtrList addressing
ENH: reduce some overhead for processorMeshes reconstructPoints
2025-10-08 21:26:22 +02:00
601239f59a Merge branch 'multi-finite-area.base-changes' into 'develop'
base changes to finite-area and faOptions to recognize different area regions.

See merge request Development/openfoam!760
2025-10-08 12:21:17 +01:00
b25147a4f8 ENH: finite-area region support to all faOptions and regionFaModels
- for a non-default mesh region, corresponding files:

     system/finite-area/faOptions.<name>
     system/finite-area/<name>/faSchemes, etc

  if the entries within the faOptions dictionary happen to contain an
  "area" entry and it conflicts with what is expected, it will be
  rejected when creating the list of options, which helps avoid
  unexpected behaviour and simplifies overall handling.
2025-10-08 13:17:40 +02:00
19628b9576 ENH: update faOptions handling to respect finite-area locations
- new locations
    * constant/finite-area/faOptions
    * system/finite-area/faOptions

- legacy locations are still supported
    * constant/faOptions
    * system/faOptions

TUT: update faOptions locations
2025-10-08 13:17:40 +02:00
b913463d95 ENH: correct handling of area-name for faMesh (#3419)
- unlike fvMesh and polyMesh, the faMesh mesh region name is passed
  separately into constructors and functions. Thus need the same for
  faMeshTools and faMeshSubset.

- ensure that an empty area name is treated like
  polyMesh::defaultRegion.
  The faMeshRegistry or other registries cannot have an empty name!
2025-10-08 13:17:40 +02:00
3ae725592d ENH: add area-regions option handling (based partly on regionProperties)
- extend the getAllRegionOptions and getAllFaRegionOptions handling
  to use the supplied string literals as fallback values.

  If regionProperties is missing (or empty) and the -regions/-area-regions
  option is supplied with literal names, these will be used directly
  instead of being used to filter the regionProperties.

STYLE: support both -all-regions and -allRegions
2025-10-08 13:17:39 +02:00
d6081a18f6 ENH: simpler mechanical or thermal use of solidProperties
- in some shell models, only the mechanical properties (rho,E,nu) are
  meaningful or just the basic thermal properties
  (rho,Cp,kappa,emissivity).

  Add a distinction when reading the dictionary entries
  if those properties are mandatory and the thermo properties
  (eg, molWt, Cp, etc) are optional or not.

  This simplifies user input for thermal and vibration shell models.
2025-10-08 13:17:39 +02:00
e46cc77a5b CONFIG: bump patch level to 2507
- changes in stream handling
- imminent API changes for finite-area
2025-10-08 13:11:07 +02:00
5321c92e3d SUBMODULE: update OpenQBMM (some compilation changes) 2025-10-08 13:05:57 +02:00
97cbe9c54e Merge branch 'update-UPstreamRequests-handling' into 'develop'
refine request handling to support MPI idioms

See merge request Development/openfoam!759
2025-10-08 10:49:29 +00:00
06b3e9bd0b ENH: update/refine UPstream request handling
- activeRequest() checks if given request is still active/pending

- finishedRequest() will now always call MPI_Test when running in
  parallel instead of using a fast-path for skipping a null request.
  This allows MPI a chance to progress operations even if that
  particular request is not active.

- sameProcs() is a convenience wrapper for the following:
  * check if indices resolve to the same underlying procs
  * check the communicator procs against a list of procs
  * to compare two lists of procs.

  For example, check if the communicator corresponds to a
  host-local communication:

     if (UPstream::sameProcs(UPstream::commLocalNode(), myComm)) ...

STYLE: UPstream::Request gets an 'active()' method

- more MPI idiomatic than 'good'
2025-10-07 21:04:23 +02:00
a6c924cf8f COMP: minor adjustments for MacOS
- to avoid the many overload warnings on that platform,
  may wish to use

      FOAM_EXTRA_CXXFLAGS="-Wno-overloaded-virtual"

GIT: remove some old compilation stub files
2025-10-07 19:43:07 +02:00
e5848196ef Merge branch 'mixed-precision-streams' into 'develop'
INT: token/stream support for reading/writing int32 and int64

See merge request Development/openfoam!756
2025-10-07 14:51:20 +00:00
aa96119de2 INT: token/stream support for reading/writing int32 and int64
integration-by: Mark Olesen <Mark.Olesen@keysight.com>
2025-10-07 14:50:37 +00:00
11166821f1 REGRESSION: corrected use of inotify 2025-10-06 16:16:26 +01:00
77b2687503 COMP: better constexpr isolation of List<char> specializations
- adjust the if/else-if/else-if cascade to have 'if constexpr (..)'
  first and the *entire* alternate branch within the following 'else'.
  This lets the compiler know that it can safely discarded the other
  parts.

  This change introduces a large amount of indentation change,
  so use `--ignore-space-change` when inspecting.

COMP: reintroduce UList<T>() initialization in List [silence gcc]

COMP: use std::min() instead of direct check [silence gcc]

- gcc complains about possible strict-overflow for this:
  ```
  if (count > len)
  {
      count = len;        // The count truncated by the new length
  }
  ```

  Using `count = std::min(count, len);` avoids these (spurious)
  warnings without adding a "diagnostic ignored" pragma

STYLE: pass std::pair<int,int> by copy [cheaper]

STYLE: make isdigit() and isspace() tests constexpr

- constexpr and C-locale only vs. the std counterparts
2025-10-06 15:54:00 +02:00
52c55543b5 COMP: no-rpath handling not found (darwin) 2025-10-06 15:01:59 +02:00
41231028da Merge branch 'feature-slicing.prerelease' into 'develop'
Adding scratch space for patchField data

See merge request Development/openfoam!757
2025-10-06 12:43:13 +00:00
35615174a3 Adding scratch space for patchField data 2025-10-06 12:43:13 +00:00
b9fecc3898 Merge branch 'time-paths' into 'develop'
Add handling of local/global layout for Time paths

See merge request Development/openfoam!758
2025-10-06 10:26:15 +00:00
c78b510928 ENH: improve search and addressing options for TimePaths
- extend time searching mechanisms to support searching in the case
  global path: times(), findClosestTime(), findInstancePath()

- extend IOobject path() and objectPath() methods with
  IOobjectOption::Layout variants

The changes are needed for addressing a global file structure
in parallel (#3431)
2025-10-05 21:52:51 +02:00
a91587e36a ENH: improve 'fuzzy' matching of time instant
- add '<=' and '>=' operators that include rounding.

  This means that typical code like the following would not have
  considered any rounding:

    instantList times = ...;
    scalar val = ..;

    // No rounding!
    if (times[i].value() <= val) { ... }

    // NEW: with rounding
    if (times[i] <= val) { ... }

    // old equivalent:
    if (times[i].value() <= val || times[i].equal(val)) { ... }

ENH: provide a default stopInstance for fileOperation::findInstance

- makes it more consistent with Time::findInstance and more convenient
  to use

STYLE: minor code style changes to TimePaths etc
2025-10-05 21:52:37 +02:00
9c4d0cdeef BUG: kinematicParcelFoam: correct source-term value (fixes #3446)
- likely results in output changes for denser carrier fluids

Co-authored-by: Kutalmis Bercin <kutalmis.bercin@esi-group.com>
2025-10-03 15:47:26 +01:00
7a266b566f DOC: functionObjects: overhaul of header documentation 2025-10-02 21:32:26 +01:00
577 changed files with 18699 additions and 8440 deletions

View File

@ -1,2 +1,2 @@
api=2506
api=2507
patch=0

View File

@ -6,7 +6,7 @@
+ MRF.DDt(U)
+ turbulence->divDevReff(U)
==
parcels.SU(U, true)
invRhoInf*parcels.SU(U)
+ fvOptions(U)
);

View File

@ -39,6 +39,11 @@ dimensionedScalar rhoInfValue
laminarTransport
);
const dimensionedScalar invRhoInf
(
dimless/dimDensity, scalar(1)/rhoInfValue.value()
);
volScalarField rhoInf
(
IOobject

View File

@ -200,7 +200,7 @@ void printTypeName()
template<class Type, bool UseTypeName = true>
void printPstreamTraits(const std::string_view name = std::string_view())
void printPstreamTraits(std::string_view name = std::string_view())
{
Info<< "========" << nl;
Info<< "type: ";
@ -299,6 +299,9 @@ void printPstreamTraits(const std::string_view name = std::string_view())
// Use element or component type (or byte-wise) for data type
using base = typename UPstream_dataType<Type>::base;
// The sizing factor is constexpr
constexpr std::streamsize count = UPstream_dataType<Type>::size(1);
Info<< " : ";
if constexpr (UseTypeName)
{
@ -311,8 +314,7 @@ void printPstreamTraits(const std::string_view name = std::string_view())
Info<< " cmpt-type=";
printDataTypeId(UPstream_dataType<Type>::datatype_id);
Info<< " count=" << UPstream_dataType<Type>::size(1);
Info<< nl;
Info<< " count=" << count << nl;
}
}
@ -362,6 +364,24 @@ void print_data_opType(BinaryOp bop, std::string_view name)
}
template<class Type>
int check_simple(std::string_view name = std::string_view())
{
// The sizing factor is constexpr
constexpr std::streamsize count = UPstream_dataType<Type>::size(1);
static_assert
(
(count == 1),
"Code does not (yet) work with aggregate types"
);
Info<< "check_simple: " << name << ": " << count << nl;
return count;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
@ -389,6 +409,8 @@ int main()
printPstreamTraits<const float>();
printPstreamTraits<floatVector>();
check_simple<floatVector>("vector<float>");
printPstreamTraits<scalar>();
printPstreamTraits<double>();
printPstreamTraits<doubleVector>();

View File

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

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2023 OpenCFD Ltd.
Copyright (C) 2023-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -158,7 +158,8 @@ void populateCompound(token::compound& ct, const dictionary& dict)
}
break;
case token::tokenType::LABEL :
case token::tokenType::INTEGER_32 :
case token::tokenType::INTEGER_64 :
{
fillComponents(label, cmpts, 123);
}

View File

@ -0,0 +1,5 @@
Test-expressionTemplates-volFields.C
/* Test-expressionTemplates-pointFields.C */
/* Test-expressionTemplates-Fields.C */
EXE = $(FOAM_USER_APPBIN)/Test-expressionTemplates

View File

@ -0,0 +1,11 @@
EXE_INC = \
-O0 \
-I$(FOAM_SRC)/meshTools/lnInclude \
-I$(FOAM_SRC)/finiteVolume/lnInclude \
EXE_LIBS = \
/* -rpath /Volumes/case_sensitive/OpenFOAM/work/feature-et/platforms */ \
/* -rpath /Volumes/case_sensitive/OpenFOAM/work/feature-et/platforms/darwin64GccDPInt32Opt/lib */ \
/* -rpath /Volumes/case_sensitive/OpenFOAM/work/feature-et/platforms/darwin64GccDPInt32Opt/lib/$(FOAM_MPI) */\
-L/Volumes/case_sensitive/OpenFOAM/work/feature-et/platforms/darwin64GccDPInt32Opt/lib \
-lfiniteVolume

View File

@ -0,0 +1,126 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2025 M. Janssens
-------------------------------------------------------------------------------
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-expressionTemplates
\*---------------------------------------------------------------------------*/
#include "Time.H"
#include "argList.H"
#include "polyMesh.H"
#include "pointMesh.H"
#include "pointFields.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
#include "setRootCase.H"
#include "createTime.H"
#include "createPolyMesh.H"
{
scalarField vals0({1.0, 2.0, 3.0});
const Expression::ListConstRefWrap<scalar> wvals0(vals0);
scalarField vals1;
Expression::ListRefWrap<scalar> wvals1(vals1.size(), vals1);
wvals1 = wvals0;
return 0;
}
const pointMesh& pMesh = pointMesh::New(mesh);
// Field, dimensionedScalar as List expression
{
scalarField vals({1.0, 2.0, 3.0});
dimensionedScalar d(dimless, 4.0);
scalarField result(d.expr(vals.size())*vals.expr());
Pout<< "result:" << result << endl;
}
Info<< "Reading field p\n" << endl;
pointScalarField p
(
IOobject
(
"pointDisplacement",
runTime.timeName(),
pMesh.thisDb(),
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
pMesh
);
pointScalarField result
(
IOobject
(
"result",
runTime.timeName(),
pMesh.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE,
IOobject::NO_REGISTER
),
pMesh,
dimensionedScalar("zero", Foam::sqr(p().dimensions()), 0)
);
// Construct value + dimensions with correct sizing
const auto oneField(dimensionedScalar(dimless, 1.0).expr(p));
// Make expression
auto expression = oneField * p.expr() + p.expr();
// Combine expressions
auto newExpression = sqr(expression);
// Assign values
result = newExpression;
DebugVar(result);
// Construct from expression
pointScalarField result2("result2", pMesh, sqrt(p.expr()));
DebugVar(result2);
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,451 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
volPointInterpolationTest
\*---------------------------------------------------------------------------*/
#include "Time.H"
#include "argList.H"
#include "fvMesh.H"
#include "ListExpression.H"
#include "GeometricFieldExpression.H"
#include "fvCFD.H"
#include "fvMatrixExpression.H"
#include <ratio>
#include <chrono>
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
tmp<volScalarField> someFunction(const volScalarField& fld)
{
return fld*1.0001;
}
template<class Type>
void fusedGaussFvmLaplacian
(
fvMatrix<Type>& fvm,
const surfaceInterpolationScheme<scalar>& interpGammaScheme,
const fv::snGradScheme<Type>& snGradScheme,
const GeometricField<scalar, fvPatchField, volMesh>& gamma,
const GeometricField<Type, fvPatchField, volMesh>& vf
)
{
// Replacement for gaussLaplacianScheme::fvmLaplacian with scalar gamma
typedef GeometricField<Type, fvsPatchField, surfaceMesh> surfaceType;
const auto& mesh = vf.mesh();
// Expression for weights
const auto weights = interpGammaScheme.weights(gamma).expr();
// Expression for gamma_face * magSf
const auto gammaMagSf =
Expression::interpolate(gamma.expr(), weights, mesh)
* mesh.magSf().expr();
// Expression for deltaCoeffs
const auto deltaCoeffs = snGradScheme.deltaCoeffs(vf).expr();
// Construct matrix
Expression::fvmLaplacianUncorrected(fvm, gammaMagSf, deltaCoeffs);
if (snGradScheme.corrected())
{
// Wrap correction
const auto corr(snGradScheme.correction(vf).expr());
const auto V = mesh.V().expr();
if (mesh.fluxRequired(vf.name()))
{
fvm.faceFluxCorrectionPtr() = std::make_unique<surfaceType>
(
IOobject
(
"faceFluxCorr",
mesh.time().timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE,
IOobject::NO_REGISTER
),
mesh,
gamma.dimensions()
*mesh.magSf().dimensions()
*corr.data().dimensions()
);
auto& faceFluxCorr = *fvm.faceFluxCorrectionPtr();
faceFluxCorr = gammaMagSf*corr;
fvm.source() =
fvm.source().expr()
- (
V * fvc::div
(
faceFluxCorr
)().primitiveField().expr()
);
}
else
{
// Temporary field
surfaceType faceFluxCorr
(
IOobject
(
"faceFluxCorr",
mesh.time().timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE,
IOobject::NO_REGISTER
),
mesh,
gamma.dimensions()
*mesh.magSf().dimensions()
*corr.data().dimensions()
);
faceFluxCorr = gammaMagSf*corr;
fvm.source() =
fvm.source().expr()
- (
V * fvc::div
(
faceFluxCorr
)().primitiveField().expr()
);
}
}
}
using namespace std::chrono;
int main(int argc, char *argv[])
{
#include "setRootCase.H"
#include "createTime.H"
#include "createMesh.H"
Info<< "Reading field p\n" << endl;
volScalarField p
(
IOobject
(
"p",
runTime.timeName(),
mesh.thisDb(),
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
{
volScalarField p2("p2", p);
DebugVar(p2.boundaryFieldRef());
for (auto& pf : p.boundaryFieldRef())
{
scalarField newVals(pf.size());
forAll(pf, i)
{
newVals[i] = scalar(i);
}
pf == newVals;
}
//std::vector<const scalarField*> ptrs;
// List<const scalarField*> ptrs;
// for (const auto& pp : p.boundaryField())
// {
// ptrs.push_back(&pp);
// }
DebugVar(sizeof(long));
DebugVar(p.boundaryField());
Expression::ListsConstRefWrap<scalarField> expr(p.boundaryField());
const auto twoA = expr + expr;
Expression::ListsRefWrap<scalarField> expr2(p2.boundaryFieldRef());
Pout<< "**before assignment twoA:" << twoA.size()
<< " expr2:" << expr2.size() << endl;
expr2 = twoA;
Pout<< "**after assignment twoA:" << twoA.size()
<< " expr2:" << expr2.size() << endl;
DebugVar(p2.boundaryField());
// forAll(expr, i)
// {
// Pout<< "i:" << i
// //<< " expr:" << expr[i]
// //<< " twoA:" << twoA[i]
// << " expr2:" << expr2[i]
// << endl;
// }
return 0;
}
{
//DebugVar(linearInterpolate(p));
//auto tweights = linear<scalar>(mesh).weights(p);
//DebugVar(tweights);
surfaceScalarField result
(
IOobject
(
"result",
runTime.timeName(),
mesh.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE,
IOobject::NO_REGISTER
),
mesh,
dimensionedScalar(p.dimensions(), 0)
);
//result = Expression::interpolate
//(
// p.expr(),
// tweights().expr(),
// mesh
//);
result = Expression::linearInterpolate(p.expr(), mesh);
DebugVar(result);
return 0;
}
volScalarField p2
(
IOobject
(
"p",
runTime.timeName(),
mesh.thisDb(),
IOobject::MUST_READ,
IOobject::AUTO_WRITE,
IOobject::NO_REGISTER
),
mesh
);
// Expresions of volFields
{
volScalarField result
(
IOobject
(
"result",
runTime.timeName(),
mesh.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE,
IOobject::NO_REGISTER
),
mesh,
dimensionedScalar(p.dimensions(), 0)
);
{
Pout<< "No expression templates:" << endl;
const high_resolution_clock::time_point t1 =
high_resolution_clock::now();
result = p + p2;
const high_resolution_clock::time_point t2 =
high_resolution_clock::now();
const duration<double> time_span = t2 - t1;
Pout<< "Operation time:" << time_span.count() << endl;
}
{
Pout<< "With expression templates:" << endl;
const high_resolution_clock::time_point t1 =
high_resolution_clock::now();
result = p.expr() + p2.expr();
const high_resolution_clock::time_point t2 =
high_resolution_clock::now();
const duration<double> time_span = t2 - t1;
Pout<< "Operation time:" << time_span.count() << endl;
}
// const auto oldDimensions = p.dimensions();
// p.dimensions().reset(dimless);
// p2.dimensions().reset(dimless);
// result.dimensions().reset(dimless);
// {
//
// Pout<< "Complex expression : No expression templates:" << endl;
// const high_resolution_clock::time_point t1 =
// high_resolution_clock::now();
// result = cos(p + 0.5*sqrt(p2-sin(p)));
// const high_resolution_clock::time_point t2 =
// high_resolution_clock::now();
// const duration<double> time_span = t2 - t1;
// Pout<< "Operation time:" << time_span.count() << endl;
// }
// {
// Pout<< "Complex expression : With expression templates:" << endl;
// const high_resolution_clock::time_point t1 =
// high_resolution_clock::now();
// const auto zeroDotFive
// (
// dimensionedScalar(dimless, 0.5).expr(p)
// );
// result = cos(p.expr() + zeroDotFive*sqrt(p2.expr()-sin(p.expr())));
// const high_resolution_clock::time_point t2 =
// high_resolution_clock::now();
// const duration<double> time_span = t2 - t1;
// Pout<< "Operation time:" << time_span.count() << endl;
// }
// p.dimensions().reset(oldDimensions);
// p2.dimensions().reset(oldDimensions);
// result.dimensions().reset(oldDimensions);
return 0;
// auto expression = someFunction(p).expr() + someFunction(p).expr();
// result = expression;
// DebugVar(result);
}
{
volScalarField result
(
IOobject
(
"result",
runTime.timeName(),
mesh.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE,
IOobject::NO_REGISTER
),
mesh,
dimensionedScalar(p.dimensions(), 0)
);
auto expression = someFunction(p).expr() + someFunction(p).expr();
result = expression;
DebugVar(result);
}
// Expresions of volFields
{
volScalarField result
(
"result",
mesh,
sqr(p.expr() + p.expr())
);
DebugVar(result);
}
{
// Fill p with some values
forAll(p, celli)
{
p[celli] = celli;
}
p.correctBoundaryConditions();
// Interpolate to surface field
surfaceScalarField result
(
"result",
mesh,
Expression::interpolate //<volExpr, surfaceExpr>
(
p.expr(),
mesh.surfaceInterpolation::weights().expr(),
mesh
)
);
DebugVar(result);
}
{
// For testing as a replacement of laplacian weights
const volScalarField gamma
(
IOobject
(
"gamma",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE,
IOobject::NO_REGISTER
),
mesh,
dimensionedScalar(dimless, 1.0)
);
fvMatrix<scalar> fvm
(
p,
gamma.dimensions()*mesh.magSf().dimensions()*p.dimensions()
);
const linear<scalar> interpGammaScheme(mesh);
const fv::correctedSnGrad<scalar> snGradScheme(mesh);
fusedGaussFvmLaplacian
(
fvm,
interpGammaScheme,
snGradScheme,
gamma,
p
);
DebugVar(fvm.source());
}
// Expressions of fvMatrix
{
tmp<fvMatrix<scalar>> tm0(fvm::laplacian(p));
const fvMatrix<scalar>& m0 = tm0();
DebugVar(m0.dimensions());
tmp<fvMatrix<scalar>> tm1(fvm::laplacian(p));
const fvMatrix<scalar>& m1 = tm1();
DebugVar(m1.dimensions());
fvMatrix<scalar> m2(p, m0.expr() + m1.expr());
DebugVar(m2.dimensions());
}
return 0;
}
// ************************************************************************* //

View File

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

View File

@ -79,8 +79,11 @@ int main(int argc, char *argv[])
}
Info<< nl << "times:" << times << nl;
sort(times);
labelList order(Foam::sortedOrder(times));
Foam::sort(times);
Info<< "Sorted:" << times << nl;
Info<< "order:" << flatOutput(order) << nl;
for (const scalar val : { -0.5, 5.0, 18.0, 25.0, 450.0, 480.0 })
{
@ -105,10 +108,29 @@ int main(int argc, char *argv[])
files.emplace_back(10, "ten");
Info<< nl << "files:" << files << nl;
sort(files);
Foam::sort(files);
Info<< "Sorted:" << files << nl;
{
const auto& a = times[3];
scalar b = 10;
Info<< "compare (" << a << ") <= (" << b << ") => "
<< a.less_equal(10) << nl;
Info<< "compare (" << a << ") >= (" << b << ") => "
<< a.greater_equal(10) << nl;
}
{
const auto& a = times[3];
const auto& b = files[4];
Info<< "compare (" << a << ") <= (" << b << ") => "
<< (a <= b) << nl;
Info<< "compare (" << a << ") >= (" << b << ") => "
<< (a >= b) << nl;
}
Info<< "\nEnd\n" << endl;
return 0;

View File

@ -54,9 +54,12 @@ int main(int argc, char *argv[])
"int",
"Num of cores to simulate (default: 4)"
);
argList::addBoolOption("scatter", "Use scatter arrows");
#include "setRootCase.H"
const bool optScatterGraph = args.found("scatter");
label nProcs = UPstream::nProcs(UPstream::worldComm);
DynamicList<int> fake_interNode_offsets;
@ -128,25 +131,50 @@ int main(int argc, char *argv[])
auto& os = Info.stream();
os << "// node topology graph:" << nl;
os.beginBlock("graph");
std::string arrow;
if (optScatterGraph)
{
arrow = " -> ";
os.beginBlock("digraph");
}
else
{
arrow = " -- ";
os.beginBlock("graph");
}
// Prefer left-to-right layout for large graphs
os << indent << "rankdir=LR" << nl;
os << indent << "rankdir=LR" << nl << nl;
const label numNodes = interNodeOffsets.size()-1;
// The master
os << indent
<< "0 [label=\"master\", style=filled, fillcolor=lightgray];"
<< nl << nl;
// First level are the inter-node connections
{
os << indent << 0 << " -- " << token::LBRACE;
os << indent
<< "// inter-node: " << flatOutput(interNodeOffsets) << nl;
for (label nodei = 1; nodei < numNodes; ++nodei)
os << indent
<< 0 << arrow.data() << nl;
os.beginBlock();
os << indent << "rank=same; node [shape=box];" << nl << nl;
os << indent;
for (label nodei = 0; nodei < numNodes; ++nodei)
{
os << ' ' << interNodeOffsets[nodei];
if (nodei) os << ' ';
os << "node" << nodei;
}
os << token::SPACE << token::RBRACE
<< " // inter-node: " << flatOutput(interNodeOffsets)
<< nl;
os << nl;
os.endBlock() << nl;
}
// Next level are the local-node connections
@ -155,8 +183,9 @@ int main(int argc, char *argv[])
const auto firstProc = interNodeOffsets[nodei];
const auto lastProc = interNodeOffsets[nodei+1];
os << indent << firstProc << " -- " << token::DQUOTE
<< (firstProc+1) << ".." << (lastProc-1)
os << indent << "node" << nodei << arrow.data()
<< token::DQUOTE
<< firstProc << ".." << (lastProc-1)
<< token::DQUOTE << nl;
}

View File

@ -38,6 +38,7 @@ Description
#include "SubField.H"
#include "vector.H"
#include "IOstreams.H"
#include "UPstreamWindow.H"
using namespace Foam;

View File

@ -296,7 +296,7 @@ int main(int argc, char *argv[])
(
strings,
order,
stringOps::natural_sort::less<string>(strings)
stringOps::natural_sort::list_less(strings)
);
Info<< "natural sortedOrder: " << flatOutput(order) << endl;
}
@ -321,7 +321,7 @@ int main(int argc, char *argv[])
/// sortable = hashed.toc();
/// sortable.sort
/// (
/// stringOps::natural_sort::less<string>(sortable)
/// stringOps::natural_sort::list_less(sortable)
/// );
/// Info<< nl << "natural:" << sortable << endl;
@ -329,7 +329,7 @@ int main(int argc, char *argv[])
/// sortable = hashed.toc();
/// sortable.sort
/// (
/// stringOps::natural_sort::greater<string>(sortable)
/// stringOps::natural_sort::list_greater(sortable)
/// );
/// Info<< nl << "natural:" << sortable << endl;
}

View File

@ -59,11 +59,6 @@ int main(int argc, char *argv[])
<< " type: " << typeid(cstr).name() << " len:" << len << nl;
Info<< " view: " << std::string_view(cstr) << nl;
Info<< " span: "
<< stdFoam::span<const char>(cstr, len) << nl;
Info<< " span: "
<< stdFoam::span<char>(const_cast<char*>(cstr), len) << nl;
}
}

View File

@ -1,4 +1,4 @@
mydebugSurfaceWriter.C
Test-surface-sampling.C
mydebugSurfaceWriter.cxx
Test-surface-sampling.cxx
EXE = $(FOAM_USER_APPBIN)/Test-surface-sampling

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.
@ -83,12 +83,10 @@ template<> struct narrowType<SymmTensor<double>>
typedef SymmTensor<float> type;
};
// FIXME: Not sure why this one seems to be broken...
//
// template<> struct narrowType<Tensor<double>>
// {
// typedef Tensor<float> type;
// };
template<> struct narrowType<Tensor<double>>
{
typedef Tensor<float> type;
};
} // End namespace Foam
@ -104,12 +102,18 @@ Foam::surfaceWriters::mydebugWriter::mergeField
{
addProfiling(merge, "debugWriter::merge-field");
// This is largely identical to surfaceWriter::mergeField()
// Identical to surfaceWriter::mergeField()
// but with narrowing for communication
if (narrowTransfer_ && parallel_ && UPstream::parRun())
if constexpr (std::is_same_v<Tensor<double>, Type>)
{
// Cannot narrow tensor. Does not compile since MatrixSpace
// does not (yet) allow assigments from different Cmpt types.
}
else if (narrowTransfer_ && parallel_ && UPstream::parRun())
{
// The narrowed type
typedef typename narrowType<Type>::type narrowedType;
using narrowedType = typename narrowType<Type>::type;
// Ensure geometry is also merged
merge();
@ -130,14 +134,29 @@ Foam::surfaceWriters::mydebugWriter::mergeField
ConstPrecisionAdaptor<narrowedType, Type> input(fld);
PrecisionAdaptor<narrowedType, Type> output(allFld);
globIndex.gather
(
input.cref(), // fld,
output.ref(), // allFld,
UPstream::msgType(),
commType_,
UPstream::worldComm
);
if (gatherv_)
{
globIndex.mpiGather
(
input.cref(), // fld
output.ref(), // allFld
UPstream::worldComm,
// For fallback:
commType_,
UPstream::msgType()
);
}
else
{
globIndex.gather
(
input.cref(), // fld
output.ref(), // allFld
UPstream::msgType(),
commType_,
UPstream::worldComm
);
}
// Commit adapted content changes
input.commit();
@ -193,8 +212,19 @@ Foam::surfaceWriters::mydebugWriter::mydebugWriter
{
Info<< "Using debug surface writer ("
<< (this->isPointData() ? "point" : "face") << " data):"
<< " commsType=" << UPstream::commsTypeNames[commType_]
<< " merge=" << Switch::name(enableMerge_)
<< " commsType=";
if (UPstream::parRun())
{
if (gatherv_) Info<< "gatherv+";
Info<< UPstream::commsTypeNames[commType_];
}
else
{
Info<< "serial";
}
Info<< " merge=" << Switch::name(enableMerge_)
<< " write=" << Switch::name(enableWrite_)
<< " narrow=" << Switch::name(narrowTransfer_)
<< endl;

View File

@ -43,6 +43,29 @@ Description
using namespace Foam;
const char yesno[2] = { 'n', 'y' };
void printIntegralTest(const token& tok)
{
Info<< "Test: " << tok.info() << nl
<< " is int32 = " << yesno[tok.is_int32()]
<< ", int64 = " << yesno[tok.is_int64()]
<< ", uint32 = " << yesno[tok.is_uint32()]
<< ", uint64 = " << yesno[tok.is_uint64()]
<< nl;
}
void printFloatTest(const token& tok)
{
Info<< "Test: " << tok.info() << nl
<< " is float = " << yesno[tok.isFloat()]
<< ", double = " << yesno[tok.isDouble()]
<< ", number = " << yesno[tok.isNumber()]
<< nl;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
@ -56,6 +79,23 @@ int main(int argc, char *argv[])
token tok1;
Info<< "default construct: " << tok1.info() << endl;
tok1 = label(100);
Info<< "assign label: " << tok1.info() << endl;
tok1 = int64_t(100);
Info<< "assign int64: " << tok1.info() << endl;
tok1 = int32_t(100);
Info<< "assign int32: " << tok1.info() << endl;
{
tok1.int64Token(int64_t(INT32_MIN)-1);
Info<< "set int64Token: " << tok1.info() << endl;
printIntegralTest(tok1);
printFloatTest(tok1);
}
tok1 = double(3.14159);
Info<< "assign double: " << tok1.info() << endl;

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2020 OpenCFD Ltd.
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -30,7 +30,8 @@ Group
grpPostProcessingUtilities
Description
List regions from constant/regionProperties.
List volume regions from constant/regionProperties
or area regions from constant/finite-area/regionProperties
Usage
\b foamListRegions [OPTION]
@ -45,6 +46,9 @@ Note
#include "Time.H"
#include "regionProperties.H"
// Same as faMesh::prefix() but without additional linkage
constexpr const char* const faMeshPrefix = "finite-area";
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -53,7 +57,8 @@ int main(int argc, char *argv[])
{
argList::addNote
(
"List regions from constant/regionProperties"
"List volume regions from constant/regionProperties,\n"
"or area regions from constant/finite-area/regionProperties"
);
argList::noBanner();
@ -62,12 +67,55 @@ int main(int argc, char *argv[])
argList::noFunctionObjects(); // Never use function objects
// No profiling since there is no time loop
argList::addBoolOption
(
"finite-area",
"List constant/finite-area/regionProperties (if available)"
);
argList::addBoolOption
(
"optional",
"A missing regionProperties is not treated as an error"
);
argList::addDryRunOption
(
"Make reading optional and add verbosity"
);
argList::addVerboseOption("Additional verbosity");
// Arguments are optional (non-mandatory)
argList::noMandatoryArgs();
argList::addArgument("regionType ... regionType");
#include "setRootCase.H"
const bool dryRun = args.dryRun();
int optVerbose = args.verbose();
if (dryRun && !optVerbose)
{
++optVerbose;
}
// File is optional, not an error
const bool isOptional = args.found("optional");
// Use finite-area regions
const bool doFiniteArea = args.found("finite-area");
// The number of optional region filters to apply
const label nFilters = (args.size()-1);
IOobjectOption::readOption readOpt(IOobjectOption::MUST_READ);
if (dryRun || isOptional || doFiniteArea)
{
// The finite-area regionProperties are also considered optional
readOpt = IOobjectOption::READ_IF_PRESENT;
}
// Silent version of "createTime.H", without libraries
Time runTime
(
@ -77,30 +125,74 @@ int main(int argc, char *argv[])
false // no enableLibs
);
regionProperties rp(runTime);
regionProperties regionProps;
if (doFiniteArea)
{
regionProps = regionProperties(runTime, faMeshPrefix, readOpt);
}
else
{
regionProps = regionProperties(runTime, readOpt);
}
// Some reporting...
if (regionProps.empty())
{
if (doFiniteArea)
{
InfoErr<< "No finite-area region types" << nl;
}
else if (isOptional)
{
InfoErr<< "No region types" << nl;
}
}
else if (optVerbose)
{
InfoErr << "Have " << regionProps.size();
if (doFiniteArea)
{
InfoErr<< " finite-area";
}
InfoErr
<< " region types, "
<< regionProps.count() << " regions" << nl << nl;
}
// We now handle checking args and general sanity etc.
wordList regionTypes;
if (args.size() > 1)
DynamicList<word> regionTypes;
if (isOptional && regionProps.empty())
{
regionTypes.resize(args.size()-1);
// Nothing to do...
}
else if (nFilters > 0)
{
// Apply region filters
// No duplicates
regionTypes.reserve_exact
(
Foam::min(nFilters, regionProps.size())
);
// No duplicates, and no duplicate warnings
wordHashSet uniq;
label nTypes = 0;
for (label argi = 1; argi < args.size(); ++argi)
{
regionTypes[nTypes] = args[argi];
const word& regType = regionTypes[nTypes];
word regType(args[argi]);
if (uniq.insert(regType))
{
if (rp.found(regType))
if (regionProps.contains(regType))
{
++nTypes;
if (!regionTypes.contains(regType))
{
regionTypes.push_back(std::move(regType));
}
}
else
{
@ -108,22 +200,22 @@ int main(int argc, char *argv[])
}
}
}
regionTypes.resize(nTypes);
}
else
{
regionTypes = rp.sortedToc();
// Take all regions
regionTypes = regionProps.sortedToc();
}
for (const word& regionType : regionTypes)
{
const wordList& regionNames = rp[regionType];
for (const word& regionName : regionNames)
if (const auto iter = regionProps.cfind(regionType); iter.good())
{
Info<< regionName << nl;
for (const word& regionName : iter.val())
{
Info<< regionName << nl;
}
}
}

View File

@ -418,8 +418,14 @@ int main(int argc, char *argv[])
// Allow explicit -constant, have zero from time range
timeSelector::addOptions(true, false); // constant(true), zero(false)
// Prevent volume BCs from triggering finite-area
regionModels::allowFaModels(false);
#include "setRootCase.H"
// ------------------------------------------------------------------------
// Configuration
const bool writeCellDist = args.found("cellDist");
// Most of these are ignored for dry-run (not triggered anywhere)

View File

@ -135,9 +135,14 @@ int main(int argc, char *argv[])
"Only reconstruct new times (i.e. that do not exist already)"
);
// Prevent volume BCs from triggering finite-area
regionModels::allowFaModels(false);
#include "setRootCase.H"
#include "createTime.H"
// ------------------------------------------------------------------------
// Configuration
const bool doFields = !args.found("no-fields");
wordRes selectedFields;

View File

@ -780,11 +780,17 @@ int main(int argc, char *argv[])
#include "addAllRegionOptions.H"
// Prevent volume BCs from triggering finite-area
regionModels::allowFaModels(false);
#include "setRootCase.H"
#include "createTime.H"
printWarning();
// ------------------------------------------------------------------------
// Configuration
const bool fullMatch = args.found("fullMatch");
const bool procMatch = args.found("procMatch");
const bool writeCellDist = args.found("cellDist");

View File

@ -1,12 +1,12 @@
passivePositionParticleCloud.C
passivePositionParticleCloud.cxx
parLagrangianDistributor.C
parLagrangianDistributorFields.C
parLagrangianDistributor.cxx
parLagrangianDistributorFields.cxx
parPointFieldDistributor.C
parFaFieldDistributorCache.C
parFvFieldDistributor.C
parFvFieldDistributorFields.C
parPointFieldDistributor.cxx
parFaFieldDistributorCache.cxx
parFvFieldDistributor.cxx
parFvFieldDistributorFields.cxx
loadOrCreateMesh.C
redistributePar.C

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.
@ -30,7 +30,7 @@ Description
Simple container to manage read/write, redistribute finiteArea fields.
SourceFiles
parFaFieldDistributorCache.C
parFaFieldDistributorCache.cxx
\*---------------------------------------------------------------------------*/
@ -71,6 +71,20 @@ class parFaFieldDistributorCache
// Private Member Functions
//- Read distributed fields
template<class BoolListType>
void readImpl
(
const Time& baseRunTime,
const fileName& proc0CaseName,
const bool decompose, // i.e. read from undecomposed case
const BoolListType& areaMeshOnProc,
refPtr<fileOperation>& readHandler,
const fileName& areaMeshInstance,
faMesh& mesh
);
//- Redistribute and write fields of given type (file-scope use)
template<class GeoField>
static void redistributeAndWrite
@ -102,9 +116,24 @@ public:
(
const Time& baseRunTime,
const fileName& proc0CaseName,
const bool decompose, // i.e. read from undecomposed case
//! read from undecomposed case?
const bool decompose,
//! Existence of the processor-local mesh (bitset)
const bitSet& areaMeshOnProc,
refPtr<fileOperation>& readHandler,
const fileName& areaMeshInstance,
faMesh& mesh
);
const boolList& areaMeshOnProc,
//- Read distributed fields
void read
(
const Time& baseRunTime,
const fileName& proc0CaseName,
//! read from undecomposed case?
const bool decompose,
//! Existence of the processor-local mesh (bool list)
const boolUList& areaMeshOnProc,
refPtr<fileOperation>& readHandler,
const fileName& areaMeshInstance,
faMesh& mesh

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.
@ -55,15 +55,14 @@ void Foam::parFaFieldDistributorCache::redistributeAndWrite
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::parFaFieldDistributorCache::read
template<class BoolListType>
void Foam::parFaFieldDistributorCache::readImpl
(
const Time& baseRunTime,
const fileName& proc0CaseName,
const bool decompose, // i.e. read from undecomposed case
const boolList& areaMeshOnProc,
const BoolListType& areaMeshOnProc,
refPtr<fileOperation>& readHandler,
const fileName& areaMeshInstance,
faMesh& mesh
@ -75,14 +74,14 @@ void Foam::parFaFieldDistributorCache::read
autoPtr<faMeshSubset> subsetterPtr;
// Missing an area mesh somewhere?
if (areaMeshOnProc.found(false))
if (!areaMeshOnProc.all())
{
const bool oldParRun = UPstream::parRun(false);
const int oldCache = fileOperation::cacheLevel(0);
// A zero-sized mesh with boundaries.
// This is used to create zero-sized fields.
subsetterPtr.reset(new faMeshSubset(mesh, zero{}));
subsetterPtr.reset(new faMeshSubset(mesh, Foam::zero{}));
fileOperation::cacheLevel(oldCache);
UPstream::parRun(oldParRun); // Restore parallel state
@ -162,6 +161,60 @@ void Foam::parFaFieldDistributorCache::read
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::parFaFieldDistributorCache::read
(
const Time& baseRunTime,
const fileName& proc0CaseName,
const bool decompose, // i.e. read from undecomposed case
const bitSet& areaMeshOnProc,
refPtr<fileOperation>& readHandler,
const fileName& areaMeshInstance,
faMesh& mesh
)
{
readImpl
(
baseRunTime,
proc0CaseName,
decompose,
areaMeshOnProc,
readHandler,
areaMeshInstance,
mesh
);
}
void Foam::parFaFieldDistributorCache::read
(
const Time& baseRunTime,
const fileName& proc0CaseName,
const bool decompose, // i.e. read from undecomposed case
const boolUList& areaMeshOnProc,
refPtr<fileOperation>& readHandler,
const fileName& areaMeshInstance,
faMesh& mesh
)
{
readImpl
(
baseRunTime,
proc0CaseName,
decompose,
areaMeshOnProc,
readHandler,
areaMeshInstance,
mesh
);
}
void Foam::parFaFieldDistributorCache::redistributeAndWrite
(
const faMeshDistributor& distributor,

View File

@ -35,9 +35,9 @@ Description
baseMesh is non-zero cells on processor0 only.
SourceFiles
parFvFieldDistributor.C
parFvFieldDistributorFields.C
parFvFieldDistributorTemplates.C
parFvFieldDistributor.cxx
parFvFieldDistributor.txx
parFvFieldDistributorFields.cxx
\*---------------------------------------------------------------------------*/
@ -228,7 +228,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "parFvFieldDistributorTemplates.C"
# include "parFvFieldDistributor.txx"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -33,9 +33,9 @@ Description
Runs in parallel. Redistributes from fromMesh to toMesh.
SourceFiles
parLagrangianDistributor.C
parLagrangianDistributorFields.C
parLagrangianDistributorTemplates.C
parLagrangianDistributor.cxx
parLagrangianDistributor.txx
parLagrangianDistributorFields.cxx
\*---------------------------------------------------------------------------*/
@ -226,7 +226,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "parLagrangianDistributorTemplates.C"
# include "parLagrangianDistributor.txx"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -46,8 +46,8 @@ Description
Runs in parallel. Redistributes from srcMesh to tgtMesh.
SourceFiles
parPointFieldDistributor.C
parPointFieldDistributorTemplates.C
parPointFieldDistributor.cxx
parPointFieldDistributor.txx
\*---------------------------------------------------------------------------*/
@ -266,7 +266,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "parPointFieldDistributorTemplates.C"
# include "parPointFieldDistributor.txx"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -30,7 +30,7 @@ Description
A Cloud of passive position particles
SourceFiles
passivePositionParticleCloud.C
passivePositionParticleCloud.cxx
\*---------------------------------------------------------------------------*/
@ -79,7 +79,7 @@ public:
passivePositionParticleCloud
(
const polyMesh& mesh,
const Foam::zero,
Foam::zero,
const word& cloudName = cloud::defaultName
)
:

View File

@ -48,13 +48,11 @@ PtrList<unmappedPassivePositionParticleCloud>
readLagrangian
(
const fvMesh& mesh,
const wordList& cloudNames,
const UList<word>& cloudNames,
const boolUList& haveClouds,
const wordRes& selectedFields
)
{
PtrList<unmappedPassivePositionParticleCloud> clouds(cloudNames.size());
if (!cloudNames.empty())
{
(void)mesh.tetBasePtIs();
@ -72,16 +70,16 @@ readLagrangian
// Setup clouds
PtrList<unmappedPassivePositionParticleCloud> clouds(cloudNames.size());
forAll(cloudNames, i)
{
//Pout<< "Loading cloud " << cloudNames[i] << endl;
clouds.set
(
i,
new unmappedPassivePositionParticleCloud(mesh, cloudNames[i], false)
);
const auto& cloudName = cloudNames[i];
//Pout<< "Loading cloud " << cloudName << endl;
//for (passivePositionParticle& p : clouds[i]))
auto& cloud = clouds.emplace_set(i, mesh, cloudName, false);
//for (passivePositionParticle& p : cloud)
//{
// Pout<< "Particle position:" << p.position()
// << " cell:" << p.cell()
@ -89,12 +87,12 @@ readLagrangian
// << endl;
//}
IOobjectList cloudObjs(clouds[i], clouds[i].time().timeName());
IOobjectList cloudObjs(cloud, cloud.time().timeName());
parLagrangianDistributor::readAllFields
(
clouds[i],
haveClouds[i],
cloud,
haveClouds.test(i),
cloudObjs,
selectedFields
);

View File

@ -1257,6 +1257,8 @@ int main(int argc, char *argv[])
true // Advanced option
);
// Prevent volume BCs from triggering finite-area
regionModels::allowFaModels(false);
//- Disable caching of times/processor dirs etc. Cause massive parallel
// problems when e.g decomposing.
@ -1269,6 +1271,7 @@ int main(int argc, char *argv[])
argList args(argc, argv);
// ------------------------------------------------------------------------
// As much as possible avoid synchronised operation. To be looked at more
// closely for the three scenarios:

View File

@ -31,9 +31,6 @@ Description
passivePositionParticleCloud but with autoMap and writing disabled.
Only used for its objectRegistry to store lagrangian fields
SourceFiles
unmappedPassivePositionParticleCloud.C
\*---------------------------------------------------------------------------*/
#ifndef Foam_unmappedPassivePositionParticleCloud_H
@ -73,7 +70,7 @@ public:
unmappedPassivePositionParticleCloud
(
const polyMesh& mesh,
const Foam::zero,
Foam::zero,
const word& cloudName = cloud::defaultName
)
:

View File

@ -323,6 +323,9 @@ int main(int argc, char *argv[])
);
argList::addOptionCompat("cellZones", {"cellZone", 1912});
// Prevent volume BCs from triggering finite-area
regionModels::allowFaModels(false);
#include "setRootCase.H"
// ------------------------------------------------------------------------

View File

@ -479,8 +479,14 @@ int main(int argc, char *argv[])
"Directory name for VTK output (default: 'VTK')"
);
// Prevent volume BCs from triggering finite-area
regionModels::allowFaModels(false);
#include "setRootCase.H"
// ------------------------------------------------------------------------
// Configuration
/// const int optVerbose = args.verbose();
const bool decomposePoly = args.found("poly-decomp");
const bool doBoundary = !args.found("no-boundary");

View File

@ -79,6 +79,7 @@ scalar calcVertexNormalWeight
{
FatalErrorInFunction
<< "Point not in face" << abort(FatalError);
return 0;
}
const vector e1 = points[f[index]] - points[f[f.fcIndex(index)]];

138
bin/foamCleanFaMesh Executable file
View File

@ -0,0 +1,138 @@
#!/bin/sh
#------------------------------------------------------------------------------
# ========= |
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
# \\ / O peration |
# \\ / A nd | www.openfoam.com
# \\/ M anipulation |
#-------------------------------------------------------------------------------
# Copyright (C) 2011 OpenFOAM Foundation
# Copyright (C) 2025 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
#
# Script
# foamCleanFaMesh
#
# Description
# Remove the contents of the constant/finite-area/faMesh directory
# as per the Foam::faMesh::removeFiles() method.
#
#------------------------------------------------------------------------------
usage() {
exec 1>&2
while [ "$#" -ge 1 ]; do echo "$1"; shift; done
cat <<USAGE
Usage: ${0##*/} [OPTION]
options:
-case <dir> case directory, default is the cwd
-area-region <name> area-mesh region
-dry-run | -n report actions but do not remove
-help print the usage
Remove the contents of the constant/finite-area/faMesh directory as per the
Foam::faMesh::removeFiles() method.
USAGE
exit 1
}
#------------------------------------------------------------------------------
# Parse options
unset caseDir areaRegion optDryRun
while [ "$#" -gt 0 ]
do
case "$1" in
-h | -help*)
usage
;;
-dry-run | -n)
optDryRun="(dry-run) "
;;
-case=*)
caseDir="${1#*=}"
;;
-case)
[ "$#" -ge 2 ] || usage "'$1' option requires an argument"
cd "$2" 2>/dev/null || usage "directory does not exist: '$2'"
caseDir=$2
shift
;;
-area-region)
[ "$#" -ge 2 ] || usage "'$1' option requires an argument"
areaRegion=$2
shift
;;
(*)
usage "unknown option/argument: '$*'"
;;
esac
shift
done
#------------------------------------------------------------------------------
# Remove files (mesh etc)
# also remove .gz versions of the same files
removeFiles()
{
local directory="$1"
for i in \
faceLabels \
faBoundary \
;
do
if [ -n "$optDryRun" ]
then
echo "${optDryRun} rm -rf $directory/{$i,$i.gz}"
else
rm -rf -- "$directory/$i" "$directory/$i.gz"
fi
done
}
#------------------------------------------------------------------------------
meshDir="constant/finite-area/${areaRegion}${areaRegion:+/}faMesh"
if [ -d "$meshDir" ]
then
# [OK] has constant/finite-areaRegion/<region>/faMesh
:
elif [ -n "$caseDir" ]
then
# Specified -case, so no extra magic...
echo "Error: no <$meshDir> in $caseDir" 1>&2
exit 1
else
# Try some other combinations
other="${meshDir#constant/}"
if [ -d "$other" ]
then
# Probably already within constant/
meshDir="$other}"
elif [ "${PWD##*/}" = faMesh ] && [ -z "$areaRegion" ]
then
# Apparently already within faMesh/
meshDir=.
fi
fi
echo "Cleaning ${caseDir:-.}/$meshDir" 1>&2
removeFiles "$meshDir"
#------------------------------------------------------------------------------

View File

@ -7,7 +7,7 @@
# \\/ M anipulation |
#-------------------------------------------------------------------------------
# Copyright (C) 2011-2016 OpenFOAM Foundation
# Copyright (C) 2022 OpenCFD Ltd.
# Copyright (C) 2022,2025 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
@ -27,9 +27,10 @@ usage() {
Usage: ${0##*/} [OPTION]
options:
-case <dir> specify alternative case directory, default is the cwd
-region <name> specify alternative mesh region
-help print the usage
-case <dir> case directory, default is the cwd
-region <name> mesh region
-dry-run | -n report actions but do not remove
-help print the usage
Remove the contents of the constant/polyMesh directory as per the
Foam::polyMesh::removeFiles() method.
@ -38,58 +39,101 @@ USAGE
exit 1
}
unset caseDir regionName
#------------------------------------------------------------------------------
# Parse options
unset caseDir regionName optDryRun
# Parse a single option
while [ "$#" -gt 0 ]
do
case "$1" in
-h | -help*)
usage
;;
-dry-run | -n)
optDryRun="(dry-run) "
;;
-case=*)
caseDir="${1#*=}"
;;
-case)
caseDir="$2"
[ "$#" -ge 2 ] || usage "'$1' option requires an argument"
cd "$2" 2>/dev/null || usage "directory does not exist: '$2'"
caseDir=$2
shift 2
shift
;;
-region)
[ "$#" -ge 2 ] || usage "'$1' option requires an argument"
regionName=$2
shift 2
regionName="$2"
shift
;;
*)
(*)
usage "unknown option/argument: '$*'"
;;
esac
shift
done
meshDir=polyMesh
if [ -n "$regionName" ]
then
meshDir="$regionName/$meshDir"
fi
#------------------------------------------------------------------------------
# If -case was specified: insist upon 'constant/polyMesh'
if [ -n "$caseDir" ]
# Remove files (mesh itself, modifiers, snappyHexMesh ones) and subdirectories
# also remove .gz versions of the same files
removeFiles()
{
local directory="$1"
for i in \
points faces \
owner neighbour \
boundary \
cells \
cellZones faceZones pointZones \
meshModifiers \
parallelData \
sets \
cellLevel pointLevel \
level0Edge \
refinementHistory \
surfaceIndex \
;
do
if [ -n "$optDryRun" ]
then
echo "${optDryRun} rm -rf $directory/{$i,$i.gz}"
else
rm -rf -- "$directory/$i" "$directory/$i.gz"
fi
done
}
#------------------------------------------------------------------------------
meshDir="constant/${regionName}${regionName:+/}polyMesh"
if [ -d "$meshDir" ]
then
if [ -d constant/"$meshDir" ]
then
# Use constant/polyMesh
meshDir=constant/"$meshDir"
else
echo "Error: no 'constant/$meshDir' in $caseDir" 1>&2
exit 1
fi
# [OK] has constant/<region>/polyMesh
:
elif [ -n "$caseDir" ]
then
# Specified -case, so no extra magic...
echo "Error: no <$meshDir> in $caseDir" 1>&2
exit 1
else
if [ -d constant/"$meshDir" ]
# Try some other combinations
other="${meshDir#constant/}"
if [ -d "$other" ]
then
# Use constant/polyMesh
meshDir=constant/"$meshDir"
elif [ -d "$meshDir" ]
then
# Likely already in constant/ - do not adjust anything
:
# Probably already within constant/
meshDir="$other}"
elif [ "${PWD##*/}" = polyMesh ] && [ -z "$regionName" ]
then
# Apparently already within polyMesh/
@ -98,31 +142,8 @@ else
fi
# Remove files (mesh itself, modifiers, snappyHexMesh ones) and subdirectories
# also remove .gz versions of the same files
echo "Cleaning ${caseDir:-.}/$meshDir" 1>&2
for i in \
points \
faces \
owner \
neighbour \
cells \
boundary \
pointZones \
faceZones \
cellZones \
meshModifiers \
parallelData \
sets \
cellLevel \
pointLevel \
level0Edge \
refinementHistory \
surfaceIndex \
;
do
rm -rf "$meshDir/$i" "$meshDir/$i.gz"
done
removeFiles "$meshDir"
#------------------------------------------------------------------------------

View File

@ -108,54 +108,116 @@ cleanPostProcessing()
}
# ---------------
# Remove constant/finite-area/faMesh or constant/finite-area/{region}/faMesh
#
# Accepts following options:
# -region <name> The region name
# -- End of options
# ---------------
cleanFaMesh()
{
if [ -e constant/finite-area/faMesh ]
local region
# Parse options
while [ "$#" -gt 0 ]
do
case "$1" in
('') ;; # Ignore empty option
(--) shift; break ;; # Stop option parsing
(-region) region="$2"; shift ;;
(*) break ;;
esac
shift
done
# safety
if [ "$region" = "--" ]; then unset region; fi
local meshDir="constant/finite-area/${region}${region:+/}faMesh"
if [ -e "$meshDir" ]
then
rm -rf constant/finite-area/faMesh
[ -n "$region" ] && echo "Clearing $meshDir" 1>&2
rm -rf -- "$meshDir"
fi
if [ -e constant/faMesh ]
# Legacy location <constant/faMesh>
# - may still have remnant <constant/faMesh/faMeshDefinition>
meshDir="constant/faMesh"
if [ -e "$meshDir" ] && [ -z "$region" ]
then
if [ -e constant/faMesh/faMeshDefinition ]
if [ -e "$meshDir"/faMeshDefinition ]
then
# Old constant/faMesh location for faMeshDefinition still in use:
# - warn but don't remove anything
# VERY OLD LOCATION
echo
echo "Warning: not removing constant/faMesh/"
echo "WARNING: not removing $meshDir/"
echo " It contains a 'faMeshDefinition' file"
echo " Please relocate file(s) to system/ !!"
echo " Please relocate file(s) to system/finite-area/ !!"
echo
else
# Can remove constant/faMesh/ entirely (no faMeshDefinition)
rm -rf constant/faMesh
echo "Clearing $meshDir" 1>&2
rm -rf -- "$meshDir"
fi
fi
}
# ---------------
# Remove constant/polyMesh or constant/<region>/polyMesh
#
# Accepts following options:
# -region <name> The region name
# -- End of options
# ---------------
cleanPolyMesh()
{
if [ -e constant/polyMesh ]
local region
# Parse options
while [ "$#" -gt 0 ]
do
case "$1" in
('') ;; # Ignore empty option
(--) shift; break ;; # Stop option parsing
(-region) region="$2"; shift ;;
(*) break ;;
esac
shift
done
# safety
if [ "$region" = "--" ]; then unset region; fi
local meshDir="constant/${region}${region:+/}polyMesh"
if [ -e "$meshDir" ]
then
if [ -e constant/polyMesh/blockMeshDict ] \
|| [ -e constant/polyMesh/blockMeshDict.m4 ]
[ -n "$region" ] && echo "Clearing $meshDir" 1>&2
if [ -e "$meshDir"/blockMeshDict ] \
|| [ -e "$meshDir"/blockMeshDict.m4 ]
then
# Old constant/polyMesh location for blockMeshDict still in use:
# - warn but don't remove anything
# VERY OLD LOCATION
echo
echo "Warning: not removing constant/polyMesh/"
echo "WARNING: not removing $meshDir/"
echo " It contains a 'blockMeshDict' or 'blockMeshDict.m4' file"
echo " Please relocate file(s) to system/ !!"
echo
else
# Can remove constant/polyMesh/ entirely (no blockMeshDict)
rm -rf constant/polyMesh
rm -rf -- "$meshDir"
fi
fi
if [ -e system/blockMeshDict.m4 ]
meshDir="system${region:+/}${region}"
if [ -e "$meshDir"/blockMeshDict.m4 ]
then
rm -f system/blockMeshDict
rm -f -- "$meshDir"/blockMeshDict
fi
}
@ -212,7 +274,7 @@ cleanCase0()
removeCase()
{
echo "Removing case ${1:-unknown}"
[ "$#" -ge 1 ] && rm -rf "$1"
[ "$#" -ge 1 ] && rm -rf -- "$1"
}

View File

@ -517,9 +517,11 @@ cloneParallelCase()
}
# ---------------
# If 0.orig/ exists, copy (overwrite) into 0/ [ie, serial case]
# * -processor : copy into processor directories instead
# * -all : copy into serial and processor directories
# ---------------
restore0Dir()
{
if [ ! -d 0.orig ]
@ -553,4 +555,61 @@ restore0Dir()
}
# ---------------
# Helper routine to remove specified fields from the 0/ directory.
# Often used in combination with foamListRegions.
#
# Accepts following options:
# -region <name> The region name
# -- End of options
#
# any remaining parameters are taken to be fields names
# ---------------
remove0DirFields()
{
local region
# Parse options
while [ "$#" -gt 0 ]
do
case "$1" in
('') ;; # Ignore empty option
(--) shift; break ;; # Stop option parsing
(-region) region="$2"; shift ;;
(*) break ;;
esac
shift
done
# safety
if [ "$region" = "--" ]; then unset region; fi
if [ "$#" -eq 0 ]
then
echo "No fields specified for ${region:+region=$region }" 1>&2
return 0
fi
echo "Remove 0/ fields${region:+ [$region]} : $@" 1>&2
local subdir
for subdir in 0/"$region" processor*/0/"$region"
do
if [ -d "$subdir" ]
then
for field in $@ ## unquoted for IFS splitting [SIC]
do
# Cautious with removal
if [ -f "$subdir/$field" ]
then
rm -f -- "$subdir/$field"
fi
done
fi
done
return 0
}
#------------------------------------------------------------------------------

View File

@ -140,6 +140,11 @@ _of_complete_()
# Could use "foamListTimes -withZero", but still doesn't address ranges
COMPREPLY=($(compgen -d -X '![-0-9]*' -- ${cur}))
;;
-area-region)
# Or: $(find system/finite-area -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sed -e 's%.*/%%')
choices=$(\ls -d system/finite-area/*/ 2>/dev/null | sed -e 's%/$%%; s%^.*/%%')
COMPREPLY=($(compgen -W "$choices" -- ${cur}))
;;
-region)
# Or: $(find system -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sed -e 's%.*/%%')
choices=$(\ls -d system/*/ 2>/dev/null | sed -e 's%/$%%; s%^.*/%%')

View File

@ -1,7 +1,7 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v2512 |
| \\ / O peration | Version: v2506 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
@ -108,11 +108,6 @@ OptimisationSwitches
// uncollated (default), collated, masterUncollated etc.
fileHandler uncollated;
//- Preferred backend for collated format. Default: 0
// 0: legacy writer
// 1: MPI/IO writer
collated.backend 0;
//- collated: thread buffer size for queued file writes.
// If set to 0 or not sufficient for the file size, threading is not used.
// A special setting is a negative value which assumes the buffer

View File

@ -55,8 +55,6 @@ wmake $targetType fileFormats
wmake $targetType surfMesh
wmake $targetType meshTools
#------------------------------------------------------------------------------
wmake $targetType finiteArea
wmake $targetType finiteVolume
wmake $targetType fused/finiteVolume

View File

@ -1 +0,0 @@
#warning File removed - left for old dependency check only

View File

@ -1 +0,0 @@
#warning File removed - left for old dependency check only

View File

@ -116,7 +116,7 @@ public:
inline explicit DynamicList(const label initialCapacity);
//- Construct with given size and capacity
inline explicit DynamicList(const std::pair<label,label>& sizing);
inline explicit DynamicList(std::pair<label,label> sizing);
//- Construct with given size and value for all elements.
inline DynamicList(const label len, const T& val);

View File

@ -66,13 +66,10 @@ inline void Foam::DynamicList<T, SizeMin>::doCapacity_copy
}
// Addressable length, possibly truncated by new capacity
const label currLen = Foam::min(List<T>::size(), newCapacity);
const label currLen = std::min(List<T>::size(), newCapacity);
// The count truncated by the new addressable range
if (count > currLen)
{
count = currLen;
}
count = std::min(count, currLen);
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
@ -104,10 +101,7 @@ inline void Foam::DynamicList<T, SizeMin>::doReserve_copy
const label currLen = List<T>::size();
// The count truncated by the addressable range
if (count > currLen)
{
count = currLen;
}
count = std::min(count, currLen);
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
@ -155,7 +149,7 @@ inline Foam::DynamicList<T, SizeMin>::DynamicList(const label initialCapacity)
template<class T, int SizeMin>
inline Foam::DynamicList<T, SizeMin>::DynamicList
(
const std::pair<label,label>& sizing
std::pair<label,label> sizing
)
:
List<T>(std::max(sizing.first, sizing.second)),

View File

@ -200,27 +200,7 @@ Foam::Istream& Foam::DynamicList<T, SizeMin>::readList(Istream& is)
// Resize to length required
list.resize_nocopy(len);
if (is.format() == IOstreamOption::BINARY && is_contiguous_v<T>)
{
// Binary and contiguous
if (len)
{
Detail::readContiguous<T>
(
is,
list.data_bytes(),
list.size_bytes()
);
is.fatalCheck
(
"DynamicList<T>::readList(Istream&) : "
"reading binary block"
);
}
}
else if constexpr (std::is_same_v<char, std::remove_cv_t<T>>)
if constexpr (std::is_same_v<char, std::remove_cv_t<T>>)
{
// Special treatment for char data (binary I/O only)
const auto oldFmt = is.format(IOstreamOption::BINARY);
@ -232,8 +212,7 @@ Foam::Istream& Foam::DynamicList<T, SizeMin>::readList(Istream& is)
is.fatalCheck
(
"DynamicList<char>::readList(Istream&) : "
"reading binary block"
"DynamicList<char>::readList(Istream&) : [binary block]"
);
}
@ -241,48 +220,70 @@ Foam::Istream& Foam::DynamicList<T, SizeMin>::readList(Istream& is)
}
else
{
// Begin of contents marker
const char delimiter = is.readBeginList("List");
if (len)
if (is.format() == IOstreamOption::BINARY && is_contiguous_v<T>)
{
if (delimiter == token::BEGIN_LIST)
{
auto iter = list.begin();
const auto last = list.end();
// Binary and contiguous
// Contents
for (/*nil*/; (iter != last); (void)++iter)
if (len)
{
Detail::readContiguous<T>
(
is,
list.data_bytes(),
list.size_bytes()
);
is.fatalCheck
(
"DynamicList<T>::readList(Istream&) : [binary block]"
);
}
}
else
{
// Begin of contents marker
const char delimiter = is.readBeginList("List");
if (len)
{
if (delimiter == token::BEGIN_LIST)
{
is >> *iter;
auto iter = list.begin();
const auto last = list.end();
// Contents
for (/*nil*/; (iter != last); (void)++iter)
{
is >> *iter;
is.fatalCheck
(
"DynamicList<T>::readList(Istream&) : "
"reading entry"
);
}
}
else
{
// Uniform content (delimiter == token::BEGIN_BLOCK)
T elem;
is >> elem;
is.fatalCheck
(
"DynamicList<T>::readList(Istream&) : "
"reading entry"
"reading the single entry"
);
// Fill with the value
UList<T>::operator=(elem);
}
}
else
{
// Uniform content (delimiter == token::BEGIN_BLOCK)
T elem;
is >> elem;
is.fatalCheck
(
"DynamicList<T>::readList(Istream&) : "
"reading the single entry"
);
// Fill with the value
UList<T>::operator=(elem);
}
// End of contents marker
is.readEndList("List");
}
// End of contents marker
is.readEndList("List");
}
}
else if (tok.isPunctuation(token::BEGIN_LIST))

View File

@ -48,16 +48,12 @@ void Foam::List<T>::resize_copy(label count, const label len)
T* old = this->v_;
const label oldLen = this->size_;
if (count > len)
{
count = len; // The count truncated by the new length
}
// The count truncated by the new length?
count = std::min(count, len);
// Extra safety, probably not necessary:
// if (count > oldLen)
// {
// count = oldLen; // The count truncated by the old length
// }
// The count truncated by the old length?
// // count = std::min(count, oldLen);
if (count > 0)
{
@ -102,6 +98,8 @@ void Foam::List<T>::resize_copy(label count, const label len)
template<class T>
Foam::List<T>::List(const label len)
:
UList<T>()
{
if (FOAM_UNLIKELY(len < 0))
{
@ -120,6 +118,8 @@ Foam::List<T>::List(const label len)
template<class T>
Foam::List<T>::List(const label len, const T& val)
:
UList<T>()
{
if (FOAM_UNLIKELY(len < 0))
{
@ -139,6 +139,8 @@ Foam::List<T>::List(const label len, const T& val)
template<class T>
Foam::List<T>::List(const label len, Foam::zero)
:
UList<T>()
{
if (FOAM_UNLIKELY(len < 0))
{
@ -185,6 +187,8 @@ Foam::List<T>::List(Foam::one, Foam::zero)
template<class T>
Foam::List<T>::List(const UList<T>& list)
:
UList<T>()
{
if (!list.empty())
{
@ -196,6 +200,8 @@ Foam::List<T>::List(const UList<T>& list)
template<class T>
Foam::List<T>::List(const List<T>& list)
:
UList<T>()
{
if (!list.empty())
{
@ -207,6 +213,8 @@ Foam::List<T>::List(const List<T>& list)
template<class T>
Foam::List<T>::List(List<T>& list, bool reuse)
:
UList<T>()
{
if (reuse)
{
@ -226,6 +234,8 @@ Foam::List<T>::List(List<T>& list, bool reuse)
template<class T>
Foam::List<T>::List(const UList<T>& list, const labelUList& indices)
:
UList<T>()
{
if (!indices.empty())
{
@ -242,6 +252,8 @@ Foam::List<T>::List
const UList<T>& list,
const FixedList<label,N>& indices
)
:
UList<T>()
{
// if (!FixedList::empty()) is always true
{
@ -261,6 +273,8 @@ Foam::List<T>::List(const FixedList<T, N>& list)
template<class T>
Foam::List<T>::List(const UPtrList<T>& list)
:
UList<T>()
{
if (!list.empty())
{
@ -273,6 +287,8 @@ Foam::List<T>::List(const UPtrList<T>& list)
template<class T>
template<class Addr>
Foam::List<T>::List(const IndirectListBase<T, Addr>& list)
:
UList<T>()
{
if (!list.empty())
{
@ -292,6 +308,8 @@ Foam::List<T>::List(std::initializer_list<T> list)
template<class T>
template<int SizeMin>
Foam::List<T>::List(DynamicList<T, SizeMin>&& list)
:
UList<T>()
{
transfer(list);
}

View File

@ -45,6 +45,7 @@ SourceFiles
#include "autoPtr.H"
#include "UList.H"
#include "SLListFwd.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -65,7 +66,6 @@ typedef List<bool> boolList; //!< A List of bools
typedef List<char> charList; //!< A List of chars
typedef List<label> labelList; //!< A List of labels
/*---------------------------------------------------------------------------*\
Class List Declaration
\*---------------------------------------------------------------------------*/
@ -395,6 +395,37 @@ public:
//- Alias for resize()
void setSize(label n, const T& val) { this->resize(n, val); }
// Expression templates
//- Construct from value expression
template<typename E>
explicit List
(
const Expression::ListExpression
<
E,
typename E::value_type
>& expr
)
{
expr.evaluate(*this);
}
//- Assign values from expression
template<typename E>
void operator=
(
const Expression::ListExpression
<
E,
typename E::value_type
>& expr
)
{
expr.evaluate(*this);
}
};

View File

@ -88,6 +88,8 @@ inline Foam::List<T>::List
InputIterator inputEnd, // (unused)
const label len
)
:
UList<T>()
{
if (len > 0)
{

View File

@ -200,27 +200,7 @@ Foam::Istream& Foam::List<T>::readList(Istream& is)
// Resize to length required
list.resize_nocopy(len);
if (is.format() == IOstreamOption::BINARY && is_contiguous_v<T>)
{
// Binary and contiguous
if (len)
{
Detail::readContiguous<T>
(
is,
list.data_bytes(),
list.size_bytes()
);
is.fatalCheck
(
"List<T>::readList(Istream&) : "
"reading binary block"
);
}
}
else if constexpr (std::is_same_v<char, std::remove_cv_t<T>>)
if constexpr (std::is_same_v<char, std::remove_cv_t<T>>)
{
// Special treatment for char data (binary I/O only)
const auto oldFmt = is.format(IOstreamOption::BINARY);
@ -232,8 +212,7 @@ Foam::Istream& Foam::List<T>::readList(Istream& is)
is.fatalCheck
(
"List<char>::readList(Istream&) : "
"reading binary block"
"List<char>::readList(Istream&) : [binary block]"
);
}
@ -241,48 +220,70 @@ Foam::Istream& Foam::List<T>::readList(Istream& is)
}
else
{
// Begin of contents marker
const char delimiter = is.readBeginList("List");
if (len)
if (is.format() == IOstreamOption::BINARY && is_contiguous_v<T>)
{
if (delimiter == token::BEGIN_LIST)
{
auto iter = list.begin();
const auto last = list.end();
// Binary and contiguous
// Contents
for (/*nil*/; (iter != last); (void)++iter)
if (len)
{
Detail::readContiguous<T>
(
is,
list.data_bytes(),
list.size_bytes()
);
is.fatalCheck
(
"List<T>::readList(Istream&) : [binary block]"
);
}
}
else
{
// Begin of contents marker
const char delimiter = is.readBeginList("List");
if (len)
{
if (delimiter == token::BEGIN_LIST)
{
is >> *iter;
auto iter = list.begin();
const auto last = list.end();
// Contents
for (/*nil*/; (iter != last); (void)++iter)
{
is >> *iter;
is.fatalCheck
(
"List<T>::readList(Istream&) : "
"reading entry"
);
}
}
else
{
// Uniform content (delimiter == token::BEGIN_BLOCK)
T elem;
is >> elem;
is.fatalCheck
(
"List<T>::readList(Istream&) : "
"reading entry"
"reading the single entry"
);
// Fill with the value
UList<T>::operator=(elem);
}
}
else
{
// Uniform content (delimiter == token::BEGIN_BLOCK)
T elem;
is >> elem;
is.fatalCheck
(
"List<T>::readList(Istream&) : "
"reading the single entry"
);
// Fill with the value
UList<T>::operator=(elem);
}
// End of contents marker
is.readEndList("List");
}
// End of contents marker
is.readEndList("List");
}
}
else if (tok.isPunctuation(token::BEGIN_LIST))

View File

@ -80,6 +80,11 @@ typedef UList<bool> boolUList; //!< A UList of bools
typedef UList<char> charUList; //!< A UList of chars
typedef UList<label> labelUList; //!< A UList of labels
namespace Expression
{
template<class E, typename ValType> class ListExpression;
template<class T> class ListConstRefWrap;
}
/*---------------------------------------------------------------------------*\
Class UList Declaration
@ -697,6 +702,39 @@ public:
{
return this->contains(val, pos);
}
// Expression templates
//- Have unique tag
using is_List = void;
//- Wrap value as expression
auto expr() const
{
return Expression::ListConstRefWrap<T>
(
reinterpret_cast<const List<T>&>(*this)
);
}
//- Assign values from expression
template<typename E>
void operator=
(
const Expression::ListExpression
<
E,
typename E::value_type
>& expr
)
{
// bypass expr.evaluate to avoid resize ...
for (label i = 0; i < expr.size(); ++i)
{
operator[](i) = expr[i];
}
}
};

View File

@ -103,19 +103,7 @@ Foam::Ostream& Foam::UList<T>::writeList
const label len = list.size();
if (os.format() == IOstreamOption::BINARY && is_contiguous_v<T>)
{
// Binary and contiguous
os << nl << len << nl;
if (len)
{
// write(...) includes surrounding start/end delimiters
os.write(list.cdata_bytes(), list.size_bytes());
}
}
else if constexpr (std::is_same_v<char, std::remove_cv_t<T>>)
if constexpr (std::is_same_v<char, std::remove_cv_t<T>>)
{
// Special treatment for char data (binary I/O only)
@ -130,61 +118,76 @@ Foam::Ostream& Foam::UList<T>::writeList
os.format(oldFmt);
}
else if (is_contiguous_v<T> && len > 1 && list.uniform())
{
// Two or more entries, and all entries have identical values.
os << len << token::BEGIN_BLOCK << list[0] << token::END_BLOCK;
}
else if
(
(len <= 1 || !shortLen)
||
(
(len <= shortLen)
&& (is_contiguous_v<T> || Foam::ListPolicy::no_linebreak<T>::value)
)
)
{
// Single-line output
// Size and start delimiter
os << len << token::BEGIN_LIST;
auto iter = list.cbegin();
const auto last = list.cend();
// Contents
if (iter != last)
{
os << *iter;
for (++iter; (iter != last); (void)++iter)
{
os << token::SPACE << *iter;
}
}
// End delimiter
os << token::END_LIST;
}
else
{
// Multi-line output
// Size and start delimiter
os << nl << len << nl << token::BEGIN_LIST;
auto iter = list.cbegin();
const auto last = list.cend();
// Contents
for (/*nil*/; (iter != last); (void)++iter)
if (os.format() == IOstreamOption::BINARY && is_contiguous_v<T>)
{
os << nl << *iter;
}
// Binary and contiguous
// End delimiter
os << nl << token::END_LIST << nl;
os << nl << len << nl;
if (len)
{
// write(...) includes surrounding start/end delimiters
os.write(list.cdata_bytes(), list.size_bytes());
}
}
else if (is_contiguous_v<T> && len > 1 && list.uniform())
{
// Two or more entries, and all entries have identical values.
os << len << token::BEGIN_BLOCK << list[0] << token::END_BLOCK;
}
else if
(
(len <= 1 || !shortLen)
||
(
(len <= shortLen)
&& (is_contiguous_v<T> || Foam::ListPolicy::no_linebreak<T>::value)
)
)
{
// Single-line output
// Size and start delimiter
os << len << token::BEGIN_LIST;
auto iter = list.cbegin();
const auto last = list.cend();
// Contents
if (iter != last)
{
os << *iter;
for (++iter; (iter != last); (void)++iter)
{
os << token::SPACE << *iter;
}
}
// End delimiter
os << token::END_LIST;
}
else
{
// Multi-line output
// Size and start delimiter
os << nl << len << nl << token::BEGIN_LIST;
auto iter = list.cbegin();
const auto last = list.cend();
// Contents
for (/*nil*/; (iter != last); (void)++iter)
{
os << nl << *iter;
}
// End delimiter
os << nl << token::END_LIST << nl;
}
}
os.check(FUNCTION_NAME);
@ -244,26 +247,6 @@ Foam::Istream& Foam::UList<T>::readList(Istream& is)
<< exit(FatalIOError);
}
if (is.format() == IOstreamOption::BINARY && is_contiguous_v<T>)
{
// Binary and contiguous
if (len)
{
Detail::readContiguous<T>
(
is,
list.data_bytes(),
list.size_bytes()
);
is.fatalCheck
(
"UList<T>::readList(Istream&) : "
"reading binary block"
);
}
}
else if constexpr (std::is_same_v<char, std::remove_cv_t<T>>)
{
// Special treatment for char data (binary I/O only)
@ -276,8 +259,7 @@ Foam::Istream& Foam::UList<T>::readList(Istream& is)
is.fatalCheck
(
"UList<char>::readList(Istream&) : "
"reading binary block"
"UList<char>::readList(Istream&) : [binary block]"
);
}
@ -285,44 +267,66 @@ Foam::Istream& Foam::UList<T>::readList(Istream& is)
}
else
{
// Begin of contents marker
const char delimiter = is.readBeginList("List");
if (len)
if (is.format() == IOstreamOption::BINARY && is_contiguous_v<T>)
{
if (delimiter == token::BEGIN_LIST)
// Binary and contiguous
if (len)
{
for (label i=0; i<len; ++i)
Detail::readContiguous<T>
(
is,
list.data_bytes(),
list.size_bytes()
);
is.fatalCheck
(
"UList<T>::readList(Istream&) : [binary block]"
);
}
}
else
{
// Begin of contents marker
const char delimiter = is.readBeginList("List");
if (len)
{
if (delimiter == token::BEGIN_LIST)
{
is >> list[i];
for (label i=0; i<len; ++i)
{
is >> list[i];
is.fatalCheck
(
"UList<T>::readList(Istream&) : "
"reading entry"
);
}
}
else
{
// Uniform content (delimiter == token::BEGIN_BLOCK)
T elem;
is >> elem;
is.fatalCheck
(
"UList<T>::readList(Istream&) : "
"reading entry"
"reading the single entry"
);
// Fill with the value
this->fill_uniform(elem);
}
}
else
{
// Uniform content (delimiter == token::BEGIN_BLOCK)
T elem;
is >> elem;
is.fatalCheck
(
"UList<T>::readList(Istream&) : "
"reading the single entry"
);
// Fill with the value
this->fill_uniform(elem);
}
// End of contents marker
is.readEndList("List");
}
// End of contents marker
is.readEndList("List");
}
}
else if (tok.isPunctuation(token::BEGIN_LIST))

View File

@ -80,7 +80,7 @@ public:
inline explicit PtrDynList(const label len);
//- Construct with given size and capacity
inline explicit PtrDynList(const std::pair<label,label>& sizing);
inline explicit PtrDynList(std::pair<label,label> sizing);
//- Copy construct using 'clone()' method on each element
inline PtrDynList(const PtrDynList<T, SizeMin>& list);

View File

@ -52,7 +52,7 @@ inline Foam::PtrDynList<T, SizeMin>::PtrDynList(const label len)
template<class T, int SizeMin>
inline Foam::PtrDynList<T, SizeMin>::PtrDynList
(
const std::pair<label,label>& sizing
std::pair<label,label> sizing
)
:
PtrList<T>(std::max(sizing.first, sizing.second)),

View File

@ -484,6 +484,13 @@ const Foam::fileName& Foam::IOobject::globalCaseName() const noexcept
}
const Foam::fileName&
Foam::IOobject::caseName(IOobjectOption::Layout layout) const noexcept
{
return time().caseName(layout);
}
Foam::scalar Foam::IOobject::instanceValue() const
{
scalar val(0);
@ -504,6 +511,7 @@ Foam::fileName Foam::IOobject::path() const
return instance();
}
// == time().path()/instance()/db_.dbDir()/local();
return rootPath()/caseName()/instance()/db_.dbDir()/local();
}
@ -515,10 +523,23 @@ Foam::fileName Foam::IOobject::globalPath() const
return instance();
}
// == time().globalPath()/instance()/db_.dbDir()/local();
return rootPath()/globalCaseName()/instance()/db_.dbDir()/local();
}
Foam::fileName Foam::IOobject::path(IOobjectOption::Layout layout) const
{
if (file_isOutsideCase(instance()))
{
return instance();
}
// == time().path(layout)/instance()/db_.dbDir()/local();
return rootPath()/caseName(layout)/instance()/db_.dbDir()/local();
}
Foam::fileName Foam::IOobject::path
(
const word& instance,
@ -541,6 +562,18 @@ Foam::fileName Foam::IOobject::globalPath
}
Foam::fileName Foam::IOobject::path
(
IOobjectOption::Layout layout,
const word& instance,
const fileName& local
) const
{
// Note: can only be called with relative instance since is word type
return rootPath()/caseName(layout)/instance/db_.dbDir()/local;
}
Foam::fileName Foam::IOobject::objectRelPath() const
{
if (file_isOutsideCase(instance()))

View File

@ -578,6 +578,9 @@ public:
//- Return the Time::globalCaseName()
const fileName& globalCaseName() const noexcept;
//- Return the Time::caseName() - normal or global
const fileName& caseName(IOobjectOption::Layout) const noexcept;
//- Read access to instance path component
inline const fileName& instance() const noexcept;
@ -600,6 +603,9 @@ public:
//- The complete global path for the object (with instance, local,...)
fileName globalPath() const;
//- The complete path (normal or global) for the object
fileName path(IOobjectOption::Layout) const;
//- The complete path with alternative instance and local
fileName path
(
@ -614,12 +620,24 @@ public:
const fileName& local = fileName::null
) const;
//- The complete path (normal or global)
//- with alternative instance and local
fileName path
(
IOobjectOption::Layout,
const word& instance,
const fileName& local = fileName::null
) const;
//- The complete path + object name
inline fileName objectPath() const;
//- The complete global path + object name
inline fileName globalObjectPath() const;
//- The complete path (normal or global) + object name
inline fileName objectPath(IOobjectOption::Layout) const;
//- The object path relative to the root
fileName objectRelPath() const;

View File

@ -329,6 +329,15 @@ inline Foam::fileName Foam::IOobject::globalObjectPath() const
}
inline Foam::fileName Foam::IOobject::objectPath
(
IOobjectOption::Layout layout
) const
{
return path(layout)/name();
}
// Error Handling
inline bool Foam::IOobject::good() const noexcept

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2018 OpenFOAM Foundation
Copyright (C) 2020-2025 OpenCFD Ltd.
Copyright (C) 2020-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -51,8 +51,6 @@ FoamFile
class decomposedBlockData;
location "constant/polyMesh";
object points;
data.format ascii; // optional
data.class vectorField; // optional
}
// processor0
@ -137,15 +135,23 @@ protected:
// Protected Member Functions
//- Read data (on master) and transmit.
//- Helper: determine number of processors whose recvSizes fits
//- into maxBufferSize
static label calcNumProcs
(
const label comm,
const off_t maxBufferSize,
const labelUList& recvSizes,
const label startProci
);
//- Read data into *this. ISstream is only valid on master.
static bool readBlocks
(
const label comm,
// [in] The input stream (only valid on master)
autoPtr<ISstream>& isPtr,
// [out] The processor local data
List<char>& localData,
const UPstream::commsTypes commsType /* unused */
List<char>& contentChars,
const UPstream::commsTypes commsType
);
//- Helper: skip a block of (binary) character data
@ -271,15 +277,14 @@ public:
}
//- Helper: write block of (binary) character content
// Housekeeping
static std::streamoff writeBlockEntry
(
OSstream& os,
const label blocki,
std::string_view sv
const std::string& s
)
{
return writeBlockEntry(os, blocki, sv.data(), sv.size());
return writeBlockEntry(os, blocki, s.data(), s.size());
}
//- Helper: write block of (binary) character data
@ -302,134 +307,61 @@ public:
);
//- Read master header information (into headerIO) and return
//- data in stream.
//- data in stream. Note: isPtr is only valid on master.
static autoPtr<ISstream> readBlocks
(
const label comm,
const fileName& fName,
//! [in] The input stream (only valid on master)
autoPtr<ISstream>& isPtr,
//! [out] header information
IOobject& headerIO,
const UPstream::commsTypes commsType /* unused */
);
//- Helper: gather data from (subset of) sub-ranks.
// In non-blocking mode it sets up send/recv for non-empty content.
// In blocking/scheduled mode it uses MPI_Gatherv to collect data.
//
// Returns:
// - recvData : the received data
// - recvOffsets : offset in data. recvOffsets is nProcs+1
static void gatherProcData
(
const label comm,
const UList<char>& localData, //!< [in] required on all procs
const labelUList& recvSizes, //!< [in] only required on master
const labelRange& whichProcs, //!< [in] required on all procs
List<int>& recvOffsets, //!< [out] only relevant on master
DynamicList<char>& recvData, //!< [out] only relevant on master
const UPstream::commsTypes commsType
);
//- Helper: gather single label. Note: using native Pstream.
// datas sized with num procs but undefined contents on
// slaves
static void gather
(
const label comm,
const label data,
labelList& datas
);
//- Helper: gather data from (subset of) slaves.
//
// Returns:
// - recvData : received data
// - recvOffsets : offset in data. recvOffsets is nProcs+1
static void gatherSlaveData
(
const label comm,
const UList<char>& data,
const labelUList& recvSizes,
const labelRange& fromProcs,
List<int>& recvOffsets,
DynamicList<char>& recvData
);
//- Write *this. Ostream only valid on master.
// Returns offsets of processor blocks in blockOffset
static bool writeBlocks
(
const label comm,
//! [in] output stream (relevant on master)
autoPtr<OSstream>& osPtr,
//! [out] start offsets to each block (relevant on master),
//! ignored if List::null() type
List<std::streamoff>& blockOffset,
const UList<char>& localData, //!< [in] required on all procs
const labelUList& recvSizes, //!< [in] only required on master
const UList<char>& masterData,
//! Optional proc data (only written on master)
//! but \b must also be symmetrically defined (empty/non-empty)
//! on all ranks
const UList<std::string_view>& procData,
const labelUList& recvSizes,
// Optional slave data (on master)
const UPtrList<SubList<char>>& slaveData,
const UPstream::commsTypes commsType,
const bool syncReturnState = true
);
// Housekeeping
//- Write *this. Ostream only valid on master.
// Returns offsets of processor blocks in blockOffset
FOAM_DEPRECATED_FOR(2023-09, "write with std::string_view instead")
static bool writeBlocks
(
const label comm,
autoPtr<OSstream>& osPtr,
List<std::streamoff>& blockOffset,
const UList<char>& localData, // [in] required on all procs
const labelUList& recvSizes, // [in] only required on master
// Optional proc data (only written on master)
// but \b must also be symmetrically defined (empty/non-empty)
// on all ranks
const UPtrList<SubList<char>>& procData,
const UPstream::commsTypes commsType,
const bool syncReturnState = true
)
{
// Transcribe to string_view
List<std::string_view> spans(procData.size());
forAll(procData, proci)
{
const auto* ptr = procData.get(proci);
if (ptr && !ptr->empty())
{
spans[proci] = std::string_view(ptr->cdata(), ptr->size());
}
}
bool ok = decomposedBlockData::writeBlocks
(
comm,
osPtr,
blockOffset,
localData,
recvSizes,
spans,
commsType,
syncReturnState
);
return ok;
}
//- Deprecated(2023-09) - consider UPstream::listGatherValue
// The only difference is that this gather also resizes the output
// on the non-master procs
// \deprecated(2023-09) - consider UPstream::listGatherValue
FOAM_DEPRECATED_FOR(2023-09, "consider UPstream::listGatherValue()")
static void gather
(
const label comm,
const label localValue,
labelList& allValues
)
{
allValues.resize_nocopy(UPstream::nProcs(comm));
UPstream::mpiGather
(
reinterpret_cast<const char*>(&localValue),
allValues.data_bytes(),
sizeof(label), // The send/recv size per rank
comm
);
}
};

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021-2023 OpenCFD Ltd.
Copyright (C) 2021-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -189,9 +189,10 @@ void Foam::decomposedBlockData::writeExtraHeaderContent
dict.set("data.class", io.type());
// Deep-copy of meta-data (if any)
if (const auto* meta = io.findMetaData(); meta && !meta->empty())
const dictionary* metaDataDict = io.findMetaData();
if (metaDataDict && !metaDataDict->empty())
{
dict.add("meta", *meta);
dict.add("meta", *metaDataDict);
}
}
@ -220,16 +221,16 @@ void Foam::decomposedBlockData::writeHeader
io.name()
);
// Same as writeExtraHeaderContent
{
writeHeaderEntry(os, "data.format", streamOptData.format());
writeHeaderEntry(os, "data.class", io.type());
}
// Meta-data (if any)
if (const auto* meta = io.findMetaData(); meta && !meta->empty())
const dictionary* metaDataDict = io.findMetaData();
if (metaDataDict && !metaDataDict->empty())
{
meta->writeEntry("meta", os);
metaDataDict->writeEntry("meta", os);
}
os.endBlock();

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017 OpenFOAM Foundation
Copyright (C) 2020-2025 OpenCFD Ltd.
Copyright (C) 2020-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -29,7 +29,7 @@ License
#include "masterOFstream.H"
#include "OFstream.H"
#include "OSspecific.H"
#include "Pstream.H"
#include "PstreamBuffers.H"
#include "masterUncollatedFileOperation.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -41,9 +41,9 @@ void Foam::masterOFstream::checkWrite
std::streamsize len
)
{
if (!str || !(len > 0))
if (!len)
{
// Can skip everything if there is nothing to write
// Can probably skip all of this if there is nothing to write
return;
}
@ -63,7 +63,9 @@ void Foam::masterOFstream::checkWrite
<< exit(FatalIOError);
}
// Write characters directly to std::ostream
// Use writeRaw() instead of writeQuoted(string,false) to output
// characters directly.
os.writeRaw(str, len);
if (!os.good())
@ -75,29 +77,24 @@ void Foam::masterOFstream::checkWrite
}
void Foam::masterOFstream::checkWrite
(
const fileName& fName,
const std::string& s
)
{
checkWrite(fName, s.data(), s.length());
}
void Foam::masterOFstream::commit()
{
// Take ownership of serialized content
DynamicList<char> charData(OCharStream::release());
if (!UPstream::parRun())
if (UPstream::parRun())
{
// Write (non-empty) data
checkWrite(pathName_, charData);
}
else
{
// Ignore content if not writing
if (!writeOnProc_)
{
charData.clear();
}
List<fileName> filePaths(UPstream::nProcs(comm_));
filePaths[UPstream::myProcNo(comm_)] = pathName_;
Pstream::gatherList(filePaths, UPstream::msgType(), comm_);
// Test for identical output paths
bool uniform =
(
UPstream::master(comm_)
@ -108,136 +105,69 @@ void Foam::masterOFstream::commit()
if (uniform)
{
// Identical file paths - write on master
if (UPstream::master(comm_) && writeOnProc_)
{
checkWrite(pathName_, charData);
checkWrite(pathName_, this->str());
}
this->reset();
return;
}
// Different files
// ---------------
//
// Non-sparse (most ranks have writeOnProc_ == true),
// so gather sizes first and use PEX-like handling,
// with polling for when data becomes available.
//
// Could also consider double buffering + write to reduce
// memory overhead.
PstreamBuffers pBufs(comm_);
// Or int64_t
const label dataSize =
(
(UPstream::is_subrank(comm_) && writeOnProc_)
? charData.size()
: 0
);
if (!UPstream::master(comm_))
{
if (writeOnProc_)
{
// Send buffer to master
string s(this->str());
const labelList recvSizes
(
UPstream::listGatherValues<label>(dataSize, comm_)
);
UOPstream os(UPstream::masterNo(), pBufs);
os.write(s.data(), s.length());
}
this->reset(); // Done with contents
}
pBufs.finishedGathers();
// Receive from these procs
DynamicList<int> recvProcs;
if (UPstream::master(comm_))
{
// Sorted by message size
labelList order(Foam::sortedOrder(recvSizes));
recvProcs.reserve_exact(order.size());
// Want to receive large messages first. Ignore empty slots
forAllReverse(order, i)
{
const label proci = order[i];
// Ignore empty slots
if (recvSizes[proci] > 0)
{
recvProcs.push_back(proci);
}
}
}
// Non-blocking communication
const label startOfRequests = UPstream::nRequests();
// Some unique tag for this read/write grouping (extra precaution)
const int messageTag = (UPstream::msgType() + 256);
if (UPstream::is_subrank(comm_) && dataSize > 0)
{
// Send to content to master
UOPstream::write
(
UPstream::commsTypes::nonBlocking,
UPstream::masterNo(),
charData.cdata_bytes(),
charData.size_bytes(),
messageTag,
comm_
);
}
else if (UPstream::master(comm_))
{
// The receive slots
List<List<char>> recvBuffers(UPstream::nProcs(comm_));
// Receive from these procs (non-empty slots)
for (const int proci : recvProcs)
{
auto& slot = recvBuffers[proci];
slot.resize_nocopy(recvSizes[proci]);
// Receive content
UIPstream::read
(
UPstream::commsTypes::nonBlocking,
proci,
slot.data_bytes(),
slot.size_bytes(),
messageTag,
comm_
);
}
if (writeOnProc_)
{
// Write non-empty master data
checkWrite(pathName_, charData);
charData.clear();
// Write master data
checkWrite(filePaths[UPstream::masterNo()], this->str());
}
this->reset(); // Done with contents
// Poll for completed receive requests and dispatch
DynamicList<int> indices(recvProcs.size());
while
(
UPstream::waitSomeRequests
(
startOfRequests,
recvProcs.size(),
&indices
)
)
// Allocate large enough to read without resizing
List<char> buf(pBufs.maxRecvCount());
for (const int proci : UPstream::subProcs(comm_))
{
for (const int i : indices)
const std::streamsize count(pBufs.recvDataCount(proci));
if (count)
{
const int proci = recvProcs[i];
auto& slot = recvBuffers[proci];
UIPstream is(proci, pBufs);
// Write non-empty sub-proc data
checkWrite(filePaths[proci], slot);
// Eager cleanup
slot.clear();
is.read(buf.data(), count);
checkWrite(filePaths[proci], buf.cdata(), count);
}
}
}
UPstream::waitRequests(startOfRequests);
}
else
{
checkWrite(pathName_, this->str());
this->reset();
}
// This method is only called once (internally)
// so no need to clear/flush old buffered data
}
@ -246,24 +176,21 @@ void Foam::masterOFstream::commit()
Foam::masterOFstream::masterOFstream
(
IOstreamOption::atomicType atomic,
const int communicator,
const label comm,
const fileName& pathName,
IOstreamOption streamOpt,
IOstreamOption::appendType append,
const bool writeOnProc
)
:
OCharStream(streamOpt),
OStringStream(streamOpt),
pathName_(pathName),
atomic_(atomic),
compression_(streamOpt.compression()),
append_(append),
writeOnProc_(writeOnProc),
comm_(communicator < 0 ? UPstream::worldComm : communicator)
{
// Start with a slightly larger buffer
OCharStream::reserve(4*1024);
}
comm_(comm)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017 OpenFOAM Foundation
Copyright (C) 2020-2025 OpenCFD Ltd.
Copyright (C) 2020-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -41,7 +41,7 @@ SourceFiles
#ifndef Foam_masterOFstream_H
#define Foam_masterOFstream_H
#include "SpanStream.H"
#include "StringStream.H"
#include "UPstream.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -55,7 +55,7 @@ namespace Foam
class masterOFstream
:
public OCharStream
public OStringStream
{
// Private Data
@ -80,8 +80,7 @@ class masterOFstream
// Private Member Functions
//- Open file with checking and write append contents.
// A no-op if str is null or len is zero
//- Open file with checking and write append contents
void checkWrite
(
const fileName& fName,
@ -90,16 +89,9 @@ class masterOFstream
);
//- Open file with checking and write append contents
void checkWrite
(
const fileName& fName,
const UList<char>& charData
)
{
checkWrite(fName, charData.cdata(), charData.size_bytes());
}
void checkWrite(const fileName& fName, const std::string& s);
//- Commit buffered information, including communication as required
//- Commit buffered information, including parallel gather as required
void commit();
@ -112,8 +104,7 @@ public:
masterOFstream
(
IOstreamOption::atomicType atomic,
//! The communicator number (-1 == worldComm)
const int communicator,
const label comm,
const fileName& pathname,
IOstreamOption streamOpt = IOstreamOption(),
IOstreamOption::appendType append = IOstreamOption::NO_APPEND,
@ -124,8 +115,7 @@ public:
//- from pathname, stream option, optional append
masterOFstream
(
//! The communicator number (-1 == worldComm)
const int communicator,
const label comm,
const fileName& pathname,
IOstreamOption streamOpt = IOstreamOption(),
IOstreamOption::appendType append = IOstreamOption::NO_APPEND,
@ -135,7 +125,7 @@ public:
masterOFstream
(
IOstreamOption::NON_ATOMIC,
communicator,
comm,
pathname,
streamOpt,
append,

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2011-2016,2024 OpenFOAM Foundation
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -150,8 +150,17 @@ public:
//- Read a string (including enclosing double-quotes)
virtual Istream& read(string&) = 0;
//- Read a label
virtual Istream& read(label&) = 0;
//- Read int32_t
virtual Istream& read(int32_t&) = 0;
//- Read int64_t
virtual Istream& read(int64_t&) = 0;
//- Read uint32_t
virtual Istream& read(uint32_t&) = 0;
//- Read uint64_t
virtual Istream& read(uint64_t&) = 0;
//- Read a float
virtual Istream& read(float&) = 0;

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2011-2016,2024 OpenFOAM Foundation
Copyright (C) 2016-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -154,6 +154,12 @@ public:
//- Write int64_t
virtual Ostream& write(const int64_t val) = 0;
//- Write uint32_t
virtual Ostream& write(const uint32_t val) = 0;
//- Write uint64_t
virtual Ostream& write(const uint64_t val) = 0;
//- Write float
virtual Ostream& write(const float val) = 0;
@ -335,22 +341,6 @@ inline Ostream& operator<<(Ostream& os, std::string_view s)
return os;
}
//- Write operator for character span. Output like string data
inline Ostream& operator<<(Ostream& os, stdFoam::span<char> s)
{
os.writeQuoted(s.data(), s.size(), true); // quoted
os.check("Foam::operator<<(Ostream&, stdFoam::span<char>)");
return os;
}
//- Write operator for const character span. Output like string data
inline Ostream& operator<<(Ostream& os, stdFoam::span<const char> s)
{
os.writeQuoted(s.data(), s.size(), true); // quoted
os.check("Foam::operator<<(Ostream&, stdFoam::span<const char>)");
return os;
}
/*---------------------------------------------------------------------------*\
Manipulators (without arguments)

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2013 OpenFOAM Foundation
Copyright (C) 2011-2013,2024 OpenFOAM Foundation
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -184,8 +184,17 @@ public:
// Read a string
virtual Istream& read(string& str) override;
//- Read a label
virtual Istream& read(label& val) override;
//- Read int32_t
virtual Istream& read(int32_t& val) override;
//- Read int64_t
virtual Istream& read(int64_t& val) override;
//- Read uint32_t
virtual Istream& read(uint32_t& val) override;
//- Read uint64_t
virtual Istream& read(uint64_t& val) override;
//- Read a float
virtual Istream& read(float& val) override;

View File

@ -5,8 +5,8 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2017-2023 OpenCFD Ltd.
Copyright (C) 2011-2015,2024 OpenFOAM Foundation
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -306,9 +306,7 @@ Foam::Istream& Foam::UIPstreamBase::read(token& t)
if (c == token::FLAG)
{
char flagVal;
if (read(flagVal))
if (char flagVal; read(flagVal))
{
processFlags(*this, flagVal);
}
@ -349,8 +347,7 @@ Foam::Istream& Foam::UIPstreamBase::read(token& t)
case token::tokenType::WORD :
case token::tokenType::DIRECTIVE :
{
word val;
if (readString(val))
if (word val; readString(val))
{
if
(
@ -376,8 +373,7 @@ Foam::Istream& Foam::UIPstreamBase::read(token& t)
case token::tokenType::VERBATIM :
case token::tokenType::CHAR_DATA :
{
string val;
if (readString(val))
if (string val; readString(val))
{
t = std::move(val);
t.setType(token::tokenType(c));
@ -389,13 +385,54 @@ Foam::Istream& Foam::UIPstreamBase::read(token& t)
return *this;
}
// Label
case token::tokenType::LABEL :
// (signed) int32
case token::tokenType::INTEGER_32 :
{
label val;
if (read(val))
if (int32_t val; read(val))
{
t = val;
t.int32Token(val);
}
else
{
t.setBad();
}
return *this;
}
// (signed) int64
case token::tokenType::INTEGER_64 :
{
if (int64_t val; read(val))
{
t.int64Token(val);
}
else
{
t.setBad();
}
return *this;
}
// (unsigned) int32
case token::tokenType::UNSIGNED_INTEGER_32 :
{
if (uint32_t val; read(val))
{
t.uint32Token(val);
}
else
{
t.setBad();
}
return *this;
}
// (unsigned) int64
case token::tokenType::UNSIGNED_INTEGER_64 :
{
if (uint64_t val; read(val))
{
t.uint64Token(val);
}
else
{
@ -407,8 +444,7 @@ Foam::Istream& Foam::UIPstreamBase::read(token& t)
// Float
case token::tokenType::FLOAT :
{
float val;
if (read(val))
if (float val; read(val))
{
t = val;
}
@ -422,8 +458,7 @@ Foam::Istream& Foam::UIPstreamBase::read(token& t)
// Double
case token::tokenType::DOUBLE :
{
double val;
if (read(val))
if (double val; read(val))
{
t = val;
}
@ -473,7 +508,28 @@ Foam::Istream& Foam::UIPstreamBase::read(string& str)
}
Foam::Istream& Foam::UIPstreamBase::read(label& val)
Foam::Istream& Foam::UIPstreamBase::read(int32_t& val)
{
readFromBuffer(val);
return *this;
}
Foam::Istream& Foam::UIPstreamBase::read(int64_t& val)
{
readFromBuffer(val);
return *this;
}
Foam::Istream& Foam::UIPstreamBase::read(uint32_t& val)
{
readFromBuffer(val);
return *this;
}
Foam::Istream& Foam::UIPstreamBase::read(uint64_t& val)
{
readFromBuffer(val);
return *this;

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2014 OpenFOAM Foundation
Copyright (C) 2011-2014,2024 OpenFOAM Foundation
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -192,12 +192,18 @@ public:
//- Write string
virtual Ostream& write(const std::string& str) override;
//- Write int32_t as a label
//- Write int32_t
virtual Ostream& write(const int32_t val) override;
//- Write int64_t as a label
//- Write int64_t
virtual Ostream& write(const int64_t val) override;
//- Write uint32_t
virtual Ostream& write(const uint32_t val) override;
//- Write uint64_t
virtual Ostream& write(const uint64_t val) override;
//- Write float
virtual Ostream& write(const float val) override;

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2011-2017,2024 OpenFOAM Foundation
Copyright (C) 2016-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -321,7 +321,7 @@ Foam::Ostream& Foam::UOPstreamBase::write(const std::string& str)
Foam::Ostream& Foam::UOPstreamBase::write(const int32_t val)
{
putChar(token::tokenType::LABEL);
putChar(token::tokenType::INTEGER_32);
writeToBuffer(val);
return *this;
}
@ -329,7 +329,23 @@ Foam::Ostream& Foam::UOPstreamBase::write(const int32_t val)
Foam::Ostream& Foam::UOPstreamBase::write(const int64_t val)
{
putChar(token::tokenType::LABEL);
putChar(token::tokenType::INTEGER_64);
writeToBuffer(val);
return *this;
}
Foam::Ostream& Foam::UOPstreamBase::write(const uint32_t val)
{
putChar(token::tokenType::UNSIGNED_INTEGER_32);
writeToBuffer(val);
return *this;
}
Foam::Ostream& Foam::UOPstreamBase::write(const uint64_t val)
{
putChar(token::tokenType::UNSIGNED_INTEGER_64);
writeToBuffer(val);
return *this;
}

View File

@ -533,6 +533,52 @@ private:
static void freeCommunicatorComponents(const label index);
// Private implementation helpers
//- Test for communicator equality.
// True if they have the same index or address the same ranks
static bool sameProcs_impl(int comm1, int comm2)
{
return
(
(comm1 == comm2) ||
(
// With guard against bad index
(comm1 >= 0 && comm1 <= procIDs_.size())
&& (comm2 >= 0 && comm2 <= procIDs_.size())
&& (procIDs_[comm1] == procIDs_[comm2])
)
);
}
//- Test equality of communicator procs with the given list of ranks
template<typename IntType>
static bool sameProcs_impl
(
int communicator,
const UList<IntType>& procs
)
{
return
(
// With guard against bad index
(communicator >= 0 && communicator <= procIDs_.size())
&& ListOps::equal(procIDs_[communicator], procs)
);
}
//- Test the equality of two lists of ranks
template<typename Type1, typename Type2>
static bool sameProcs_impl
(
const UList<Type1>& procs1,
const UList<Type2>& procs2
)
{
return ListOps::equal(procs1, procs2);
}
protected:
// Protected Member Functions
@ -1061,7 +1107,7 @@ public:
//
// \param pos starting position within the internal list of requests
// \param len length of slice to remove (negative = until the end)
static void removeRequests(const label pos, label len = -1);
static void removeRequests(label pos, label len = -1);
//- Non-blocking comms: free outstanding request.
//- Corresponds to MPI_Request_free()
@ -1085,7 +1131,7 @@ public:
//
// \param pos starting position within the internal list of requests
// \param len length of slice to check (negative = until the end)
static void waitRequests(const label pos, label len = -1);
static void waitRequests(label pos, label len = -1);
//- Wait until all requests have finished.
//- Corresponds to MPI_Waitall()
@ -1103,7 +1149,7 @@ public:
//
// \param pos starting position within the internal list of requests
// \param len length of slice to check (negative = until the end)
static bool waitAnyRequest(const label pos, label len = -1);
static bool waitAnyRequest(label pos, label len = -1);
//- Wait until some requests (from position onwards) have finished.
//- Corresponds to MPI_Waitsome()
@ -1122,7 +1168,7 @@ public:
// when calling within a loop.
static bool waitSomeRequests
(
const label pos,
label pos,
label len = -1,
DynamicList<int>* indices = nullptr
);
@ -1148,7 +1194,7 @@ public:
//- Corresponds to MPI_Waitany()
// Returns -1 if parRun() == false, or the list is empty,
// or if all the requests have already been handled
static label waitAnyRequest(UList<UPstream::Request>& requests);
static int waitAnyRequest(UList<UPstream::Request>& requests);
//- Wait until request i has finished.
//- Corresponds to MPI_Wait()
@ -1162,6 +1208,14 @@ public:
// A no-op if parRun() == false or for a null-request
static void waitRequest(UPstream::Request& req);
//- Is request \p i active (!= MPI_REQUEST_NULL)?
// False if there are no pending requests,
// or if the index is out-of-range (0 to nRequests)
static bool activeRequest(const label i);
//- Is request active (!= MPI_REQUEST_NULL)?
static bool activeRequest(const UPstream::Request& req);
//- Non-blocking comms: has request i finished?
//- Corresponds to MPI_Test()
// A no-op and returns true if parRun() == false,
@ -1185,7 +1239,7 @@ public:
//
// \param pos starting position within the internal list of requests
// \param len length of slice to check (negative = until the end)
static bool finishedRequests(const label pos, label len = -1);
static bool finishedRequests(label pos, label len = -1);
//- Non-blocking comms: have all requests finished?
//- Corresponds to MPI_Testall()
@ -1291,6 +1345,43 @@ public:
}
//- Test for communicator equality.
// True if they have the same index or address the same ranks
static bool sameProcs(int communicator1, int communicator2)
{
return sameProcs_impl(communicator1, communicator2);
}
//- Test equality of communicator procs with the given list of ranks.
//- Includes a guard for the communicator index.
template
<
typename T1,
typename = std::void_t
<std::enable_if_t<std::is_integral_v<T1>>>
>
static bool sameProcs(int communicator, const UList<T1>& procs)
{
return sameProcs_impl(communicator, procs);
}
//- Test the equality of two lists of ranks
template
<
typename T1,
typename T2,
typename = std::void_t
<
std::enable_if_t<std::is_integral_v<T1>>,
std::enable_if_t<std::is_integral_v<T2>>
>
>
static bool sameProcs(const UList<T1>& procs1, const UList<T2>& procs2)
{
return sameProcs_impl(procs1, procs2);
}
// Worlds
//- All worlds
@ -1997,6 +2088,8 @@ public:
// Member Functions
// Access
//- Return raw value
value_type value() const noexcept { return value_; }
@ -2006,6 +2099,9 @@ public:
return reinterpret_cast<const void*>(value_);
}
// Query
//- True if not equal to MPI_COMM_NULL
bool good() const noexcept;
@ -2094,6 +2190,8 @@ public:
// Member Functions
// Access
//- Return raw value
value_type value() const noexcept { return value_; }
@ -2103,23 +2201,37 @@ public:
return reinterpret_cast<const void*>(value_);
}
// Basics
//- True if not equal to MPI_REQUEST_NULL
bool good() const noexcept;
//- Reset to default constructed value (MPI_REQUEST_NULL)
void reset() noexcept;
//- Same as calling UPstream::cancelRequest()
void cancel() { UPstream::cancelRequest(*this); }
//- Same as calling UPstream::freeRequest()
void free() { UPstream::freeRequest(*this); }
//- True if request is active (!= MPI_REQUEST_NULL)
//- Same as good(). Same as calling UPstream::activeRequest()
bool active() const noexcept { return good(); }
//- Same as calling UPstream::finishedRequest()
// Uses MPI_Test()
bool finished() { return UPstream::finishedRequest(*this); }
//- Same as calling UPstream::waitRequest()
//- Same as calling UPstream::waitRequest().
// Uses MPI_Wait()
void wait() { UPstream::waitRequest(*this); }
// Other
//- Same as calling UPstream::cancelRequest().
// Uses MPI_Cancel(), MPI_Request_free()
void cancel() { UPstream::cancelRequest(*this); }
//- Same as calling UPstream::freeRequest().
// Uses MPI_Request_free()
void free() { UPstream::freeRequest(*this); }
};
@ -2138,6 +2250,9 @@ Ostream& operator<<(Ostream&, const UPstream::commsStruct&);
#include "UPstreamTraits.H"
#include "UPstreamWindow.H"
// Locally include the following where required:
// - UPstreamFile.H
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository

View File

@ -343,11 +343,22 @@ void Foam::UPstream::mpiGatherv
}
// Nothing further to do
}
else if constexpr (UPstream_basic_dataType<Type>::value)
else if constexpr (UPstream_dataType<Type>::value)
{
// Restrict to basic (or aliased) MPI types to avoid recalculating
// the list of counts/offsets.
// The sizing factor (constexpr) must be 1 otherwise
// [recvCounts,recvOffsets] are likely incorrect
constexpr std::streamsize count = UPstream_dataType<Type>::size(1);
static_assert
(
(count == 1),
"Code does not (yet) work with aggregate types"
);
UPstream::mpi_gatherv
(
sendData,
@ -356,7 +367,7 @@ void Foam::UPstream::mpiGatherv
recvCounts,
recvOffsets,
UPstream_basic_dataType<Type>::datatype_id,
UPstream_dataType<Type>::datatype_id,
communicator
);
}
@ -364,7 +375,8 @@ void Foam::UPstream::mpiGatherv
{
static_assert
(
stdFoam::dependent_false_v<Type>, "Only basic MPI data types"
stdFoam::dependent_false_v<Type>,
"Only basic and user data types"
);
}
}
@ -392,11 +404,22 @@ void Foam::UPstream::mpiScatterv
}
// Nothing further to do
}
else if constexpr (UPstream_basic_dataType<Type>::value)
else if constexpr (UPstream_dataType<Type>::value)
{
// Restrict to basic (or aliased) MPI types to avoid recalculating
// the list of counts/offsets.
// The sizing factor (constexpr) must be 1 otherwise
// [sendCounts,sendOffsets] are likely incorrect
constexpr std::streamsize count = UPstream_dataType<Type>::size(1);
static_assert
(
(count == 1),
"Code does not (yet) work with aggregate types"
);
UPstream::mpi_scatterv
(
sendData,
@ -405,7 +428,7 @@ void Foam::UPstream::mpiScatterv
recvData,
recvCount,
UPstream_basic_dataType<Type>::datatype_id,
UPstream_dataType<Type>::datatype_id,
communicator
);
}
@ -413,7 +436,8 @@ void Foam::UPstream::mpiScatterv
{
static_assert
(
stdFoam::dependent_false_v<Type>, "Only basic MPI data types"
stdFoam::dependent_false_v<Type>,
"Only basic and user data types"
);
}
}

View File

@ -354,7 +354,7 @@ struct UPstream_basic_dataType
UPstream_alias_dataType<base>::datatype_id;
//- The size in terms of the number of underlying data elements
static std::streamsize size(std::streamsize n) noexcept
static constexpr std::streamsize size(std::streamsize n) noexcept
{
if constexpr (UPstream_alias_dataType<T>::value)
{
@ -373,7 +373,10 @@ struct UPstream_basic_dataType
template<> struct UPstream_basic_dataType<void> : UPstream_mpi_dataType<void>
{
using base = void;
static std::streamsize size(std::streamsize n) noexcept { return n; }
static constexpr std::streamsize size(std::streamsize n) noexcept
{
return n;
}
};
@ -410,7 +413,7 @@ struct UPstream_dataType
UPstream_any_dataType<base>::datatype_id;
//- The size in terms of the number of base data elements
static std::streamsize size(std::streamsize n) noexcept
static constexpr std::streamsize size(std::streamsize n) noexcept
{
if constexpr (UPstream_any_dataType<T>::value)
{

View File

@ -1 +0,0 @@
#warning File removed - left for old dependency check only

View File

@ -1 +0,0 @@
#warning File removed - left for old dependency check only

View File

@ -1 +0,0 @@
#warning File removed - left for old dependency check only

View File

@ -1 +0,0 @@
#warning File removed - left for old dependency check only

View File

@ -1 +0,0 @@
#warning File removed - left for old dependency check only

View File

@ -1 +0,0 @@
#warning File removed - left for old dependency check only

View File

@ -1 +0,0 @@
#warning File removed - left for old dependency check only

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.
@ -714,7 +714,7 @@ Foam::Istream& Foam::ISstream::read(token& t)
case '0' : case '1' : case '2' : case '3' : case '4' :
case '5' : case '6' : case '7' : case '8' : case '9' :
{
label labelVal = (c != '.'); // used as bool here
bool isIntegral = (c != '.'); // possible integral value?
unsigned nChar = 0;
buf[nChar++] = c;
@ -725,7 +725,7 @@ Foam::Istream& Foam::ISstream::read(token& t)
(
is_.get(c)
&& (
isdigit(c)
std::isdigit(c)
|| c == '+'
|| c == '-'
|| c == '.'
@ -734,10 +734,10 @@ Foam::Istream& Foam::ISstream::read(token& t)
)
)
{
if (labelVal)
{
labelVal = isdigit(c);
}
// Silently skip "'" digit separators in numeric literals?
// Still possible as integral?
isIntegral = isIntegral && std::isdigit(c);
buf[nChar++] = c;
if (nChar == bufLen)
@ -766,23 +766,91 @@ Foam::Istream& Foam::ISstream::read(token& t)
{
is_.putback(c);
if (nChar == 1 && buf[0] == '-')
if (nChar == 1)
{
// A single '-' is punctuation
t = token::punctuationToken(token::MINUS);
}
else if (labelVal && Foam::read(buf, labelVal))
{
t = labelVal;
}
else
{
scalar scalarVal;
if (readScalar(buf, scalarVal))
// Special single char handling
switch (buf[0])
{
// A scalar or too big to fit as a label
t = scalarVal;
case '-' : // A single '-' is punctuation
{
t.pToken(token::MINUS);
break;
}
case '.' : // A single '.' is currently bad
{
t.setBad();
break;
}
default :
{
if (isIntegral)
{
// Single digit : conversion is trivial
t.int32Token(buf[0] - '0');
}
else
{
// At the moment nothing to handle here
t.setBad();
}
break;
}
}
return *this;
}
if (isIntegral)
{
// Parse as an integral?
// - read with largest resolution and narrow when possible.
// - retain (signed|unsigned) int32/int64 ...
if (int64_t val; Foam::readInt64(buf, val))
{
// Use smaller representations when possible
if (val >= INT32_MIN && val <= INT32_MAX)
{
t.int32Token(static_cast<int32_t>(val));
}
else if (val >= 0 && val <= int64_t(UINT32_MAX))
{
t.uint32Token(static_cast<uint32_t>(val));
}
else
{
t.int64Token(val);
}
}
else if (uint64_t val; Foam::readUint64(buf, val))
{
// Use smaller representations when possible
if (val <= UINT32_MAX)
{
t.uint32Token(static_cast<uint32_t>(val));
}
else
{
t.uint64Token(val);
}
}
else
{
// Fallthrough to scalar parsing
isIntegral = false;
}
}
// Floating point format or a series of digits that are too
// big to fit an integral representation
//
// - read as 'scalar' (float|double) since this is what the
// rest of the code expects to handle anyhow
if (!isIntegral)
{
if (scalar val; Foam::readScalar(buf, val))
{
t = val;
}
else
{
@ -1007,7 +1075,31 @@ Foam::Istream& Foam::ISstream::read(string& str)
}
Foam::Istream& Foam::ISstream::read(label& val)
Foam::Istream& Foam::ISstream::read(int32_t& val)
{
is_ >> val;
syncState();
return *this;
}
Foam::Istream& Foam::ISstream::read(int64_t& val)
{
is_ >> val;
syncState();
return *this;
}
Foam::Istream& Foam::ISstream::read(uint32_t& val)
{
is_ >> val;
syncState();
return *this;
}
Foam::Istream& Foam::ISstream::read(uint64_t& val)
{
is_ >> val;
syncState();

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2012 OpenFOAM Foundation
Copyright (C) 2011-2012,2024 OpenFOAM Foundation
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -226,8 +226,17 @@ public:
// and an embedded newline character.
virtual Istream& read(string& str) override;
//- Read a label
virtual Istream& read(label& val) override;
//- Read int32_t
virtual Istream& read(int32_t& val) override;
//- Read int64_t
virtual Istream& read(int64_t& val) override;
//- Read uint32_t
virtual Istream& read(uint32_t& val) override;
//- Read uint64_t
virtual Istream& read(uint64_t& val) override;
//- Read a float
virtual Istream& read(float& val) override;

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2011-2016,2024 OpenFOAM Foundation
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -218,6 +218,22 @@ Foam::Ostream& Foam::OSstream::write(const int64_t val)
}
Foam::Ostream& Foam::OSstream::write(const uint32_t val)
{
os_ << val;
syncState();
return *this;
}
Foam::Ostream& Foam::OSstream::write(const uint64_t val)
{
os_ << val;
syncState();
return *this;
}
Foam::Ostream& Foam::OSstream::write(const float val)
{
os_ << val;

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2014 OpenFOAM Foundation
Copyright (C) 2011-2014,2024 OpenFOAM Foundation
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -198,6 +198,12 @@ public:
//- Write int64_t
virtual Ostream& write(const int64_t val) override;
//- Write uint32_t
virtual Ostream& write(const uint32_t val) override;
//- Write uint64_t
virtual Ostream& write(const uint64_t val) override;
//- Write float
virtual Ostream& write(const float val) override;

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2014 OpenFOAM Foundation
Copyright (C) 2011-2014,2024 OpenFOAM Foundation
Copyright (C) 2020-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -140,6 +140,20 @@ Foam::Ostream& Foam::prefixOSstream::write(const int64_t val)
}
Foam::Ostream& Foam::prefixOSstream::write(const uint32_t val)
{
checkWritePrefix();
return OSstream::write(val);
}
Foam::Ostream& Foam::prefixOSstream::write(const uint64_t val)
{
checkWritePrefix();
return OSstream::write(val);
}
Foam::Ostream& Foam::prefixOSstream::write(const float val)
{
checkWritePrefix();

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2014 OpenFOAM Foundation
Copyright (C) 2011-2014,2024 OpenFOAM Foundation
Copyright (C) 2020-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -130,6 +130,12 @@ public:
//- Write int64_t
virtual Ostream& write(const int64_t val) override;
//- Write uint32_t
virtual Ostream& write(const uint32_t val) override;
//- Write uint64_t
virtual Ostream& write(const uint64_t val) override;
//- Write float
virtual Ostream& write(const float val) override;

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2011-2015,2024 OpenFOAM Foundation
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -95,10 +95,12 @@ Foam::tokenList Foam::ITstream::parse_chars
IOstreamOption streamOpt
)
{
ISpanStream is(s, nbytes, streamOpt);
tokenList tokens;
parseStream(is, tokens);
if (s && nbytes > 0) // extra safety
{
ISpanStream is(s, nbytes, streamOpt);
parseStream(is, tokens);
}
return tokens;
}
@ -107,10 +109,19 @@ Foam::tokenList Foam::ITstream::parse_chars
void Foam::ITstream::reset(const char* input, size_t nbytes)
{
ISpanStream is(input, nbytes, static_cast<IOstreamOption>(*this));
tokenList tokens;
if (input && nbytes > 0) // extra safety
{
ISpanStream is(input, nbytes, static_cast<IOstreamOption>(*this));
parseStream(is, static_cast<tokenList&>(*this));
ITstream::seek(0); // rewind() bypassing virtual
parseStream(is, static_cast<tokenList&>(*this));
ITstream::seek(0); // rewind() bypassing virtual
}
else
{
ITstream::seek(0); // rewind() bypassing virtual
tokenList::clear();
}
}
@ -248,7 +259,10 @@ Foam::ITstream::ITstream
:
ITstream(streamOpt, name)
{
reset(input, strlen(input));
if (input)
{
reset(input, strlen(input));
}
}
@ -643,7 +657,28 @@ Foam::Istream& Foam::ITstream::read(string&)
}
Foam::Istream& Foam::ITstream::read(label&)
Foam::Istream& Foam::ITstream::read(int32_t&)
{
NotImplemented;
return *this;
}
Foam::Istream& Foam::ITstream::read(int64_t&)
{
NotImplemented;
return *this;
}
Foam::Istream& Foam::ITstream::read(uint32_t&)
{
NotImplemented;
return *this;
}
Foam::Istream& Foam::ITstream::read(uint64_t&)
{
NotImplemented;
return *this;

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2011-2016,2024 OpenFOAM Foundation
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -77,7 +77,8 @@ class ITstream
// but leave any excess capacity (ie, like reserve).
void reserveCapacity(const label newCapacity);
//- Convert input sequence into a list of tokens,
//- Convert input sequence into a list of tokens.
// Includes nullptr guard
static tokenList parse_chars
(
const char* s,
@ -87,6 +88,7 @@ class ITstream
//- Convert input sequence into a list of tokens,
//- using the existing stream format. Rewinds the stream
// Includes nullptr guard
void reset(const char* input, size_t nbytes);
//- Failsafe read-access to token at specified location
@ -175,32 +177,6 @@ public:
reset(s.data(), s.size());
}
//- Construct token list by parsing the input character sequence
// Uses static parse function internally.
explicit ITstream
(
stdFoam::span<char> s,
IOstreamOption streamOpt = IOstreamOption()
)
:
ITstream(streamOpt)
{
reset(s.data(), s.size());
}
//- Construct token list by parsing the input character sequence
// Uses static parse function internally.
explicit ITstream
(
stdFoam::span<const char> s,
IOstreamOption streamOpt = IOstreamOption()
)
:
ITstream(streamOpt)
{
reset(s.data(), s.size());
}
// Additional constructors
@ -255,17 +231,6 @@ public:
return parse_chars(input.cdata(), input.size(), streamOpt);
}
//- Create token list by parsing the input string
//- until no good tokens remain.
static tokenList parse
(
const std::string& input,
IOstreamOption streamOpt = IOstreamOption()
)
{
return parse_chars(input.data(), input.size(), streamOpt);
}
//- Create token list by parsing the input character sequence
//- until no good tokens remain.
static tokenList parse
@ -274,7 +239,14 @@ public:
IOstreamOption streamOpt = IOstreamOption()
)
{
return parse_chars(input, strlen(input), streamOpt);
if (input)
{
return parse_chars(input, strlen(input), streamOpt);
}
else
{
return tokenList();
}
}
//- Create token list by parsing the input character sequence
@ -288,28 +260,6 @@ public:
return parse_chars(s.data(), s.size(), streamOpt);
}
//- Create token list by parsing the input character sequence
//- until no good tokens remain.
static tokenList parse
(
stdFoam::span<char> s,
IOstreamOption streamOpt = IOstreamOption()
)
{
return parse_chars(s.data(), s.size(), streamOpt);
}
//- Create token list by parsing the input character sequence
//- until no good tokens remain.
static tokenList parse
(
stdFoam::span<const char> s,
IOstreamOption streamOpt = IOstreamOption()
)
{
return parse_chars(s.data(), s.size(), streamOpt);
}
// Member Functions
@ -387,7 +337,7 @@ public:
label& tokenIndex() noexcept { return tokenIndex_; }
//- Set the token index (no checks). \return the previous value
label tokenIndex(const label num) noexcept
label tokenIndex(label num) noexcept
{
label old(tokenIndex_);
tokenIndex_ = num;
@ -509,8 +459,17 @@ public:
//- triggers not implemented error
virtual Istream& read(string&) override;
//- Read a label : triggers not implemented error
virtual Istream& read(label&) override;
//- Read int32_t : triggers not implemented error
virtual Istream& read(int32_t&) override;
//- Read int64_t : triggers not implemented error
virtual Istream& read(int64_t&) override;
//- Read uint32_t : triggers not implemented error
virtual Istream& read(uint32_t&) override;
//- Read uint64_t : triggers not implemented error
virtual Istream& read(uint64_t&) override;
//- Read a float : triggers not implemented error
virtual Istream& read(float&) override;

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.
@ -65,7 +65,7 @@ Foam::Ostream& Foam::OTstream::writeQuoted
if (quoted)
{
// tokenType::STRING
tokens().emplace_back() = string(str, len);
tokens().emplace_back() = Foam::string(str, len);
}
else if (len > 0)
{
@ -120,7 +120,7 @@ Foam::Ostream& Foam::OTstream::write(const std::string& str)
Foam::Ostream& Foam::OTstream::write(const int32_t val)
{
tokens().push_back(token(label(val))); // tokenType::LABEL
tokens().emplace_back().int32Token(val);
return *this;
}
@ -128,24 +128,36 @@ Foam::Ostream& Foam::OTstream::write(const int32_t val)
Foam::Ostream& Foam::OTstream::write(const int64_t val)
{
tokens().push_back(token(label(val))); // tokenType::LABEL
tokens().emplace_back().int64Token(val);
return *this;
}
Foam::Ostream& Foam::OTstream::write(const uint32_t val)
{
tokens().emplace_back().uint32Token(val);
return *this;
}
Foam::Ostream& Foam::OTstream::write(const uint64_t val)
{
tokens().emplace_back().uint64Token(val);
return *this;
}
Foam::Ostream& Foam::OTstream::write(const float val)
{
tokens().push_back(token(val)); // tokenType::FLOAT
tokens().emplace_back().floatToken(val);
return *this;
}
Foam::Ostream& Foam::OTstream::write(const double val)
{
tokens().push_back(token(val)); // tokenType::DOUBLE
tokens().emplace_back().doubleToken(val);
return *this;
}

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