Compare commits

..

1 Commits

Author SHA1 Message Date
7b7229fc13 ENH: integrate memory pool support for List allocations
- provides an optional memory management using a memory pool.
  Currently can support Umpire (https://github.com/LLNL/Umpire)

  When available, its use can be controlled by the FOAM_MEMORY_POOL
  environment variable, or the memory_pool Optimisation switch
  (etc/controlDict).

Notes:

  Use of the memory-pool is controlled by the 'is_aligned_type()' test
  and the minimum field size, controlled by the 'use_memory_pool()' test.

  If the memory-pool is not enabled or not required according to the two
  above tests, the allocation falls back to either an aligned or unaligned
  allocation (depending on the field size).

  The thresholds for aligned, unaligned, memory-pool allocation
  are still a compile-time option. Made by direct edit of the
  corrsponding functions.
2025-05-22 16:22:09 +02:00
257 changed files with 3594 additions and 3213 deletions

View File

@ -1,2 +1,2 @@
api=2502
api=2501
patch=0

View File

@ -13,14 +13,7 @@ volVectorField U
);
// Initialise the velocity internal field to zero
// Note: explicitly bypass evaluation of contraint patch overrides
// (e.g. swirlFanVelocity might lookup phi,rho)
//U = dimensionedVector(U.dimensions(), Zero);
{
const dimensionedVector dt(U.dimensions(), Zero);
U.internalFieldRef() = dt;
U.boundaryFieldRef() = dt.value();
}
U = dimensionedVector(U.dimensions(), Zero);
surfaceScalarField phi
(

View File

@ -51,7 +51,6 @@ See also
#include "IndirectList.H"
#include "SubList.H"
#include "SliceList.H"
#include "SubField.H"
#include "ListPolicy.H"
#include <list>
@ -282,33 +281,6 @@ int main(int argc, char *argv[])
};
Info<< "list4: " << list4 << endl;
{
List<scalar> list4Mag = ListOps::create<scalar>
(
list4,
[](const auto& a){ return a.mag(); }
);
const auto equalMag = [](const auto& a, const auto& b)
{
return (Foam::mag(a) == Foam::mag(b));
};
Info<< "list4 (mag): " << list4Mag << endl;
bool same = ListOps::equal(list4, list4Mag, equalMag);
Info<< "mag(list4) == list4(mag): " << same << nl;
SubField<scalar>(list4Mag) *= -1;
same = ListOps::equal(list4, list4Mag, equalMag);
Info<< "mag(list4) == list4(mag): " << same << nl;
SubField<scalar>(list4Mag) *= 1.1;
same = ListOps::equal(list4, list4Mag, equalMag);
Info<< "mag(list4) == list4(mag): " << same << nl;
}
List<vector> list5
{
{5, 3, 1},

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -131,6 +131,7 @@ int main(int argc, char *argv[])
if (probed.second > 0)
{
// Message found and had size: receive it
const label proci(probed.first);
const label count(probed.second);
@ -163,7 +164,8 @@ int main(int argc, char *argv[])
scalarField fld(is);
Info<< "from [" << proci << "] : " << flatOutput(fld) << endl;
Info<< "from [" << probed.first
<< "] : " << flatOutput(fld) << endl;
}
}

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v2506 |
| \\ / O peration | Version: v2412 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
@ -26,7 +26,7 @@ stopAt writeNow;
endTime 4;
writeControl adjustable;
writeControl adjustableRunTime;
writeInterval 0.1;

View File

@ -1,7 +1,7 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v2506 |
| \\ / O peration | Version: v2412 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
@ -27,7 +27,7 @@ endTime 0.1;
deltaT 0.0001;
writeControl adjustable;
writeControl adjustableRunTime;
writeInterval 0.01;

View File

@ -525,7 +525,6 @@ public:
}
}
};
class edgePointTransformOp
{
public:
@ -544,24 +543,25 @@ public:
points1[i] = fld[i].second();
}
pointField points0New;
pointField points1New;
if (forward)
{
vt.transformPositionList(points0);
vt.transformPositionList(points1);
points0New = vt.transformPosition(points0);
points1New = vt.transformPosition(points1);
}
else
{
vt.invTransformPositionList(points0);
vt.invTransformPositionList(points1);
points0New = vt.invTransformPosition(points0);
points1New = vt.invTransformPosition(points1);
}
forAll(fld, i)
{
fld[i] = PointPair(points0[i], points1[i]);
fld[i] = PointPair(points0New[i], points1New[i]);
}
}
};
class edgePointFlipOp
{
public:
@ -572,7 +572,6 @@ public:
return newVal;
}
};
void testEdgeFlip2(const polyMesh& mesh, Random& rndGen)
{
Info<< nl << "Testing edge-wise (oriented) data synchronisation." << endl;
@ -760,11 +759,13 @@ class pointListOps
{
public:
void operator()(UList<point>& lhs, const UList<point>& rhs) const
void operator()(pointList& lhs, const pointList& rhs) const
{
forAll(lhs, i)
{
maxMagSqrEqOp<vector>()(lhs[i], rhs[i]);
point& l = lhs[i];
const point& r = rhs[i];
maxMagSqrEqOp<vector>()(l, r);
}
}
@ -772,31 +773,38 @@ public:
(
const vectorTensorTransform& vt,
const bool forward,
UList<pointList>& fld
List<pointList>& fld
) const
{
if (forward)
{
for (auto& pts : fld)
for (auto& elems : fld)
{
vt.transformPositionList(pts);
for (auto& elem : elems)
{
elem = vt.transformPosition(elem);
}
}
}
else
{
for (auto& pts : fld)
for (auto& elems : fld)
{
vt.invTransformPositionList(pts);
for (auto& elem : elems)
{
elem = vt.invTransformPosition(elem);
}
}
}
}
//- Transform patch-based field
void operator()(const coupledPolyPatch& cpp, UList<pointList>& fld) const
void operator()(const coupledPolyPatch& cpp, List<pointList>& fld) const
{
forAll(fld, facei)
{
for (auto& pt : fld[facei])
pointList& pts = fld[facei];
for (auto& pt : pts)
{
cpp.transformPosition(pt, facei);
}

View File

@ -39,7 +39,8 @@ Foam::label Foam::findOppositeWedge
&& isA<wedgePolyPatch>(patches[patchi])
)
{
const auto& pp = refCast<const wedgePolyPatch>(patches[patchi]);
const wedgePolyPatch& pp =
refCast<const wedgePolyPatch>(patches[patchi]);
// Calculate (cos of) angle to wpp (not pp!) centre normal
scalar ppCosAngle = wpp.centreNormal() & pp.n();
@ -79,7 +80,8 @@ bool Foam::checkWedges
{
if (patches[patchi].size() && isA<wedgePolyPatch>(patches[patchi]))
{
const auto& pp = refCast<const wedgePolyPatch>(patches[patchi]);
const wedgePolyPatch& pp =
refCast<const wedgePolyPatch>(patches[patchi]);
scalar wedgeAngle = acos(pp.cosAngle());
@ -103,7 +105,7 @@ bool Foam::checkWedges
return true;
}
const auto& opp =
const wedgePolyPatch& opp =
refCast<const wedgePolyPatch>(patches[oppositePatchi]);
@ -273,27 +275,25 @@ namespace Foam
void operator()
(
const coupledPolyPatch& cpp,
UList<pointField>& pts
List<pointField>& pts
) const
{
// Each element of pts is all the points in the face.
// Convert into lists of size cpp to transform.
// Each element of pts is all the points in the face. Convert into
// lists of size cpp to transform.
List<pointField> newPts(pts.size());
forAll(pts, facei)
{
newPts[facei].resize(pts[facei].size());
newPts[facei].setSize(pts[facei].size());
}
pointField ptsAtIndex(pts.size());
label index = 0;
while (true)
{
label n = 0;
// Extract for every face the i'th position
ptsAtIndex = Zero;
pointField ptsAtIndex(pts.size(), Zero);
forAll(cpp, facei)
{
const pointField& facePts = pts[facei];
@ -326,8 +326,7 @@ namespace Foam
index++;
}
// Transfer newPts -> pts
std::move(newPts.begin(), newPts.end(), pts.begin());
pts.transfer(newPts);
}
};
}
@ -353,7 +352,10 @@ bool Foam::checkCoupledPoints
{
if (patches[patchi].coupled())
{
const auto& cpp = refCast<const coupledPolyPatch>(patches[patchi]);
const coupledPolyPatch& cpp = refCast<const coupledPolyPatch>
(
patches[patchi]
);
forAll(cpp, i)
{
@ -385,7 +387,8 @@ bool Foam::checkCoupledPoints
{
if (patches[patchi].coupled())
{
const auto& cpp = refCast<const coupledPolyPatch>(patches[patchi]);
const coupledPolyPatch& cpp =
refCast<const coupledPolyPatch>(patches[patchi]);
if (cpp.owner())
{
@ -1020,7 +1023,7 @@ Foam::label Foam::checkGeometry
{
if (isA<cyclicAMIPolyPatch>(pbm[patchi]))
{
const auto& cpp =
const cyclicAMIPolyPatch& cpp =
refCast<const cyclicAMIPolyPatch>(pbm[patchi]);
if (cpp.owner())
@ -1055,7 +1058,7 @@ Foam::label Foam::checkGeometry
if (isA<cyclicACMIPolyPatch>(pbm[patchi]))
{
const auto& pp =
const cyclicACMIPolyPatch& pp =
refCast<const cyclicACMIPolyPatch>(pbm[patchi]);
scalarField mergedMask;
@ -1105,9 +1108,8 @@ Foam::label Foam::checkGeometry
if (isA<cyclicACMIPolyPatch>(pbm[patchi]))
{
const auto& pp =
const cyclicACMIPolyPatch& pp =
refCast<const cyclicACMIPolyPatch>(pbm[patchi]);
scalarField mergedMask;
globalFaces().gather
(

View File

@ -210,7 +210,6 @@ autoPtr<labelIOList> faProcAddressing
// Return cached or read proc addressing from facesInstance
FOAM_NO_DANGLING_REFERENCE
const labelIOList& procAddressing
(
const PtrList<fvMesh>& procMeshList,

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021-2025 OpenCFD Ltd.
Copyright (C) 2021-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
@ -44,10 +44,10 @@ forAll(meshes, regioni)
IOobjectOption::NO_REGISTER
);
if (fieldSelector)
if (fieldSelector && !fieldSelector().empty())
{
objects.filterObjects(fieldSelector);
faObjects.filterObjects(fieldSelector);
objects.filterObjects(fieldSelector());
faObjects.filterObjects(fieldSelector());
}
// Remove "*_0" restart fields

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016-2025 OpenCFD Ltd.
Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -406,27 +406,34 @@ int main(int argc, char *argv[])
// Field selection/deselection
wordRes includedFields, excludedFields;
autoPtr<wordRes::filter> fieldSelector(nullptr);
const bool doConvertFields = !args.found("no-fields");
if (doConvertFields)
{
bool resetFilter = false;
if (args.readListIfPresent<wordRe>("fields", includedFields))
{
resetFilter = true;
Info<< "Including fields "
<< flatOutput(includedFields) << nl << endl;
}
if (args.readListIfPresent<wordRe>("exclude-fields", excludedFields))
{
resetFilter = true;
Info<< "Excluding fields "
<< flatOutput(excludedFields) << nl << endl;
}
if (resetFilter)
{
fieldSelector =
autoPtr<wordRes::filter>::New(includedFields, excludedFields);
}
}
else
else if (doConvertFields)
{
Info<< "Field conversion disabled with the '-no-fields' option" << nl;
}
const wordRes::filter fieldSelector(includedFields, excludedFields);
// ------------------------------------------------------------------------
#include "createTime.H"

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018-2025 OpenCFD Ltd.
Copyright (C) 2018-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
@ -136,7 +136,7 @@ Description
labelList patchIds;
if (doBoundary)
{
patchIds = patchSelector.indices(patches);
patchIds = getSelectedPatches(patches, patchSelector);
}
if (oneBoundary && patchIds.size())

View File

@ -166,54 +166,56 @@ Note
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
labelList getSelectedPatches
(
const polyBoundaryMesh& patches,
const autoPtr<wordRes::filter>& patchSelector
)
{
labelList indices;
// Simple wrapper for polyBoundaryMesh::indices() with some additional logic
struct polyBoundaryPatchSelector
{
wordRes allow_;
wordRes deny_;
void clear()
if (patchSelector && !patchSelector().empty())
{
allow_.clear();
deny_.clear();
// Name-based selection
indices =
(
stringListOps::findMatching
(
patches,
patchSelector(),
nameOp<polyPatch>()
)
);
}
else
{
indices = identity(patches.size());
}
//- Forward to polyBoundaryMesh::indices() with additional handling.
// Prune emptyPolyPatch (always) and processorPolyPatch (in parallel)
labelList indices(const polyBoundaryMesh& pbm) const
// Remove undesirable patches
label count = 0;
for (const label patchi : indices)
{
labelList ids = pbm.indices(allow_, deny_);
const polyPatch& pp = patches[patchi];
const bool excludeProcPatches = UPstream::parRun();
// Prune undesirable patches
label count = 0;
for (const label patchi : ids)
if (isType<emptyPolyPatch>(pp))
{
const auto& pp = pbm[patchi];
if (isType<emptyPolyPatch>(pp))
{
continue;
}
else if (excludeProcPatches && bool(isA<processorPolyPatch>(pp)))
{
break; // No processor patches for parallel output
}
ids[count] = patchi;
++count;
continue;
}
else if (UPstream::parRun() && bool(isA<processorPolyPatch>(pp)))
{
break; // No processor patches for parallel output
}
ids.resize(count);
return ids;
indices[count] = patchi;
++count;
}
};
} // End namespace Foam
indices.resize(count);
return indices;
}
//
@ -550,38 +552,45 @@ int main(int argc, char *argv[])
}
// Patch selection/deselection
polyBoundaryPatchSelector patchSelector;
wordRes includedPatches, excludedPatches;
autoPtr<wordRes::filter> patchSelector(nullptr);
if (doBoundary)
{
if
(
auto& slot = patchSelector.allow_;
args.readListIfPresent<wordRe>("patches", slot)
)
bool resetFilter = false;
if (args.readListIfPresent<wordRe>("patches", includedPatches))
{
Info<< "Including patches " << flatOutput(slot) << nl << endl;
resetFilter = true;
Info<< "Including patches "
<< flatOutput(includedPatches) << nl << endl;
}
if
(
auto& slot = patchSelector.deny_;
args.readListIfPresent<wordRe>("exclude-patches", slot)
)
if (args.readListIfPresent<wordRe>("exclude-patches", excludedPatches))
{
Info<< "Excluding patches " << flatOutput(slot) << nl << endl;
resetFilter = true;
Info<< "Excluding patches "
<< flatOutput(excludedPatches) << nl << endl;
}
if (resetFilter)
{
patchSelector =
autoPtr<wordRes::filter>::New(includedPatches, excludedPatches);
}
}
// Field selection/deselection
wordRes includedFields, excludedFields;
autoPtr<wordRes::filter> fieldSelector(nullptr);
bool doConvertFields = !args.found("no-fields");
if (doConvertFields)
{
bool resetFilter = false;
if (args.readListIfPresent<wordRe>("fields", includedFields))
{
Info<< "Including fields "
<< flatOutput(includedFields) << nl << endl;
resetFilter = !includedFields.empty();
if (includedFields.empty())
{
// Compat: Can be specified as empty (ie, no fields)
@ -594,22 +603,22 @@ int main(int argc, char *argv[])
}
if (args.readListIfPresent<wordRe>("exclude-fields", excludedFields))
{
resetFilter = true;
Info<< "Excluding fields "
<< flatOutput(excludedFields) << nl << endl;
}
if (!doConvertFields)
if (resetFilter && doConvertFields)
{
includedFields.clear();
excludedFields.clear();
fieldSelector =
autoPtr<wordRes::filter>::New(includedFields, excludedFields);
}
}
else
else if (doConvertFields)
{
Info<< "Field conversion disabled with the '-no-fields' option" << nl;
}
const wordRes::filter fieldSelector(includedFields, excludedFields);
// Non-mandatory
const wordRes selectedFaceZones(args.getList<wordRe>("faceZones", false));
@ -790,10 +799,10 @@ int main(int argc, char *argv[])
IOobjectOption::NO_REGISTER
);
if (fieldSelector)
if (fieldSelector && !fieldSelector().empty())
{
objects.filterObjects(fieldSelector);
faObjects.filterObjects(fieldSelector);
objects.filterObjects(fieldSelector());
faObjects.filterObjects(fieldSelector());
}
// Remove "*_0" restart fields

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2018-2025 OpenCFD Ltd.
Copyright (C) 2018-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -39,23 +39,74 @@ namespace Foam
{
template<class Type>
void evaluateConstraintTypes
(
GeometricField<Type, fvPatchField, volMesh>& fld
)
void evaluateConstraintTypes(GeometricField<Type, fvPatchField, volMesh>& fld)
{
fld.boundaryFieldRef().evaluate_if
auto& bfld = fld.boundaryFieldRef();
const UPstream::commsTypes commsType = UPstream::defaultCommsType;
if
(
[](const auto& pfld) -> bool
commsType == UPstream::commsTypes::buffered
|| commsType == UPstream::commsTypes::nonBlocking
)
{
const label startOfRequests = UPstream::nRequests();
for (auto& pfld : bfld)
{
return
if
(
pfld.type() == pfld.patch().patch().type()
&& polyPatch::constraintType(pfld.patch().patch().type())
);
},
UPstream::defaultCommsType
);
)
{
pfld.initEvaluate(commsType);
}
}
// Wait for outstanding requests (non-blocking)
UPstream::waitRequests(startOfRequests);
for (auto& pfld : bfld)
{
if
(
pfld.type() == pfld.patch().patch().type()
&& polyPatch::constraintType(pfld.patch().patch().type())
)
{
pfld.evaluate(commsType);
}
}
}
else if (commsType == UPstream::commsTypes::scheduled)
{
const lduSchedule& patchSchedule =
fld.mesh().globalData().patchSchedule();
for (const auto& schedEval : patchSchedule)
{
const label patchi = schedEval.patch;
auto& pfld = bfld[patchi];
if
(
pfld.type() == pfld.patch().patch().type()
&& polyPatch::constraintType(pfld.patch().patch().type())
)
{
if (schedEval.init)
{
pfld.initEvaluate(commsType);
}
else
{
pfld.evaluate(commsType);
}
}
}
}
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2025 OpenCFD Ltd.
Copyright (C) 2017-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -155,39 +155,50 @@ void writeOBJ
}
}
// Simple wrapper for polyBoundaryMesh::indices() with some additional logic
// - prune emptyPolyPatch (always) and (maybe) processorPolyPatch
labelList getSelectedPatches
(
const polyBoundaryMesh& pbm,
const polyBoundaryMesh& patches,
const wordRes& allow,
const wordRes& deny,
const bool excludeProcPatches
const wordRes& deny
)
{
labelList ids = pbm.indices(allow, deny);
// Name-based selection
labelList indices
(
stringListOps::findMatching
(
patches,
allow,
deny,
nameOp<polyPatch>()
)
);
// Remove undesirable patches
label count = 0;
for (const label patchi : ids)
for (const label patchi : indices)
{
const polyPatch& pp = pbm[patchi];
const polyPatch& pp = patches[patchi];
if (isType<emptyPolyPatch>(pp))
{
continue;
}
else if (excludeProcPatches && bool(isA<processorPolyPatch>(pp)))
else if (Pstream::parRun() && bool(isA<processorPolyPatch>(pp)))
{
break; // No processor patches for parallel output
break; // No processor patches for parallel output
}
ids[count] = patchi;
indices[count] = patchi;
++count;
}
ids.resize(count);
return ids;
indices.resize(count);
return indices;
}
@ -657,14 +668,11 @@ int main(int argc, char *argv[])
const labelList patchIds =
(
getSelectedPatches
(
bMesh,
includePatches,
excludePatches,
// No processor patches? (parallel output or excluded)
(UPstream::parRun() || !includeProcPatches)
)
(includePatches.size() || excludePatches.size())
? getSelectedPatches(bMesh, includePatches, excludePatches)
: includeProcPatches
? identity(bMesh.size())
: identity(bMesh.nNonProcessor())
);
labelList faceZoneIds;

View File

@ -132,6 +132,11 @@ projectDir="$HOME/OpenFOAM/OpenFOAM-$WM_PROJECT_VERSION"
# projectDir="@PROJECT_DIR@"
: # Safety statement (if the user removed all fallback values)
# [FOAM_MEMORY_POOL] - Optional memory management
# - overrides the 'memory_pool' etc/controlDict entry
# = "true | false | host [size=nn] [incr=nn]"
#export FOAM_MEMORY_POOL="host"
# [FOAM_SIGFPE] - Trap floating-point exceptions.
# - overrides the 'trapFpe' controlDict entry
# = true | false

View File

@ -221,6 +221,9 @@ OptimisationSwitches
// Other
// =====
// Optional memory management (sizing in MB)
// memory_pool "host; size=1024; incr=5"
// Trap floating point exception.
// Can override with FOAM_SIGFPE env variable (true|false)
trapFpe 1;

View File

@ -134,6 +134,11 @@ set projectDir=`lsof +p $$ |& sed -ne 's#^[^/]*##;\@/'"$projectName"'[^/]*/etc/c
# Or optionally hard-coded (eg, with autoconfig)
# set projectDir="@PROJECT_DIR@"
# [FOAM_MEMORY_POOL] - Optional memory management
# - overrides the 'memory_pool' etc/controlDict entry
# = "true | false | host [size=nn] [incr=nn]"
#setenv FOAM_MEMORY_POOL "host"
# [FOAM_SIGFPE] - Trap floating-point exceptions.
# - overrides the 'trapFpe' controlDict entry
# = true | false

View File

@ -3,6 +3,8 @@ MSwindows.C
cpuInfo/cpuInfo.C
memInfo/memInfo.C
memory/MemoryPool.cxx
signals/sigFpe.cxx
signals/sigInt.cxx
signals/sigQuit.cxx

View File

@ -0,0 +1,83 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "MemoryPool.H"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
// bool Foam::MemoryPool::create(const std::string& ctrl, bool verbose)
// {
// return false;
// }
bool Foam::MemoryPool::create(bool verbose)
{
// No banner information since it is currently never an option
return false;
}
void Foam::MemoryPool::destroy(bool verbose)
{}
bool Foam::MemoryPool::active() noexcept
{
return false;
}
bool Foam::MemoryPool::suspend() noexcept
{
return false;
}
void Foam::MemoryPool::resume() noexcept
{}
bool Foam::MemoryPool::is_pool(void* ptr)
{
return false;
}
void* Foam::MemoryPool::try_allocate(std::size_t nbytes)
{
return nullptr;
}
bool Foam::MemoryPool::try_deallocate(void* ptr)
{
return (!ptr);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -2,6 +2,7 @@
cd "${0%/*}" || exit # Run from this directory
targetType=libo # Preferred library type
. ${WM_PROJECT_DIR:?}/wmake/scripts/AllwmakeParseArguments $*
. ${WM_PROJECT_DIR:?}/wmake/scripts/have_umpire
#------------------------------------------------------------------------------
# Hack for MacOS (with Gcc).
@ -59,6 +60,47 @@ then
export COMP_FLAGS="-DFOAM_USE_INOTIFY"
fi
#------------------------------------------------------------------------------
# Have -lumpire, but also -lcamp etc.
# Also need to follow the link order
get_umpire_libs()
{
if [ -d "${UMPIRE_LIB_DIR}" ]
then
set -- $(
# Expected link order
for name in umpire fmt camp
do
[ -f "$UMPIRE_LIB_DIR/lib${name}.a" ] && echo "-l$name"
done
)
echo "$@"
else
echo
fi
}
if have_umpire
then
libNames="$(get_umpire_libs)"
if [ -n "$libNames" ]
then
echo " found umpire -- enabling memory pool interface" 1>&2
echo " umpire libs: $libNames" 1>&2
COMP_FLAGS="$COMP_FLAGS -DFOAM_USE_UMPIRE -I${UMPIRE_INC_DIR}"
LINK_FLAGS="$LINK_FLAGS -L${UMPIRE_LIB_DIR} $libNames"
export COMP_FLAGS LINK_FLAGS
else
echo " expecting umpire, but did not resolve the libraries" 1>&2
fi
fi
#------------------------------------------------------------------------------
# Make object (non-shared by default)
# Never want/need openmp, especially for static objects
wmake -no-openmp $targetType

View File

@ -4,6 +4,8 @@ cpuInfo/cpuInfo.C
cpuTime/cpuTimePosix.C
memInfo/memInfo.C
memory/MemoryPool.cxx
signals/sigFpe.cxx
signals/sigSegv.cxx
signals/sigInt.cxx

View File

@ -1 +1,4 @@
EXE_INC = $(COMP_FLAGS)
/* umpire uses old-style cast etc */
EXE_INC = $(COMP_FLAGS) $(c++LESSWARN)
LIBO_LIBS = $(LINK_FLAGS)

View File

@ -0,0 +1,510 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "MemoryPool.H"
#include "debug.H"
#include "dictionary.H"
#include "sigFpe.H"
#include "OSspecific.H" // For getEnv
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
#ifdef FOAM_USE_UMPIRE
// #include <cerrno>
#include <cinttypes>
#include <tuple>
#include "umpire/Allocator.hpp"
#include "umpire/ResourceManager.hpp"
#include "umpire/strategy/AlignedAllocator.hpp"
#include "umpire/strategy/DynamicPoolList.hpp"
static bool disabled_(false);
static umpire::Allocator aligned_allocator;
static umpire::Allocator pooled_allocator;
static umpire::ResourceManager* manager_(nullptr);
static umpire::ResourceManager* suspended_(nullptr);
#endif
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
#ifdef FOAM_USE_UMPIRE
namespace
{
// Different supported allocation types
enum class Types { undefined, none, host, device, managed };
typedef std::tuple<Types, std::size_t, std::size_t> ctrlTuple;
// Extract key=INT, the key includes the '='
int getIntParameter(const std::string& key, const std::string& ctrl)
{
int val(0);
const auto pos = ctrl.find(key);
if (pos == std::string::npos)
{
return val;
}
const char* buf = (ctrl.data() + pos + key.size());
char *endptr = nullptr;
errno = 0;
auto parsed = std::strtoimax(buf, &endptr, 10);
if (errno || endptr == buf)
{
// Some type of error OR no conversion
}
else
{
val = int(parsed);
}
return val;
}
ctrlTuple getControlValues(const std::string& ctrl)
{
ctrlTuple result(Types::undefined, 0, 0);
bool checkParam = false;
// Also find things that look like Switch constants.
// Unfortunately need to do this manually since Switch::find()
// itself would not manage to parse something like "true; size=10"
if (ctrl.empty())
{
// Nothing => undefined
}
else if
(
std::string::npos != ctrl.find("false") // ctrl.contains("false")
|| std::string::npos != ctrl.find("off") // ctrl.contains("off")
|| std::string::npos != ctrl.find("no") // ctrl.contains("no")
|| std::string::npos != ctrl.find("none") // ctrl.contains("none")
)
{
std::get<0>(result) = Types::none;
}
else if
(
std::string::npos != ctrl.find("true") // ctrl.contains("true")
|| std::string::npos != ctrl.find("on") // ctrl.contains("on")
|| std::string::npos != ctrl.find("yes") // ctrl.contains("yes")
|| std::string::npos != ctrl.find("host") // ctrl.contains("host")
|| std::string::npos != ctrl.find("system") // ctrl.contains("system")
)
{
std::get<0>(result) = Types::host;
checkParam = true;
}
// These need more testing
else if
(
std::string::npos != ctrl.find("device") // ctrl.contains("device")
)
{
std::get<0>(result) = Types::device;
checkParam = true;
}
else if
(
std::string::npos != ctrl.find("managed") // ctrl.contains("managed")
)
{
std::get<0>(result) = Types::managed;
checkParam = true;
}
if (checkParam)
{
std::get<1>(result) = getIntParameter("size=", ctrl);
std::get<2>(result) = getIntParameter("incr=", ctrl);
}
return result;
}
bool create_from(const ctrlTuple& controls, bool verbose)
{
using namespace Foam;
if (manager_ || suspended_)
{
// Already created
return true;
}
// Type, initial size, increment
auto [which, size, incr] = controls;
// std::cerr
// << "which=" << int(which)
// << ", size=" << int(size)
// << ", incr=" << int(incr) << '\n';
constexpr size_t MegaByte(1024*1024);
switch (which)
{
case Types::undefined :
{
if (verbose)
{
Info<< "memory pool : unused" << nl;
}
break;
}
case Types::none :
{
if (verbose)
{
Info<< "memory pool : disabled" << nl;
}
break;
}
case Types::host :
{
// Default sizing parameters
if (!size) size = 1024;
if (!incr) incr = 5;
auto& rm = umpire::ResourceManager::getInstance();
manager_ = &rm;
aligned_allocator =
rm.makeAllocator<umpire::strategy::AlignedAllocator>
(
"aligned_allocator",
rm.getAllocator("HOST"),
// alignment
256
);
pooled_allocator =
rm.makeAllocator<umpire::strategy::DynamicPoolList>
(
"openfoam_HOST_pool",
aligned_allocator,
// initial block allocation size
(size*MegaByte),
// incremental block allocation size
(incr*MegaByte)
);
if (verbose)
{
Info<< "memory pool : host (size="
<< int(size) << "MB, incr="
<< int(incr) << "MB)\n";
}
break;
}
case Types::device :
{
auto& rm = umpire::ResourceManager::getInstance();
manager_ = &rm;
aligned_allocator = rm.getAllocator("DEVICE");
pooled_allocator =
rm.makeAllocator<umpire::strategy::DynamicPoolList>
(
"openfoam_DEVICE_pool",
aligned_allocator
);
if (verbose)
{
Info<< "memory pool : device" << nl;
}
break;
}
case Types::managed :
{
// Default sizing parameters
if (!size) size = 10*1024;
if (!incr) incr = 10;
auto& rm = umpire::ResourceManager::getInstance();
manager_ = &rm;
aligned_allocator = rm.getAllocator("UM");
pooled_allocator =
rm.makeAllocator<umpire::strategy::DynamicPoolList>
(
"openfoam_UM_pool",
aligned_allocator,
// initial block allocation size
(size*MegaByte),
// incremental block allocation size
(incr*MegaByte)
);
if (verbose)
{
Info<< "memory pool : managed (size="
<< int(size) << "MB, incr="
<< int(incr) << "MB)\n";
}
break;
}
}
return (which != Types::undefined && which != Types::none);
}
} // End anonymous namespace
#endif // FOAM_USE_UMPIRE
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
// bool Foam::MemoryPool::create(const std::string& ctrl, bool verbose)
// {
// #ifdef FOAM_USE_UMPIRE
// if (manager_ || suspended_)
// {
// // Already created
// return true;
// }
//
// auto controls = getControlValues(ctrl);
//
// return create_from(controls, verbose);
// #else
// return false;
// #endif
// }
bool Foam::MemoryPool::create(bool verbose)
{
#ifdef FOAM_USE_UMPIRE
if (disabled_)
{
// Disallowed
return false;
}
else if (manager_ || suspended_)
{
// Already created
return true;
}
// First check environment
auto controls = getControlValues(Foam::getEnv("FOAM_MEMORY_POOL"));
if (std::get<0>(controls) == Types::none)
{
// Disabled from environment - has highest priority
disabled_ = true;
}
// Currently no easy way to handle <system>/controlDict...
// Fallback from etc/controlDict
if (std::get<0>(controls) == Types::undefined)
{
// From central etc/controlDict
const auto& dict = Foam::debug::optimisationSwitches();
if (auto* eptr = dict.findStream("memory_pool", keyType::LITERAL))
{
const token& firstToken = eptr->front();
if (firstToken.isStringType())
{
controls = getControlValues(firstToken.stringToken());
}
}
}
return create_from(controls, verbose);
#else
if (verbose)
{
Info<< "memory pool : not available" << nl;
}
return false;
#endif
}
void Foam::MemoryPool::destroy(bool verbose)
{
// Nothing currently needed but could add in something like this:
// if (manager_ || suspended_)
// {
// pooled_allocator.release();
// }
// However, need to find the proper sequence within
// Foam::exit() or UPstream::exit() ...
}
bool Foam::MemoryPool::active() noexcept
{
#ifdef FOAM_USE_UMPIRE
return bool(manager_);
#else
return false;
#endif
}
bool Foam::MemoryPool::suspend() noexcept
{
#ifdef FOAM_USE_UMPIRE
bool status(suspended_);
if (manager_) // <- and (!suspended_)
{
std::swap(manager_, suspended_);
}
return status;
#else
return false;
#endif
}
void Foam::MemoryPool::resume() noexcept
{
#ifdef FOAM_USE_UMPIRE
if (suspended_) // <- and (!manager_)
{
std::swap(manager_, suspended_);
}
#endif
}
bool Foam::MemoryPool::is_pool(void* ptr)
{
#ifdef FOAM_USE_UMPIRE
if (ptr)
{
if (manager_)
{
return manager_->hasAllocator(ptr);
}
else if (suspended_)
{
return suspended_->hasAllocator(ptr);
}
}
#endif
return false;
}
void* Foam::MemoryPool::try_allocate(std::size_t nbytes)
{
void* ptr = nullptr;
#ifdef FOAM_USE_UMPIRE
if (manager_)
{
ptr = pooled_allocator.allocate(nbytes);
// std::cerr<< "allocate(" << int(nbytes) << ")\n";
// Optionally fill with NaN (depends on current flags)
Foam::sigFpe::fillNan_if(ptr, nbytes);
if (!ptr)
{
// Pout<< "umpire failed to allocate memory\n";
}
}
#endif
return ptr;
}
bool Foam::MemoryPool::try_deallocate(void* ptr)
{
#ifdef FOAM_USE_UMPIRE
if (ptr)
{
if (manager_)
{
if (manager_->hasAllocator(ptr)) // <- ie, is_pool()
{
// std::cerr<< "deallocate()\n";
manager_->deallocate(ptr);
return true;
}
}
else if (suspended_)
{
// Deallocate even if nominally suspended
if (suspended_->hasAllocator(ptr)) // <- ie, is_pool()
{
// std::cerr<< "deallocate()\n";
suspended_->deallocate(ptr);
return true;
}
}
}
#endif
return (!ptr);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -587,7 +587,7 @@ meshes/Identifiers/surface/geometricSurfacePatch.C
meshes/Identifiers/surface/surfZoneIdentifier.C
meshes/Identifiers/zone/zoneIdentifier.C
meshes/MeshObject/meshObject.cxx
meshes/MeshObject/meshObject.C
polyMesh = meshes/polyMesh

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2018-2025 OpenCFD Ltd.
Copyright (C) 2018-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -28,6 +28,8 @@ License
#include "ListOps.H"
#include "CompactListList.H"
#include "HashSet.H"
#include <numeric>
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
@ -113,8 +115,7 @@ Foam::Map<Foam::label> Foam::invertToMap(const labelUList& values)
{
const label len = values.size();
Map<label> inverse;
inverse.reserve(len);
Map<label> inverse(2*len);
for (label i = 0 ; i < len; ++i)
{
@ -279,14 +280,13 @@ void Foam::inplaceReorder
void Foam::ListOps::unionEqOp::operator()
(
labelList& x,
const labelUList& y
const labelList& y
) const
{
if (y.size())
{
if (x.size())
{
// Using HashSet will likely change the order of list
labelHashSet set(x);
set.insert(y);
x = set.toc();

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2017-2025 OpenCFD Ltd.
Copyright (C) 2017-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -485,6 +485,7 @@ labelPair findMinMax(const ListType& input, label start=0);
// <code> (list[i] < val) </code> for the test.
//
// \tparam ListType The input list type
// \tparam T The value type (should normally be ListType::value_type)
//
// \param input The sorted list to search
// \param val The value for searching/comparing
@ -507,7 +508,7 @@ label findSortedIndex
// <code> lessOp<T>(list[i], val) </code> for the test.
//
// \tparam ListType The input list type
// \tparam T The value type (usually the same as ListType::value_type)
// \tparam T The value type (is often the same as ListType::value_type)
// \tparam ComparePredicate The type of the comparison functor that
// returns true for sorting below.
//
@ -584,33 +585,23 @@ namespace ListOps
template<class T>
struct appendEqOp
{
void operator()(List<T>& x, const UList<T>& y) const;
void operator()(List<T>& x, const List<T>& y) const;
};
//- List helper to append y unique elements onto the end of x
template<class T>
struct uniqueEqOp
{
void operator()(List<T>& x, const UList<T>& y) const;
void operator()(List<T>& x, const List<T>& y) const;
};
//- List helper to add y unique elements to x
struct unionEqOp
{
void operator()(labelList& x, const labelUList& y) const;
void operator()(labelList& x, const labelList& y) const;
};
//- Test for list equality with different but compatible data types.
//- Eg, int32 and int64
template<class Type1, class Type2>
bool equal(const UList<Type1>& a, const UList<Type2>& b);
//- Test for list equality with different but compatible data types.
template<class Type1, class Type2, class BinaryPredicate>
bool equal(const UList<Type1>& a, const UList<Type2>& b, BinaryPredicate pred);
// Public classes
//- A list compare binary predicate for normal sort

View File

@ -1081,7 +1081,7 @@ template<class T>
void Foam::ListOps::appendEqOp<T>::operator()
(
List<T>& x,
const UList<T>& y
const List<T>& y
) const
{
if (y.size())
@ -1102,7 +1102,7 @@ template<class T>
void Foam::ListOps::uniqueEqOp<T>::operator()
(
List<T>& x,
const UList<T>& y
const List<T>& y
) const
{
if (y.size())
@ -1111,7 +1111,6 @@ void Foam::ListOps::uniqueEqOp<T>::operator()
{
for (const T& val : y)
{
// Not very efficient
x.push_uniq(val);
}
}
@ -1123,37 +1122,6 @@ void Foam::ListOps::uniqueEqOp<T>::operator()
}
template<class Type1, class Type2>
bool Foam::ListOps::equal
(
const UList<Type1>& a,
const UList<Type2>& b
)
{
return
(
(a.size() == b.size())
&& std::equal(a.cbegin(), a.cend(), b.cbegin())
);
}
template<class Type1, class Type2, class BinaryPredicate>
bool Foam::ListOps::equal
(
const UList<Type1>& a,
const UList<Type2>& b,
BinaryPredicate pred
)
{
return
(
(a.size() == b.size())
&& std::equal(a.cbegin(), a.cend(), b.cbegin(), pred)
);
}
template<class ListType, class UnaryPredicate>
Foam::label Foam::ListOps::count_if
(

View File

@ -34,6 +34,7 @@ Description
#ifndef Foam_ListPolicy_H
#define Foam_ListPolicy_H
#include "MemoryPool.H" // Also includes <cstdint>
#include "contiguous.H" // Also includes <type_traits>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -103,6 +104,18 @@ template<> struct no_linebreak<wordRe> : std::true_type {};
// - use_offload(n) :
// Lower threshold for switching to device offloading
//
//
// Use of the memory-pool is controlled by the 'is_aligned_type()' test
// and the minimum field size, controlled by the 'use_memory_pool()' test.
//
// If the memory-pool is not enabled or not required according to the two
// above tests, the allocation falls back to either an aligned or unaligned
// allocation.
//
// The decision about when to choose aligned vs unaligned allocation
// is still a compile-time option. Made by direct edit of the
// appropriate functions.
//
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Consider aligned allocation for the given type?
@ -146,27 +159,104 @@ inline constexpr bool use_offload(IntType n) noexcept
}
//- Default alignment for larger fields
inline constexpr std::align_val_t default_alignment() noexcept
{
return std::align_val_t(256);
}
//- Allocate from memory pool (if active), or aligned, or normal
template<class T, class IntType>
inline T* allocate(IntType n)
{
// Plain new
return new T[n];
if constexpr (ListPolicy::is_aligned_type<T>())
{
// Note: threshold for use_memory_pool() >= use_alignment()
if (ListPolicy::use_alignment(n))
{
if
(
void *pool_ptr
(
// Consider memory pool for large amounts of data
ListPolicy::use_memory_pool(n)
? Foam::MemoryPool::try_allocate(sizeof(T)*n)
: nullptr
);
pool_ptr
)
{
// Placement new
return new (pool_ptr) T[n];
}
else
{
return new (ListPolicy::default_alignment()) T[n];
}
}
else
{
// Plain new
return new T[n];
}
}
else
{
// Plain new
return new T[n];
}
}
//- Deallocate from memory pool, or normal
template<class T, class IntType>
inline void deallocate(T* ptr)
{
// Plain new
delete[] ptr;
if constexpr (ListPolicy::is_aligned_type<T>())
{
if (ptr && !Foam::MemoryPool::try_deallocate(ptr))
{
// Plain new
delete[] ptr;
}
}
else
{
// Plain new
delete[] ptr;
}
}
//- Deallocate from memory pool, or aligned, or normal
template<class T, class IntType>
inline void deallocate(T* ptr, [[maybe_unused]] IntType n)
{
// Plain new
delete[] ptr;
if constexpr (ListPolicy::is_aligned_type<T>())
{
// Note: threshold for use_memory_pool() >= use_alignment()
if (ListPolicy::use_alignment(n))
{
if (ptr && !Foam::MemoryPool::try_deallocate(ptr))
{
// Alignment depends on the number of elements
::operator delete[](ptr, ListPolicy::default_alignment());
}
}
else
{
// Plain new
delete[] ptr;
}
}
else
{
// Plain new
delete[] ptr;
}
}

View File

@ -257,13 +257,13 @@ public:
return ioState_ & std::ios_base::badbit;
}
//- True if the stream has not failed
//- Return true if the stream has not failed
explicit operator bool() const noexcept
{
return !fail();
}
//- True if the stream has failed
//- Return true if the stream has failed
bool operator!() const noexcept
{
return fail();
@ -406,10 +406,10 @@ public:
return flags((flags() & ~mask) | (f & mask));
}
//- Unset stream flags, return old stream flags
std::ios_base::fmtflags unsetf(std::ios_base::fmtflags f)
//- Unset flags of stream
void unsetf(std::ios_base::fmtflags f)
{
return flags(flags() & ~f);
flags(flags() & ~f);
}

View File

@ -179,9 +179,6 @@ public:
// Public Classes
//- Wrapper for OpenFOAM internal communicator index
class communicator; // Forward Declaration
//- Wrapper for MPI_Comm
class Communicator; // Forward Declaration
@ -381,25 +378,6 @@ public:
//- Print un-directed graph in graphviz dot format
void printGraph(Ostream& os, int proci = 0) const;
//- Write the communication tree
Ostream& writeList(Ostream& os) const
{
return tree_.writeList(os);
}
// Member / Friend Operators
//- Write the communication tree
friend Ostream& operator<<
(
Ostream& os,
const commsStructList& rhs
)
{
return rhs.writeList(os);
}
};
@ -872,7 +850,7 @@ public:
const bool withComponents = true
);
//- Create new communicator with sub-ranks on the parent communicator
//- Creaet new communicator with sub-ranks on the parent communicator
static label newCommunicator
(
//! The parent communicator
@ -918,6 +896,126 @@ public:
const bool withComponents = true
);
//- Wrapper class for allocating/freeing communicators. Always invokes
//- allocateCommunicatorComponents() and freeCommunicatorComponents()
class communicator
{
label comm_;
public:
//- No copy construct
communicator(const communicator&) = delete;
//- No copy assignment
void operator=(const communicator&) = delete;
//- Default construct (a placeholder communicator)
communicator() noexcept : comm_(-1) {}
//- Move construct, takes ownership
communicator(communicator&& c) : comm_(c.comm_) { c.comm_ = -1; }
//- Allocate communicator for contiguous sub-ranks on given parent
communicator
(
//! The parent communicator
const label parentComm,
//! The contiguous sub-ranks of parent to use
const labelRange& subRanks
)
:
comm_(UPstream::newCommunicator(parentComm, subRanks))
{}
//- Allocate communicator for sub-ranks on given parent
communicator
(
//! The parent communicator
const label parentComm,
//! The sub-ranks of parent to use (negative values ignored)
const labelUList& subRanks
)
:
comm_(UPstream::newCommunicator(parentComm, subRanks))
{}
//- Factory Method :
//- Duplicate the given communicator
static communicator duplicate(const label parentComm)
{
communicator c;
c.comm_ = UPstream::dupCommunicator(parentComm);
return c;
}
//- Factory Method :
//- Split the communicator on the given \em colour.
static communicator split
(
//! The parent communicator
const label parentComm,
//! The colouring to select which ranks to include.
//! Negative values correspond to 'ignore'
const int colour,
//! Use MPI_Allgather+MPI_Comm_create_group vs MPI_Comm_split
const bool two_step = true
)
{
communicator c;
c.comm_ =
UPstream::splitCommunicator(parentComm, colour, two_step);
return c;
}
//- Free allocated communicator
~communicator() { UPstream::freeCommunicator(comm_); }
//- True if communicator is non-negative (ie, was allocated)
bool good() const noexcept { return (comm_ >= 0); }
//- The communicator label
label comm() const noexcept { return comm_; }
//- Release ownership of the communicator, return old value.
// Leave further management to the caller
label release() noexcept { label c(comm_); comm_ = -1; return c; }
//- Free allocated communicator
void reset() { UPstream::freeCommunicator(comm_); comm_ = -1; }
//- Allocate with contiguous sub-ranks of parent communicator
void reset(label parent, const labelRange& subRanks)
{
UPstream::freeCommunicator(comm_);
comm_ = UPstream::newCommunicator(parent, subRanks);
}
//- Allocate with sub-ranks of parent communicator
void reset(label parent, const labelUList& subRanks)
{
UPstream::freeCommunicator(comm_);
comm_ = UPstream::newCommunicator(parent, subRanks);
}
//- Take ownership, free allocated communicator
// \caution do not call as self-assignment
void reset(communicator&& c)
{
if (comm_ != c.comm_) UPstream::freeCommunicator(comm_);
comm_ = c.comm_;
c.comm_ = -1;
}
//- Move assignment, takes ownership
// \caution do not call as self-assignment
void operator=(communicator&& c) { reset(std::move(c)); }
//- Cast to label - the same as comm()
operator label() const noexcept { return comm_; }
};
//- Return physical processor number (i.e. processor number in
//- worldComm) given communicator and processor
static int baseProcNo(label comm, int procID);
@ -1741,168 +1839,6 @@ public:
}
};
/*---------------------------------------------------------------------------*\
Class UPstream::communicator Declaration
\*---------------------------------------------------------------------------*/
//- Wrapper for internally indexed communicator label.
//- Always invokes UPstream::allocateCommunicatorComponents()
//- and UPstream::freeCommunicatorComponents()
class UPstream::communicator
{
// Private Data
//- The communicator label
label comm_;
public:
// Generated Methods
//- No copy construct
communicator(const communicator&) = delete;
//- No copy assignment
void operator=(const communicator&) = delete;
// Constructors
//- Default construct (a placeholder communicator)
communicator() noexcept : comm_(-1) {}
//- Move construct, takes ownership
communicator(communicator&& c) : comm_(c.comm_) { c.comm_ = -1; }
//- Allocate communicator for contiguous sub-ranks on given parent
communicator
(
//! The parent communicator
const label parentComm,
//! The contiguous sub-ranks of parent to use
const labelRange& subRanks
)
:
comm_(UPstream::newCommunicator(parentComm, subRanks))
{}
//- Allocate communicator for sub-ranks on given parent
communicator
(
//! The parent communicator
const label parentComm,
//! The sub-ranks of parent to use (negative values ignored)
const labelUList& subRanks
)
:
comm_(UPstream::newCommunicator(parentComm, subRanks))
{}
// Destructor
//- Free allocated communicator
~communicator() { UPstream::freeCommunicator(comm_); }
// Factory Methods
//- Duplicate the given communicator
static communicator duplicate(const label parentComm)
{
communicator c;
c.comm_ = UPstream::dupCommunicator(parentComm);
return c;
}
//- Factory Method :
//- Split the communicator on the given \em colour.
static communicator split
(
//! The parent communicator
const label parentComm,
//! The colouring to select which ranks to include.
//! Negative values correspond to 'ignore'
const int colour,
//! Use MPI_Allgather+MPI_Comm_create_group vs MPI_Comm_split
const bool two_step = true
)
{
communicator c;
c.comm_ = UPstream::splitCommunicator(parentComm, colour, two_step);
return c;
}
// Member Functions
//- True if communicator is non-negative (ie, was allocated)
bool good() const noexcept { return (comm_ >= 0); }
//- The communicator label
label comm() const noexcept { return comm_; }
//- Return non-const reference to this
communicator& constCast() const noexcept
{
return const_cast<communicator&>(*this);
}
//- Release ownership of the communicator, return old value.
// Leave further management to the caller
label release() noexcept { label c(comm_); comm_ = -1; return c; }
//- Free allocated communicator
void reset() { UPstream::freeCommunicator(comm_); comm_ = -1; }
//- Allocate with contiguous sub-ranks of parent communicator
void reset(label parent, const labelRange& subRanks)
{
UPstream::freeCommunicator(comm_);
comm_ = UPstream::newCommunicator(parent, subRanks);
}
//- Allocate with sub-ranks of parent communicator
void reset(label parent, const labelUList& subRanks)
{
UPstream::freeCommunicator(comm_);
comm_ = UPstream::newCommunicator(parent, subRanks);
}
//- Take ownership, free managed communicator
void reset(communicator&& c)
{
if (this == &c) return; // No self-assignment
if (comm_ != c.comm_) UPstream::freeCommunicator(comm_);
comm_ = c.comm_;
c.comm_ = -1;
}
//- Swap communicator labels
void swap(communicator& c) { std::swap(comm_, c.comm_); }
// Member Operators
//- Implicit cast to label - the same as comm()
operator label() const noexcept { return comm_; }
//- Move assignment, takes ownership
void operator=(communicator&& c) { reset(std::move(c)); }
//- Test for equality
bool operator==(const communicator& c) const noexcept
{
return (comm_ == c.comm_);
}
//- Test for inequality
bool operator!=(const communicator& c) const noexcept
{
return (comm_ != c.comm_);
}
};
/*---------------------------------------------------------------------------*\
Class UPstream::Communicator Declaration

View File

@ -470,10 +470,18 @@ public:
//- Copy append a list of tokens at the current tokenIndex,
//- incrementing the index.
//
// \param newTokens the list of tokens to copy append
// \param lazy leaves any excess capacity for further appends.
// The caller will be responsible for resizing later.
void add_tokens(const UList<token>& toks);
//- Move append a list of tokens at the current tokenIndex,
//- incrementing the index.
//
// \param newTokens the list of tokens to move append
// \param lazy leaves any excess capacity for further appends.
// The caller will be responsible for resizing later.
void add_tokens(List<token>&& toks);

View File

@ -32,7 +32,7 @@ Note
#include "error.H"
#include "dictionary.H"
#include "foamVersion.H"
#include "UPstream.H"
#include "Pstream.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -106,34 +106,22 @@ Foam::messageStream::messageStream(const dictionary& dict)
Foam::OSstream& Foam::messageStream::stream
(
OSstream* alternative,
int communicator
OSstream* alternative
)
{
if (communicator < 0)
{
communicator = UPstream::worldComm;
}
if (level)
{
// Master-only output?
const bool masterOnly
// Serlal (master only) output?
const bool serialOnly
(
!UPstream::parRun()
|| ((severity_ & ~errorSeverity::USE_STDERR) == errorSeverity::INFO)
|| ((severity_ & ~errorSeverity::USE_STDERR) == errorSeverity::WARNING)
);
if
(
masterOnly
&& (UPstream::parRun() && !UPstream::master(communicator))
)
if (serialOnly && (UPstream::parRun() && !UPstream::master()))
{
// Requested master-only output but is non-master (in parallel)
// -> early exit
return Snull;
return Snull; // Non-serial, non-master: exit early
}
@ -151,9 +139,10 @@ Foam::OSstream& Foam::messageStream::stream
OSstream* osptr;
if (masterOnly)
if (serialOnly)
{
// Use supplied alternative? Valid for master-only output
// Use supplied alternative? Valid for serial only
osptr =
(
alternative
@ -163,6 +152,7 @@ Foam::OSstream& Foam::messageStream::stream
}
else
{
// Non-serial
osptr = (use_stderr ? &Perr : &Pout);
}
@ -185,13 +175,8 @@ Foam::OSstream& Foam::messageStream::stream
}
Foam::OSstream& Foam::messageStream::masterStream(int communicator)
Foam::OSstream& Foam::messageStream::masterStream(const int communicator)
{
if (communicator < 0)
{
communicator = UPstream::worldComm;
}
if (UPstream::warnComm >= 0 && communicator != UPstream::warnComm)
{
Perr<< "** messageStream with comm:" << communicator << endl;
@ -200,7 +185,7 @@ Foam::OSstream& Foam::messageStream::masterStream(int communicator)
if (communicator == UPstream::worldComm || UPstream::master(communicator))
{
return this->stream(nullptr, communicator);
return this->stream();
}
return Snull;
@ -209,7 +194,6 @@ Foam::OSstream& Foam::messageStream::masterStream(int communicator)
std::ostream& Foam::messageStream::stdStream()
{
// Currently do not need communicator != worldComm
return this->stream().stdStream();
}
@ -416,13 +400,13 @@ Foam::OSstream& Foam::messageStream::operator()
Foam::messageStream Foam::Info
(
// No title
"", // No title
Foam::messageStream::INFO
);
Foam::messageStream Foam::InfoErr
(
// No title
"", // No title
Foam::messageStream::INFO,
0,
true // use_stderr = true

View File

@ -179,7 +179,7 @@ public:
// \return the previous value for maxErrors
int maxErrors(int nErrors) noexcept
{
int old(maxErrors_);
int old = maxErrors_;
maxErrors_ = nErrors;
return old;
}
@ -191,15 +191,12 @@ public:
OSstream& stream
(
//! An alternative output stream (serial-only)
OSstream* alternative = nullptr,
//! Communicator. Negative is treated like UPstream::worldComm
int communicator = -1
OSstream* alternative = nullptr
);
//- Return OSstream for output operations on the master process only,
//- Snull on other processes.
// A negative communicator is treated like UPstream::worldComm
OSstream& masterStream(int communicator);
OSstream& masterStream(const int communicator);
//- Return std::ostream for output operations.
std::ostream& stdStream();

View File

@ -145,9 +145,9 @@ public:
// Static Member Functions
//- Return a null DimensionedField (reference to a nullObject).
static const this_type& null() noexcept
static const DimensionedField<Type, GeoMesh>& null() noexcept
{
return NullObjectRef<this_type>();
return NullObjectRef<DimensionedField<Type, GeoMesh>>();
}
@ -373,33 +373,6 @@ public:
Field<Type>&& iField
);
//- Return tmp field (NO_READ, NO_WRITE)
//- from name, mesh, dimensions, primitive field (tmp).
//- [Takes current timeName from the mesh registry].
// For LEGACY_REGISTER, registration is determined by
// objectRegistry::is_cacheTemporaryObject().
static tmp<DimensionedField<Type, GeoMesh>> New
(
const word& name,
IOobjectOption::registerOption regOpt,
const Mesh& mesh,
const dimensionSet& dims,
const tmp<Field<Type>>& tfield
);
//- Return tmp field (NO_READ, NO_WRITE)
//- from name, mesh, dimensions, primitive field (tmp).
//- [Takes current timeName from the mesh registry].
// Registration/persistence determined by
// objectRegistry::is_cacheTemporaryObject().
static tmp<DimensionedField<Type, GeoMesh>> New
(
const word& name,
const Mesh& mesh,
const dimensionSet& dims,
const tmp<Field<Type>>& tfield
);
//- Return tmp field (NO_READ, NO_WRITE)
//- from name, mesh, dimensions.
//- [Takes current timeName from the mesh registry].

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022-2025 OpenCFD Ltd.
Copyright (C) 2022-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -163,49 +163,6 @@ Foam::DimensionedField<Type, GeoMesh>::New
}
template<class Type, class GeoMesh>
Foam::tmp<Foam::DimensionedField<Type, GeoMesh>>
Foam::DimensionedField<Type, GeoMesh>::New
(
const word& name,
IOobjectOption::registerOption regOpt,
const Mesh& mesh,
const dimensionSet& dims,
const tmp<Field<Type>>& tfield
)
{
return DimensionedField<Type, GeoMesh>::New_impl
(
regOpt,
name,
mesh,
dims,
tfield
);
}
template<class Type, class GeoMesh>
Foam::tmp<Foam::DimensionedField<Type, GeoMesh>>
Foam::DimensionedField<Type, GeoMesh>::New
(
const word& name,
const Mesh& mesh,
const dimensionSet& dims,
const tmp<Field<Type>>& tfield
)
{
return DimensionedField<Type, GeoMesh>::New_impl
(
IOobjectOption::LEGACY_REGISTER,
name,
mesh,
dims,
tfield
);
}
template<class Type, class GeoMesh>
Foam::tmp<Foam::DimensionedField<Type, GeoMesh>>
Foam::DimensionedField<Type, GeoMesh>::New

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017,2022 OpenFOAM Foundation
Copyright (C) 2016-2025 OpenCFD Ltd.
Copyright (C) 2016-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -38,56 +38,53 @@ template<class CheckPatchFieldType>
bool Foam::GeometricBoundaryField<Type, PatchField, GeoMesh>::checkConsistency
(
const scalar tol,
const bool exitIfBad
const bool doExit
) const
{
auto& bfld = this->constCast();
if (!bfld.size())
if (!this->size())
{
return true;
}
if (debug&2)
{
const auto& pfld0 = this->operator[](0);
PoutInFunction
<< " Checking boundary consistency for field "
<< bfld[0].internalField().name() << endl;
<< pfld0.internalField().name()
<< endl;
}
// Store old values and states
List<Field<Type>> oldFields(bfld.size());
boolList oldUpdated(bfld.size());
boolList oldManipulated(bfld.size());
auto& bfld = this->constCast();
label nEvaluated(0);
// Store old value
List<Field<Type>> oldBfld(this->size());
boolList oldUpdated(this->size());
//Note: areaFields (finiteArea) do not have manipulatedMatrix() flag. TBD.
//boolList oldManipulated(this->size());
for (auto& pfld : bfld)
{
if (isA<CheckPatchFieldType>(pfld))
{
const label patchi = pfld.patch().index();
oldFields[patchi] = pfld;
oldUpdated[patchi] = pfld.updated();
oldManipulated[patchi] = pfld.manipulatedMatrix();
++nEvaluated;
oldBfld[patchi] = pfld;
//oldManipulated[patchi] = pfld.manipulatedMatrix();
}
}
if (!nEvaluated) return true; // Early termination
// Re-evaluate
{
const label startOfRequests = UPstream::nRequests();
nEvaluated = 0;
for (auto& pfld : bfld)
{
if (isA<CheckPatchFieldType>(pfld))
{
pfld.initEvaluate(UPstream::commsTypes::nonBlocking);
++nEvaluated;
}
}
@ -99,81 +96,90 @@ bool Foam::GeometricBoundaryField<Type, PatchField, GeoMesh>::checkConsistency
if (isA<CheckPatchFieldType>(pfld))
{
pfld.evaluate(UPstream::commsTypes::nonBlocking);
if (--nEvaluated == 0) break; // Early termination
}
}
}
// Check
bool allOk(true);
bool ok = true;
for (auto& pfld : bfld)
{
if (isA<CheckPatchFieldType>(pfld))
{
const label patchi = pfld.patch().index();
auto& oldPfld = oldFields[patchi];
const auto& oldPfld = oldBfld[patchi];
bool localOk(true);
if (allOk)
forAll(pfld, facei)
{
// Only check for first failed patch
forAll(pfld, facei)
if (mag(pfld[facei]-oldPfld[facei]) > tol)
{
if (tol < Foam::mag(pfld[facei]-oldPfld[facei]))
{
allOk = false;
localOk = false;
break;
}
ok = false;
break;
}
}
if (!localOk)
if (!ok)
{
// Raise warning or error
OSstream& err =
(
exitIfBad
? FatalErrorInFunction
: WarningInFunction
);
err << "Field "
<< pfld.internalField().name()
<< " is not evaluated?"
<< " On patch " << pfld.patch().name()
<< " type " << pfld.type()
<< " : average of field = "
<< average(oldPfld)
<< ". Average of evaluated field = "
<< average(pfld)
<< ". Difference:" << average(pfld-oldPfld)
<< ". Tolerance:" << tol << endl;
if (exitIfBad)
if (doExit)
{
FatalError<< exit(FatalError);
FatalErrorInFunction << "Field "
<< pfld.internalField().name()
<< " is not evaluated?"
<< " On patch " << pfld.patch().name()
<< " type " << pfld.type()
<< " : average of field = "
<< average(oldPfld)
<< ". Average of evaluated field = "
<< average(pfld)
<< ". Difference:" << average(pfld-oldPfld)
<< ". Tolerance:" << tol
<< exit(FatalError);
}
else
{
WarningInFunction << "Field "
<< pfld.internalField().name()
<< " is not evaluated?"
<< " On patch " << pfld.patch().name()
<< " type " << pfld.type()
<< " : average of field = "
<< average(oldPfld)
<< ". Average of evaluated field = "
<< average(pfld)
<< ". Difference:" << average(pfld-oldPfld)
<< ". Tolerance:" << tol
<< endl;
// Skip other patches
break;
}
}
}
}
// Restore patch field values and states
static_cast<Field<Type>&>(pfld) = std::move(oldPfld);
// Restore bfld, updated
for (auto& pfld : bfld)
{
if (isA<CheckPatchFieldType>(pfld))
{
const label patchi = pfld.patch().index();
pfld.setUpdated(oldUpdated[patchi]);
pfld.setManipulated(oldManipulated[patchi]);
Field<Type>& vals = pfld;
vals = std::move(oldBfld[patchi]);
//pfld.setManipulated(oldManipulated[patchi]);
}
}
if (debug&2)
{
const auto& pfld0 = this->operator[](0);
PoutInFunction
<< " Result of checking for field "
<< bfld[0].internalField().name() << " : " << allOk << endl;
<< pfld0.internalField().name() << " : " << ok << endl;
}
return allOk;
return ok;
}
@ -620,7 +626,6 @@ void Foam::GeometricBoundaryField<Type, PatchField, GeoMesh>::evaluate_if
|| commsType == UPstream::commsTypes::nonBlocking
)
{
label nEvaluated(0);
const label startOfRequests = UPstream::nRequests();
for (auto& pfld : *this)
@ -628,21 +633,17 @@ void Foam::GeometricBoundaryField<Type, PatchField, GeoMesh>::evaluate_if
if (pred(pfld))
{
pfld.initEvaluate(commsType);
++nEvaluated;
}
}
// Wait for outstanding requests (non-blocking)
UPstream::waitRequests(startOfRequests);
if (!nEvaluated) return; // Early termination
for (auto& pfld : *this)
{
if (pred(pfld))
{
pfld.evaluate(commsType);
if (--nEvaluated == 0) break; // Early termination
}
}
}
@ -777,25 +778,81 @@ void Foam::GeometricBoundaryField<Type, PatchField, GeoMesh>::evaluateCoupled
const UPstream::commsTypes commsType
)
{
if constexpr (std::is_void_v<CoupledPatchType>)
// Alternative (C++14)
//
// this->evaluate_if
// (
// [](const auto& pfld) -> bool
// {
// const auto* cpp = isA<CoupledPatchType>(pfld.patch());
// return (cpp && cpp->coupled());
// },
// commsType
// );
// DebugInFunction << nl;
if
(
commsType == UPstream::commsTypes::buffered
|| commsType == UPstream::commsTypes::nonBlocking
)
{
this->evaluate_if
(
[](const auto& pfld) { return pfld.coupled(); },
commsType
);
const label startOfRequests = UPstream::nRequests();
for (auto& pfld : *this)
{
const auto* cpp = isA<CoupledPatchType>(pfld.patch());
if (cpp && cpp->coupled())
{
pfld.initEvaluate(commsType);
}
}
// Wait for outstanding requests (non-blocking)
UPstream::waitRequests(startOfRequests);
for (auto& pfld : *this)
{
const auto* cpp = isA<CoupledPatchType>(pfld.patch());
if (cpp && cpp->coupled())
{
pfld.evaluate(commsType);
}
}
}
else if (commsType == UPstream::commsTypes::scheduled)
{
const lduSchedule& patchSchedule =
bmesh_.mesh().globalData().patchSchedule();
for (const auto& schedEval : patchSchedule)
{
const label patchi = schedEval.patch;
auto& pfld = (*this)[patchi];
const auto* cpp = isA<CoupledPatchType>(pfld.patch());
if (cpp && cpp->coupled())
{
if (schedEval.init)
{
pfld.initEvaluate(commsType);
}
else
{
pfld.evaluate(commsType);
}
}
}
}
else
{
this->evaluate_if
(
[](const auto& pfld) -> bool
{
const auto* cpp = isA<CoupledPatchType>(pfld.patch());
return (cpp && cpp->coupled());
},
commsType
);
FatalErrorInFunction
<< "Unsupported communications type " << int(commsType) << nl
<< exit(FatalError);
}
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017,2022 OpenFOAM Foundation
Copyright (C) 2015-2025 OpenCFD Ltd.
Copyright (C) 2015-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -88,8 +88,7 @@ private:
// Private Member Functions
//- Check if patch fields have been consistently evaluated.
// If not:
//- Helper: check if patchfields have been evaluated. If not:
// exit = true : FatalError
// exit = false : return bool
template<class CheckPatchField>
@ -206,12 +205,8 @@ public:
const UPstream::commsTypes commsType = UPstream::defaultCommsType
);
//- Evaluate boundary conditions on coupled patches of the given type,
//- using specified or default comms.
//
// \tparam CoupledPatchType The coupled \b patch type that should
// be evaluated. For a \c void type,
// all coupled patch fields will be evaluated.
//- Evaluate boundary conditions on coupled patches of given type.
//- Uses specified or default comms.
template<class CoupledPatchType>
void evaluateCoupled
(

View File

@ -63,10 +63,8 @@ void Foam::GeometricField<Type, PatchField, GeoMesh>::readFields
if (dict.readIfPresent("referenceLevel", refLevel))
{
// Add to internal (primitive) field
this->field() += refLevel;
Field<Type>::operator+=(refLevel);
// Add to boundary fields
forAll(boundaryField_, patchi)
{
boundaryField_[patchi] == boundaryField_[patchi] + refLevel;
@ -411,7 +409,7 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
boundaryField_(mesh.boundary(), *this, patchFieldType)
{
DebugInFunction
<< "Copy construct from primitive field" << nl << this->info() << endl;
<< "Copy construct from internal field" << nl << this->info() << endl;
readIfPresent();
}
@ -432,28 +430,7 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
boundaryField_(mesh.boundary(), *this, patchFieldType)
{
DebugInFunction
<< "Move construct from primitive field" << nl << this->info() << endl;
readIfPresent();
}
template<class Type, template<class> class PatchField, class GeoMesh>
Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
(
const IOobject& io,
const Mesh& mesh,
const dimensionSet& dims,
const tmp<Field<Type>>& tfield,
const word& patchFieldType
)
:
Internal(io, mesh, dims, tfield),
timeIndex_(this->time().timeIndex()),
boundaryField_(mesh.boundary(), *this, patchFieldType)
{
DebugInFunction
<< "Construct from tmp primitive field" << nl << this->info() << endl;
<< "Move construct from internal field" << nl << this->info() << endl;
readIfPresent();
}
@ -1414,7 +1391,10 @@ void Foam::GeometricField<Type, PatchField, GeoMesh>::operator=
// Make sure any e.g. jump-cyclic are updated.
boundaryFieldRef().evaluate_if
(
[](const auto& pfld) { return pfld.constraintOverride(); }
[](const auto& pfld) -> bool
{
return pfld.constraintOverride();
}
);
}
@ -1456,7 +1436,10 @@ void Foam::GeometricField<Type, PatchField, GeoMesh>::operator=
// Make sure any e.g. jump-cyclic are updated.
boundaryFieldRef().evaluate_if
(
[](const auto& pfld) { return pfld.constraintOverride(); }
[](const auto& pfld) -> bool
{
return pfld.constraintOverride();
}
);
}
@ -1473,7 +1456,10 @@ void Foam::GeometricField<Type, PatchField, GeoMesh>::operator=
// Make sure any e.g. jump-cyclic are updated.
boundaryFieldRef().evaluate_if
(
[](const auto& pfld) { return pfld.constraintOverride(); }
[](const auto& pfld) -> bool
{
return pfld.constraintOverride();
}
);
}
@ -1498,7 +1484,10 @@ void Foam::GeometricField<Type, PatchField, GeoMesh>::operator==
// Make sure any e.g. jump-cyclic are updated.
boundaryFieldRef().evaluate_if
(
[](const auto& pfld) { return pfld.constraintOverride(); }
[](const auto& pfld) -> bool
{
return pfld.constraintOverride();
}
);
}
@ -1515,7 +1504,10 @@ void Foam::GeometricField<Type, PatchField, GeoMesh>::operator==
// Make sure any e.g. jump-cyclic are updated.
boundaryFieldRef().evaluate_if
(
[](const auto& pfld) { return pfld.constraintOverride(); }
[](const auto& pfld) -> bool
{
return pfld.constraintOverride();
}
);
}
@ -1535,7 +1527,10 @@ void Foam::GeometricField<Type, PatchField, GeoMesh>::operator op \
\
boundaryFieldRef().evaluate_if \
( \
[](const auto& pfld) { return pfld.constraintOverride(); } \
[](const auto& pfld) -> bool \
{ \
return pfld.constraintOverride(); \
} \
); \
} \
\
@ -1550,7 +1545,10 @@ void Foam::GeometricField<Type, PatchField, GeoMesh>::operator op \
\
boundaryFieldRef().evaluate_if \
( \
[](const auto& pfld) { return pfld.constraintOverride(); } \
[](const auto& pfld) -> bool \
{ \
return pfld.constraintOverride(); \
} \
); \
} \
\
@ -1565,7 +1563,10 @@ void Foam::GeometricField<Type, PatchField, GeoMesh>::operator op \
\
boundaryFieldRef().evaluate_if \
( \
[](const auto& pfld) { return pfld.constraintOverride(); } \
[](const auto& pfld) -> bool \
{ \
return pfld.constraintOverride(); \
} \
); \
}

View File

@ -156,9 +156,9 @@ public:
// Static Member Functions
//- Return a null GeometricField (reference to a nullObject).
static const this_type& null() noexcept
static const GeometricField<Type, PatchField, GeoMesh>& null() noexcept
{
return NullObjectRef<this_type>();
return NullObjectRef<GeometricField<Type, PatchField, GeoMesh>>();
}
@ -251,7 +251,7 @@ public:
const PtrList<PatchField<Type>>& ptfl
);
//- Construct from internal field (tmp) and a patch list to clone
//- Move construct from internal field and a patch list to clone
GeometricField
(
const IOobject& io,
@ -273,7 +273,7 @@ public:
const PtrList<PatchField<Type>>& ptfl
);
//- Copy construct from primitive field, with specified patch type
//- Copy construct from internal field, with specified patch type
GeometricField
(
const IOobject& io,
@ -283,7 +283,7 @@ public:
const word& patchFieldType = PatchField<Type>::calculatedType()
);
//- Move construct from primitive field, with specified patch type
//- Move construct from internal field, with specified patch type
GeometricField
(
const IOobject& io,
@ -293,17 +293,7 @@ public:
const word& patchFieldType = PatchField<Type>::calculatedType()
);
//- Construct from primitive field (tmp), with specified patch type
GeometricField
(
const IOobject& io,
const Mesh& mesh,
const dimensionSet& dims,
const tmp<Field<Type>>& tfield,
const word& patchFieldType = PatchField<Type>::calculatedType()
);
//- Copy construct from primitive field and a patch list to clone
//- Copy construct from components
GeometricField
(
const IOobject& io,
@ -313,7 +303,7 @@ public:
const PtrList<PatchField<Type>>& ptfl
);
//- Move construct from primitive field and a patch list to clone
//- Move construct from internal field and a patch list to clone
GeometricField
(
const IOobject& io,
@ -329,7 +319,7 @@ public:
const IOobject& io,
const Mesh& mesh,
const dimensionSet& dims,
const tmp<Field<Type>>& tfield,
const tmp<Field<Type>>& tiField,
const PtrList<PatchField<Type>>& ptfl
);
@ -518,37 +508,6 @@ public:
const word& patchFieldType = PatchField<Type>::calculatedType()
);
//- Return tmp field (NO_READ, NO_WRITE)
//- from name, mesh, dimensions, tmp of primitive field
//- and patch type.
//- [Takes current timeName from the mesh registry].
// For LEGACY_REGISTER, registration is determined by
// objectRegistry::is_cacheTemporaryObject().
static tmp<GeometricField<Type, PatchField, GeoMesh>> New
(
const word& name,
IOobjectOption::registerOption regOpt,
const Mesh& mesh,
const dimensionSet& dims,
const tmp<Field<Type>>& tfield,
const word& patchFieldType = PatchField<Type>::calculatedType()
);
//- Return tmp field (NO_READ, NO_WRITE)
//- from name, mesh, dimensions, tmp of primitive field
//- and patch type.
//- [Takes current timeName from the mesh registry].
// Registration/persistence determined by
// objectRegistry::is_cacheTemporaryObject().
static tmp<GeometricField<Type, PatchField, GeoMesh>> New
(
const word& name,
const Mesh& mesh,
const dimensionSet& dims,
const tmp<Field<Type>>& tfield,
const word& patchFieldType = PatchField<Type>::calculatedType()
);
//- Return tmp field (NO_READ, NO_WRITE)
//- from name, mesh, dimensions, copy of internal field contents
//- and patch list to clone.

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017 OpenFOAM Foundation
Copyright (C) 2019-2025 OpenCFD Ltd.
Copyright (C) 2019-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -215,53 +215,6 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::New
}
template<class Type, template<class> class PatchField, class GeoMesh>
Foam::tmp<Foam::GeometricField<Type, PatchField, GeoMesh>>
Foam::GeometricField<Type, PatchField, GeoMesh>::New
(
const word& name,
IOobjectOption::registerOption regOpt,
const Mesh& mesh,
const dimensionSet& dims,
const tmp<Field<Type>>& tfield,
const word& patchFieldType
)
{
return GeometricField<Type, PatchField, GeoMesh>::New_impl
(
regOpt,
name,
mesh,
dims,
tfield,
patchFieldType
);
}
template<class Type, template<class> class PatchField, class GeoMesh>
Foam::tmp<Foam::GeometricField<Type, PatchField, GeoMesh>>
Foam::GeometricField<Type, PatchField, GeoMesh>::New
(
const word& name,
const Mesh& mesh,
const dimensionSet& dims,
const tmp<Field<Type>>& tfield,
const word& patchFieldType
)
{
return GeometricField<Type, PatchField, GeoMesh>::New_impl
(
IOobjectOption::LEGACY_REGISTER,
name,
mesh,
dims,
tfield,
patchFieldType
);
}
template<class Type, template<class> class PatchField, class GeoMesh>
Foam::tmp<Foam::GeometricField<Type, PatchField, GeoMesh>>
Foam::GeometricField<Type, PatchField, GeoMesh>::New

View File

@ -6,7 +6,6 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -88,27 +87,20 @@ void Foam::basicSymmetryPointPatchField<Type>::evaluate
const Pstream::commsTypes
)
{
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type : no-op
}
else
{
const vectorField& nHat = this->patch().pointNormals();
const vectorField& nHat = this->patch().pointNormals();
const Field<Type> pif(this->patchInternalField());
// Could write as loop instead...
tmp<Field<Type>> tvalues
tmp<Field<Type>> tvalues =
(
(
0.5*(pif + transform(I - 2.0*sqr(nHat), pif))
);
this->patchInternalField()
+ transform(I - 2.0*sqr(nHat), this->patchInternalField())
)/2.0
);
// Get internal field to insert values into
auto& iF = const_cast<Field<Type>&>(this->primitiveField());
// Get internal field to insert values into
Field<Type>& iF = const_cast<Field<Type>&>(this->primitiveField());
this->setInInternalField(iF, tvalues());
}
this->setInInternalField(iF, tvalues());
}

View File

@ -27,6 +27,7 @@ License
\*---------------------------------------------------------------------------*/
#include "fixedValuePointPatchField.H"
#include "boolList.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //

View File

@ -84,27 +84,20 @@ Foam::cyclicSlipPointPatchField<Type>::cyclicSlipPointPatchField
template<class Type>
void Foam::cyclicSlipPointPatchField<Type>::evaluate(const Pstream::commsTypes)
{
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type : no-op
}
else
{
const vectorField& nHat = this->patch().pointNormals();
const vectorField& nHat = this->patch().pointNormals();
const Field<Type> pif(this->patchInternalField());
// Could write as loop instead...
tmp<Field<Type>> tvalues
tmp<Field<Type>> tvalues =
(
(
0.5*(pif + transform(I - 2.0*sqr(nHat), pif))
);
this->patchInternalField()
+ transform(I - 2.0*sqr(nHat), this->patchInternalField())
)/2.0
);
// Get internal field to insert values into
auto& iF = const_cast<Field<Type>&>(this->primitiveField());
// Get internal field to insert values into
Field<Type>& iF = const_cast<Field<Type>&>(this->primitiveField());
this->setInInternalField(iF, tvalues());
}
this->setInInternalField(iF, tvalues());
}

View File

@ -91,27 +91,20 @@ void Foam::nonuniformTransformCyclicPointPatchField<Type>::evaluate
const Pstream::commsTypes
)
{
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type : no-op
}
else
{
const vectorField& nHat = this->patch().pointNormals();
const vectorField& nHat = this->patch().pointNormals();
const Field<Type> pif(this->patchInternalField());
// Could write as loop instead...
tmp<Field<Type>> tvalues
tmp<Field<Type>> tvalues =
(
(
0.5*(pif + transform(I - 2.0*sqr(nHat), pif))
);
this->patchInternalField()
+ transform(I - 2.0*sqr(nHat), this->patchInternalField())
)/2.0
);
// Get internal field to insert values into
auto& iF = const_cast<Field<Type>&>(this->primitiveField());
// Get internal field to insert values into
Field<Type>& iF = const_cast<Field<Type>&>(this->primitiveField());
this->setInInternalField(iF, tvalues());
}
this->setInInternalField(iF, tvalues());
}

View File

@ -106,27 +106,20 @@ void Foam::symmetryPlanePointPatchField<Type>::evaluate
const Pstream::commsTypes
)
{
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type : no-op
}
else
{
const symmTensor rot(I - 2.0*sqr(symmetryPlanePatch_.n()));
vector nHat = symmetryPlanePatch_.n();
const Field<Type> pif(this->patchInternalField());
// Could write as loop instead...
tmp<Field<Type>> tvalues
tmp<Field<Type>> tvalues =
(
(
0.5*(pif + transform(rot, pif))
);
this->patchInternalField()
+ transform(I - 2.0*sqr(nHat), this->patchInternalField())
)/2.0
);
// Get internal field to insert values into
auto& iF = const_cast<Field<Type>&>(this->primitiveField());
// Get internal field to insert values into
Field<Type>& iF = const_cast<Field<Type>&>(this->primitiveField());
this->setInInternalField(iF, tvalues());
}
this->setInInternalField(iF, tvalues());
}

View File

@ -6,7 +6,6 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -29,6 +28,7 @@ License
#include "wedgePointPatchField.H"
#include "transformField.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Type>
@ -101,28 +101,17 @@ Foam::wedgePointPatchField<Type>::wedgePointPatchField
template<class Type>
void Foam::wedgePointPatchField<Type>::evaluate(const Pstream::commsTypes)
{
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type : no-op
}
else
{
// In order to ensure that the wedge patch is always flat, take the
// normal vector from the first point
// In order to ensure that the wedge patch is always flat, take the
// normal vector from the first point
const vector& nHat = this->patch().pointNormals()[0];
const symmTensor rot(I - 2.0*sqr(this->patch().pointNormals()[0]));
tmp<Field<Type>> tvalues =
transform(I - nHat*nHat, this->patchInternalField());
// Could write as loop instead...
tmp<Field<Type>> tvalues
(
transform(rot, this->patchInternalField())
);
// Get internal field to insert values into
Field<Type>& iF = const_cast<Field<Type>&>(this->primitiveField());
// Get internal field to insert values into
auto& iF = const_cast<Field<Type>&>(this->primitiveField());
this->setInInternalField(iF, tvalues());
}
this->setInInternalField(iF, tvalues());
}

View File

@ -6,7 +6,6 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -89,22 +88,13 @@ void Foam::fixedNormalSlipPointPatchField<Type>::evaluate
const Pstream::commsTypes
)
{
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type : no-op
}
else
{
tmp<Field<Type>> tvalues
(
transform(I - n_*n_, this->patchInternalField())
);
tmp<Field<Type>> tvalues =
transform(I - n_*n_, this->patchInternalField());
// Get internal field to insert values into
auto& iF = const_cast<Field<Type>&>(this->primitiveField());
// Get internal field to insert values into
Field<Type>& iF = const_cast<Field<Type>&>(this->primitiveField());
this->setInInternalField(iF, tvalues());
}
this->setInInternalField(iF, tvalues());
}

View File

@ -318,7 +318,6 @@ void Foam::pointPatchField<Type>::evaluate(const Pstream::commsTypes)
}
pointPatchFieldBase::setUpdated(false);
pointPatchFieldBase::setManipulated(false);
}

View File

@ -98,6 +98,16 @@ protected:
// Useful when initially constructed without a dictionary
virtual void readDict(const dictionary& dict);
//- Set updated state
void setUpdated(bool state) noexcept
{
updated_ = state;
}
//- Set matrix manipulated state. Currently a no-op for pointPatchField.
void setManipulated(bool state) noexcept
{}
public:
@ -218,24 +228,13 @@ public:
return updated_;
}
//- Set updated state
void setUpdated(bool state) noexcept
{
updated_ = state;
}
//- True if the matrix has already been manipulated.
//- Currently always false for pointPatchField
//- Currently ignored (always false) for pointPatchField
bool manipulatedMatrix() const noexcept
{
return false;
}
//- Set matrix manipulated state.
//- Currently a no-op for pointPatchField.
void setManipulated(bool state) noexcept
{}
// Check
@ -263,9 +262,6 @@ public:
//- The value_type for the patch field
typedef Type value_type;
//- The component type for patch field
typedef typename pTraits<Type>::cmptType cmptType;
//- The internal field type associated with the patch field
typedef DimensionedField<Type, pointMesh> Internal;

View File

@ -37,6 +37,7 @@ License
#include "IOobject.H"
#include "dynamicCode.H"
#include "simpleObjectRegistry.H"
#include "MemoryPool.H"
#include "sigFpe.H"
#include "sigInt.H"
#include "sigQuit.H"
@ -2182,6 +2183,9 @@ void Foam::argList::parse
sigQuit::set(bannerEnabled());
sigSegv::set(bannerEnabled());
// Create memory pool (if any) after MPI has been setup
MemoryPool::create(bannerEnabled());
if (UPstream::master() && bannerEnabled())
{
Info<< "fileModificationChecking : "

View File

@ -71,21 +71,6 @@ Description
# define FOAM_LIKELY(cond) (cond)
#endif
// Shadow macro for __GNUC__, excluding compilers masquerading as gcc
#undef FOAM_REAL_GNUC
#if defined(__GNUC__) && !defined(__llvm__)
# define FOAM_REAL_GNUC __GNUC__
#endif
// Suppress false positives from -Wdangling-reference (gcc >= 14)
#if (FOAM_REAL_GNUC >= 14)
# define FOAM_NO_DANGLING_REFERENCE [[gnu::no_dangling]]
#endif
#ifndef FOAM_NO_DANGLING_REFERENCE
#define FOAM_NO_DANGLING_REFERENCE
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019-2025 OpenCFD Ltd.
Copyright (C) 2019-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -243,15 +243,7 @@ Foam::GAMGAgglomeration::GAMGAgglomeration
const dictionary& controlDict
)
:
MeshObject_type
(
controlDict.getOrDefault<word>
(
"name",
GAMGAgglomeration::typeName
),
mesh
),
MeshObject_type(mesh),
maxLevels_(50),
@ -316,17 +308,10 @@ const Foam::GAMGAgglomeration& Foam::GAMGAgglomeration::New
const dictionary& controlDict
)
{
const GAMGAgglomeration* agglomPtr =
mesh.thisDb().cfindObject<GAMGAgglomeration>
(
controlDict.getOrDefault<word>
(
"name",
GAMGAgglomeration::typeName
)
GAMGAgglomeration::typeName
);
if (agglomPtr)
@ -388,16 +373,12 @@ const Foam::GAMGAgglomeration& Foam::GAMGAgglomeration::New
const GAMGAgglomeration* agglomPtr =
mesh.thisDb().cfindObject<GAMGAgglomeration>
(
controlDict.getOrDefault<word>
(
"name",
GAMGAgglomeration::typeName
)
GAMGAgglomeration::typeName
);
if (agglomPtr)
{
if (agglomPtr->requireUpdate_ || agglomPtr->requiresUpdate())
if (agglomPtr->requireUpdate_)
{
mesh.thisDb().checkOut(const_cast<GAMGAgglomeration*>(agglomPtr));
return GAMGAgglomeration::New(matrix, controlDict);
@ -450,16 +431,12 @@ const Foam::GAMGAgglomeration& Foam::GAMGAgglomeration::New
const GAMGAgglomeration* agglomPtr =
mesh.thisDb().cfindObject<GAMGAgglomeration>
(
controlDict.getOrDefault<word>
(
"name",
GAMGAgglomeration::typeName
)
GAMGAgglomeration::typeName
);
if (agglomPtr)
{
if (agglomPtr->requireUpdate_ || agglomPtr->requiresUpdate())
if (agglomPtr->requireUpdate_)
{
mesh.thisDb().checkOut(const_cast<GAMGAgglomeration*>(agglomPtr));
return GAMGAgglomeration::New(mesh, controlDict);

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019-2025 OpenCFD Ltd.
Copyright (C) 2019-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -38,12 +38,8 @@ Description
// Whether to cache the agglomeration
cacheAgglomeration yes;
// Optionally update every updateInterval time steps. Default is 1.
// - only applies if cacheAgglomeration
// - applies also for static mesh cases
// Optionally update every updateInterval mesh motion. Default is 1.
updateInterval 10;
// Optional name (default is GAMGAgglomeration)
//name pAgglomeration;
// Optionally agglomerate coarsest-level across processors
processorAgglomerator masterCoarsest;
@ -192,7 +188,7 @@ protected:
// Protected Member Functions
//- Does the agglomeration need to be fully updated?
virtual bool requiresUpdate() const;
bool requiresUpdate() const;
//- Assemble coarse mesh addressing
void agglomerateLduAddressing(const label fineLevelIndex);

View File

@ -0,0 +1,116 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::MemoryPool
Description
Optional memory management using a memory pool such as Umpire
(https://github.com/LLNL/Umpire).
When compiled with Umpire, its use can be controlled by the
\c FOAM_MEMORY_POOL environment variable, or the
\c memory_pool Optimisation switch (etc/controlDict).
It currently looks for any of the following entries, in this order:
- true - same as \em "host"
- false/none - disabled.
- \em "host" - uses host memory pool
- \em "system" - same as \em "host"
- \em "device" - uses device memory pool
- \em "managed" - uses managed host/device memory pool
.
The parameters "size=nn" and "incr=nn" (in MegaBytes) can be used
to specify alternatives to the default sizing.
\*---------------------------------------------------------------------------*/
#ifndef Foam_MemoryPool_H
#define Foam_MemoryPool_H
#include <cstdint> // For size_t
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class MemoryPool Declaration
\*---------------------------------------------------------------------------*/
class MemoryPool
{
public:
// Constructors
//- Create a memory pool instance (if not already active).
// Uses environment or etc/controlDict entry
static bool create(bool verbose = false);
// Destructor
//- Remove the memory pool instance (currently does nothing)
static void destroy(bool verbose = false);
// Member Functions
//- True if pool is active (ie, created and not suspended)
static bool active() noexcept;
//- Suspend use of memory pool (for allocation).
// \return previous suspend status
static bool suspend() noexcept;
//- Resume use of memory pool (if previously active)
static void resume() noexcept;
//- Test if given pointer belongs to the pool
static bool is_pool(void *ptr);
//- Allocate from pool (if active).
// \returns nullptr if the pool is not active
static void* try_allocate(std::size_t nbytes);
//- Deallocate a pointer managed by the pool
// \returns True if a nullptr (no-op) or when the pointer was
// managed by the pool.
static bool try_deallocate(void *ptr);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2025 OpenCFD Ltd.
Copyright (C) 2018-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -168,12 +168,10 @@ public:
//- Get existing or create MeshObject registered with typeName
template<class... Args>
FOAM_NO_DANGLING_REFERENCE //< Reference stored in registry
static const Type& New(const Mesh& mesh, Args&&... args);
//- Get existing or create MeshObject with given registration name
template<class... Args>
FOAM_NO_DANGLING_REFERENCE //< Reference stored in registry
static const Type& New
(
const word& objName,
@ -322,7 +320,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "MeshObject.txx"
#include "MeshObject.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2018-2025 OpenCFD Ltd.
Copyright (C) 2018-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -89,11 +89,7 @@ void Foam::pointBoundaryMesh::calcGroupIDs() const
// Remove groups that clash with patch names
forAll(patches, patchi)
{
if (groupLookup.empty())
{
break; // Early termination
}
else if (groupLookup.erase(patches[patchi].name()))
if (groupLookup.erase(patches[patchi].name()))
{
WarningInFunction
<< "Removed group '" << patches[patchi].name()
@ -374,7 +370,7 @@ Foam::labelList Foam::pointBoundaryMesh::indices
// Only check groups if requested and they exist
const bool checkGroups = (useGroups && this->hasGroupIDs());
labelHashSet ids;
labelHashSet ids(0);
if (matcher.isPattern())
{
@ -385,7 +381,7 @@ Foam::labelList Foam::pointBoundaryMesh::indices
{
if (matcher(iter.key()))
{
// Add ids associated with the group
// Add patch ids associated with the group
ids.insert(iter.val());
}
}
@ -417,7 +413,7 @@ Foam::labelList Foam::pointBoundaryMesh::indices
if (iter.good())
{
// Add ids associated with the group
// Hash ids associated with the group
ids.insert(iter.val());
}
}
@ -442,7 +438,7 @@ Foam::labelList Foam::pointBoundaryMesh::indices
return this->indices(matcher.front(), useGroups);
}
labelHashSet ids;
labelHashSet ids(0);
// Only check groups if requested and they exist
if (useGroups && this->hasGroupIDs())
@ -454,7 +450,7 @@ Foam::labelList Foam::pointBoundaryMesh::indices
{
if (matcher(iter.key()))
{
// Add ids associated with the group
// Add patch ids associated with the group
ids.insert(iter.val());
}
}
@ -475,20 +471,20 @@ Foam::labelList Foam::pointBoundaryMesh::indices
Foam::labelList Foam::pointBoundaryMesh::indices
(
const wordRes& allow,
const wordRes& deny,
const wordRes& select,
const wordRes& ignore,
const bool useGroups
) const
{
if (allow.empty() && deny.empty())
//return mesh().boundaryMesh().indices(select, ignore, useGroups);
if (ignore.empty())
{
// Fast-path: select all
return identity(this->size());
return this->indices(select, useGroups);
}
const wordRes::filter matcher(allow, deny);
const wordRes::filter matcher(select, ignore);
labelHashSet ids;
labelHashSet ids(0);
// Only check groups if requested and they exist
if (useGroups && this->hasGroupIDs())
@ -500,7 +496,7 @@ Foam::labelList Foam::pointBoundaryMesh::indices
{
if (matcher(iter.key()))
{
// Add ids associated with the group
// Add patch ids associated with the group
ids.insert(iter.val());
}
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2013 OpenFOAM Foundation
Copyright (C) 2018-2025 OpenCFD Ltd.
Copyright (C) 2018-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -28,9 +28,7 @@ Class
Foam::pointBoundaryMesh
Description
A pointBoundaryMesh is a pointPatch list with registered IO,
a reference to the associated pointMesh,
with additional search methods etc.
Foam::pointBoundaryMesh
SourceFiles
pointBoundaryMesh.C
@ -104,10 +102,10 @@ public:
// Constructors
//- Construct from pointMesh and polyBoundaryMesh
//- Construct from polyBoundaryMesh
pointBoundaryMesh(const pointMesh&, const polyBoundaryMesh&);
//- Construct from IOobject, pointMesh and polyBoundaryMesh
//- Construct from IOobject and polyBoundaryMesh
pointBoundaryMesh
(
const IOobject& io,
@ -143,29 +141,24 @@ public:
//- Return a list of physical types
wordList physicalTypes() const;
//- The (sorted) patch indices for all matches,
//- optionally matching patch groups.
// \returns an empty list for an empty matcher
//- Return (sorted) patch indices for all matches.
// A no-op (returns empty list) for an empty matcher
labelList indices(const wordRe& matcher, const bool useGroups) const;
//- The (sorted) patch indices for all matches,
//- optionally matching patch groups.
// \returns an empty list for an empty matcher
//- Return (sorted) patch indices for all matches.
// A no-op (returns empty list) for an empty matcher
labelList indices(const wordRes& matcher, const bool useGroups) const;
//- The (sorted) patch indices: logic as per Foam::wordRes::filter,
//- optionally matching patch groups.
//
// An empty \em allow accepts everything not in \em deny.
// A literal \em allow match has higher priority than any \em deny.
// A regex \em allow match has lower priority than any \em deny.
//
// \returns identity list when allow/deny are both empty.
//- Return (sorted) patch indices for all selected matches that
//- are not ignored.
//- The selection logic as per Foam::wordRes::filter.
// Optionally matches patch groups.
// A no-op (returns empty list) for an empty select matcher
labelList indices
(
const wordRes& allow,
const wordRes& deny,
const bool useGroups //!< Match patch groups
const wordRes& select,
const wordRes& ignore,
const bool useGroups
) const;
//- Find patch index given a name

View File

@ -167,13 +167,13 @@ public:
}
//- Return processor number
int myProcNo() const noexcept
int myProcNo() const
{
return procPolyPatch_.myProcNo();
}
//- Return neighbour processor number
int neighbProcNo() const noexcept
int neighbProcNo() const
{
return procPolyPatch_.neighbProcNo();
}
@ -191,13 +191,13 @@ public:
}
//- Return the underlying processorPolyPatch
const processorPolyPatch& procPolyPatch() const noexcept
const processorPolyPatch& procPolyPatch() const
{
return procPolyPatch_;
}
//- Return mesh points in the correct order for the receiving side
const labelList& reverseMeshPoints() const noexcept
const labelList& reverseMeshPoints() const
{
return reverseMeshPoints_;
}

View File

@ -34,8 +34,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef Foam_wedgePointPatch_H
#define Foam_wedgePointPatch_H
#ifndef wedgePointPatch_H
#define wedgePointPatch_H
#include "facePointPatch.H"
#include "wedgePolyPatch.H"
@ -53,9 +53,9 @@ class wedgePointPatch
:
public facePointPatch
{
// Private Data
// Private data
//- Local reference cast into the wedgePolyPatch patch
//- Local reference cast into the symmetryPlane patch
const wedgePolyPatch& wedgePolyPatch_;
@ -120,8 +120,8 @@ public:
pointConstraint&
) const;
//- Return the normal to the patch
const vector& n() const noexcept
//- Return symmetry plane normal
const vector& n() const
{
return wedgePolyPatch_.n();
}

View File

@ -40,6 +40,96 @@ namespace Foam
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<>
void Foam::mapDistribute::transform::operator()
(
const vectorTensorTransform&,
const bool,
List<label>&
) const {}
template<>
void Foam::mapDistribute::transform::operator()
(
const coupledPolyPatch&,
UList<label>&
) const {}
template<>
void Foam::mapDistribute::transform::operator()
(
const coupledPolyPatch&,
Map<label>&
) const {}
template<>
void Foam::mapDistribute::transform::operator()
(
const coupledPolyPatch&,
EdgeMap<label>&
) const {}
template<>
void Foam::mapDistribute::transform::operator()
(
const vectorTensorTransform&,
const bool,
List<scalar>&
) const {}
template<>
void Foam::mapDistribute::transform::operator()
(
const coupledPolyPatch&,
UList<scalar>&
) const {}
template<>
void Foam::mapDistribute::transform::operator()
(
const coupledPolyPatch&,
Map<scalar>&
) const {}
template<>
void Foam::mapDistribute::transform::operator()
(
const coupledPolyPatch&,
EdgeMap<scalar>&
) const {}
template<>
void Foam::mapDistribute::transform::operator()
(
const vectorTensorTransform&,
const bool,
List<bool>&
) const {}
template<>
void Foam::mapDistribute::transform::operator()
(
const coupledPolyPatch&,
UList<bool>&
) const {}
template<>
void Foam::mapDistribute::transform::operator()
(
const coupledPolyPatch&,
Map<bool>&
) const {}
template<>
void Foam::mapDistribute::transform::operator()
(
const coupledPolyPatch&,
EdgeMap<bool>&
) const {}
void Foam::mapDistribute::printLayout(Ostream& os) const
{
mapDistributeBase::printLayout(os);

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2015-2025 OpenCFD Ltd.
Copyright (C) 2015-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -176,25 +176,25 @@ class mapDistribute
//- Helper function: copy transformElements without transformation
template<class T>
void applyDummyTransforms(UList<T>& field) const;
void applyDummyTransforms(List<T>& field) const;
template<class T, class TransformOp>
void applyTransforms
(
const globalIndexAndTransform& globalTransforms,
UList<T>& field,
List<T>& field,
const TransformOp& top
) const;
//- Helper function: copy transformElements without transformation
template<class T>
void applyDummyInverseTransforms(UList<T>& field) const;
void applyDummyInverseTransforms(List<T>& field) const;
template<class T, class TransformOp>
void applyInverseTransforms
(
const globalIndexAndTransform& globalTransforms,
UList<T>& field,
List<T>& field,
const TransformOp& top
) const;
@ -219,14 +219,11 @@ public:
(
const vectorTensorTransform& vt,
const bool forward,
UList<Type>& fld
List<Type>& fld
) const
{
if constexpr (is_rotational_vectorspace_v<Type>)
{
const tensor rot(forward ? vt.R() : vt.R().T());
transformList(rot, fld);
}
const tensor T(forward ? vt.R() : vt.R().T());
transformList(T, fld);
}
template<class Type>
@ -237,13 +234,9 @@ public:
List<List<Type>>& flds
) const
{
if constexpr (is_rotational_vectorspace_v<Type>)
for (List<Type>& fld : flds)
{
const tensor rot(forward ? vt.R() : vt.R().T());
for (auto& fld : flds)
{
transformList(rot, fld);
}
operator()(vt, forward, fld);
}
}
@ -251,12 +244,9 @@ public:
template<class Type>
void operator()(const coupledPolyPatch& cpp, UList<Type>& fld) const
{
if constexpr (is_rotational_vectorspace_v<Type>)
if (!cpp.parallel())
{
if (!cpp.parallel())
{
transformList(cpp.forwardT(), fld);
}
transformList(cpp.forwardT(), fld);
}
}
@ -265,12 +255,9 @@ public:
void operator()(const coupledPolyPatch& cpp, Container<Type>& map)
const
{
if constexpr (is_rotational_vectorspace_v<Type>)
if (!cpp.parallel())
{
if (!cpp.parallel())
{
transformList(cpp.forwardT(), map);
}
transformList(cpp.forwardT(), map);
}
}
};
@ -284,16 +271,17 @@ public:
(
const vectorTensorTransform& vt,
const bool forward,
UList<point>& fld
List<point>& fld
) const
{
pointField pfld(std::move(fld));
if (forward)
{
vt.transformPositionList(fld);
fld = vt.transformPosition(pfld);
}
else
{
vt.invTransformPositionList(fld);
fld = vt.invTransformPosition(pfld);
}
}
@ -304,19 +292,9 @@ public:
List<List<point>>& flds
) const
{
if (forward)
for (List<point>& fld : flds)
{
for (auto& fld : flds)
{
vt.transformPositionList(fld);
}
}
else
{
for (auto& fld : flds)
{
vt.invTransformPositionList(fld);
}
operator()(vt, forward, fld);
}
}
@ -704,6 +682,86 @@ public:
};
// Template specialisation for primitives that do not need transform
template<>
void mapDistribute::transform::operator()
(
const vectorTensorTransform&,
const bool,
List<label>&
) const;
template<>
void mapDistribute::transform::operator()
(
const coupledPolyPatch&,
UList<label>&
) const;
template<>
void mapDistribute::transform::operator()
(
const coupledPolyPatch&,
Map<label>&
) const;
template<>
void mapDistribute::transform::operator()
(
const coupledPolyPatch&,
EdgeMap<label>&
) const;
template<>
void mapDistribute::transform::operator()
(
const coupledPolyPatch&,
UList<scalar>&
) const;
template<>
void mapDistribute::transform::operator()
(
const vectorTensorTransform&,
const bool,
List<scalar>&
) const;
template<>
void mapDistribute::transform::operator()
(
const coupledPolyPatch&,
Map<scalar>&
) const;
template<>
void mapDistribute::transform::operator()
(
const coupledPolyPatch&,
EdgeMap<scalar>&
) const;
template<>
void mapDistribute::transform::operator()
(
const coupledPolyPatch& cpp,
UList<bool>& fld
) const;
template<>
void mapDistribute::transform::operator()
(
const vectorTensorTransform&,
const bool,
List<bool>&
) const;
template<>
void mapDistribute::transform::operator()
(
const coupledPolyPatch&,
Map<bool>&
) const;
template<>
void mapDistribute::transform::operator()
(
const coupledPolyPatch&,
EdgeMap<bool>&
) const;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -235,7 +235,7 @@ protected:
static void flipAndCombine
(
//! [in,out] The left of binary combine operation
UList<T>& lhs,
List<T>& lhs,
//! The right of binary combine operation
const UList<T>& rhs,
//! The mapping indices
@ -254,8 +254,8 @@ protected:
static void accessAndFlip
(
//! [out] The result values
UList<T>& output,
//! The input values
List<T>& output,
//! [out] The input values
const UList<T>& values,
//! The mapping indices
const labelUList& map,
@ -270,7 +270,7 @@ protected:
template<class T, class NegateOp>
static List<T> accessAndFlip
(
//! The input values
//! [out] The input values
const UList<T>& values,
//! The mapping indices
const labelUList& map,
@ -895,7 +895,7 @@ public:
static void distribute
(
const UPstream::commsTypes commsType,
const UList<labelPair>& schedule,
const List<labelPair>& schedule,
const label constructSize,
const labelListList& subMap,
const bool subHasFlip,
@ -918,7 +918,7 @@ public:
static void distribute
(
const UPstream::commsTypes commsType,
const UList<labelPair>& schedule,
const List<labelPair>& schedule,
const label constructSize,
const labelListList& subMap,
const bool subHasFlip,
@ -1078,7 +1078,7 @@ public:
//- Do all sends using PstreamBuffers
template<class T>
void send(PstreamBuffers& pBufs, const UList<T>& field) const;
void send(PstreamBuffers& pBufs, const List<T>& field) const;
//- Do all receives using PstreamBuffers
template<class T>

View File

@ -35,7 +35,7 @@ License
template<class T, class CombineOp, class NegateOp>
void Foam::mapDistributeBase::flipAndCombine
(
UList<T>& lhs,
List<T>& lhs,
const UList<T>& rhs,
const labelUList& map,
@ -46,9 +46,6 @@ void Foam::mapDistributeBase::flipAndCombine
{
const label len = map.size();
// FULLDEBUG: if (lhs.size() < max(map)) FatalError ...;
// FULLDEBUG: if (rhs.size() < len) FatalError ...;
if (hasFlip)
{
for (label i = 0; i < len; ++i)
@ -85,7 +82,7 @@ void Foam::mapDistributeBase::flipAndCombine
template<class T, class NegateOp>
void Foam::mapDistributeBase::accessAndFlip
(
UList<T>& output,
List<T>& output,
const UList<T>& values,
const labelUList& map,
const bool hasFlip,
@ -94,7 +91,6 @@ void Foam::mapDistributeBase::accessAndFlip
{
const label len = map.size();
// FULLDEBUG: if (values.size() < max(map)) FatalError ...;
// FULLDEBUG: if (output.size() < len) FatalError ...;
if (hasFlip)
@ -451,7 +447,7 @@ template<class T, class CombineOp, class NegateOp>
void Foam::mapDistributeBase::distribute
(
const UPstream::commsTypes commsType,
const UList<labelPair>& schedule,
const List<labelPair>& schedule,
const label constructSize,
const labelListList& subMap,
const bool subHasFlip,
@ -898,7 +894,7 @@ template<class T, class NegateOp>
void Foam::mapDistributeBase::distribute
(
const UPstream::commsTypes commsType,
const UList<labelPair>& schedule,
const List<labelPair>& schedule,
const label constructSize,
const labelListList& subMap,
const bool subHasFlip,
@ -1336,7 +1332,7 @@ template<class T>
void Foam::mapDistributeBase::send
(
PstreamBuffers& pBufs,
const UList<T>& field
const List<T>& field
) const
{
// Stream data into buffer
@ -1486,11 +1482,13 @@ void Foam::mapDistributeBase::distribute
const int tag
) const
{
List<T> work(std::move(values));
values.shrink();
distribute(commsType, work, tag);
List<T>& list = static_cast<List<T>&>(values);
values = std::move(work);
distribute(commsType, list, tag);
values.setCapacity(list.size());
}

View File

@ -35,7 +35,7 @@ License
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class T>
void Foam::mapDistribute::applyDummyTransforms(UList<T>& field) const
void Foam::mapDistribute::applyDummyTransforms(List<T>& field) const
{
forAll(transformElements_, trafoI)
{
@ -51,7 +51,7 @@ void Foam::mapDistribute::applyDummyTransforms(UList<T>& field) const
template<class T>
void Foam::mapDistribute::applyDummyInverseTransforms(UList<T>& field) const
void Foam::mapDistribute::applyDummyInverseTransforms(List<T>& field) const
{
forAll(transformElements_, trafoI)
{
@ -70,7 +70,7 @@ template<class T, class TransformOp> //, class CombineOp>
void Foam::mapDistribute::applyTransforms
(
const globalIndexAndTransform& globalTransforms,
UList<T>& field,
List<T>& field,
const TransformOp& top
) const
{
@ -100,7 +100,7 @@ template<class T, class TransformOp> //, class CombineOp>
void Foam::mapDistribute::applyInverseTransforms
(
const globalIndexAndTransform& globalTransforms,
UList<T>& field,
List<T>& field,
const TransformOp& top
) const
{
@ -193,11 +193,13 @@ void Foam::mapDistribute::distribute
const int tag
) const
{
List<T> work(std::move(fld));
fld.shrink();
distribute(commsType, work, dummyTransform, tag);
List<T>& list = static_cast<List<T>&>(fld);
fld = std::move(work);
distribute(commsType, list, dummyTransform, tag);
fld.setCapacity(list.size());
}

View File

@ -93,11 +93,7 @@ void Foam::polyBoundaryMesh::calcGroupIDs() const
// Remove groups that clash with patch names
forAll(patches, patchi)
{
if (groupLookup.empty())
{
break; // Early termination
}
else if (groupLookup.erase(patches[patchi].name()))
if (groupLookup.erase(patches[patchi].name()))
{
WarningInFunction
<< "Removed group '" << patches[patchi].name()
@ -786,7 +782,7 @@ Foam::labelList Foam::polyBoundaryMesh::indices
// Only check groups if requested and they exist
const bool checkGroups = (useGroups && this->hasGroupIDs());
labelHashSet ids;
labelHashSet ids(0);
if (matcher.isPattern())
{
@ -854,7 +850,7 @@ Foam::labelList Foam::polyBoundaryMesh::indices
return this->indices(matcher.front(), useGroups);
}
labelHashSet ids;
labelHashSet ids(0);
// Only check groups if requested and they exist
if (useGroups && this->hasGroupIDs())
@ -887,20 +883,19 @@ Foam::labelList Foam::polyBoundaryMesh::indices
Foam::labelList Foam::polyBoundaryMesh::indices
(
const wordRes& allow,
const wordRes& deny,
const wordRes& select,
const wordRes& ignore,
const bool useGroups
) const
{
if (allow.empty() && deny.empty())
if (ignore.empty())
{
// Fast-path: select all
return identity(this->size());
return this->indices(select, useGroups);
}
const wordRes::filter matcher(allow, deny);
const wordRes::filter matcher(select, ignore);
labelHashSet ids;
labelHashSet ids(0);
// Only check groups if requested and they exist
if (useGroups && this->hasGroupIDs())
@ -1074,7 +1069,7 @@ Foam::labelHashSet Foam::polyBoundaryMesh::patchSet
const bool useGroups
) const
{
labelHashSet ids;
labelHashSet ids(0);
if (select.empty())
{
return ids;

View File

@ -28,9 +28,8 @@ Class
Foam::polyBoundaryMesh
Description
A polyBoundaryMesh is a polyPatch list with registered IO,
a reference to the associated polyMesh,
with additional search methods etc.
A polyBoundaryMesh is a polyPatch list with additional search methods
and registered IO.
SourceFiles
polyBoundaryMesh.C
@ -260,37 +259,34 @@ public:
labelRange range(const label patchi) const;
//- The (sorted) patch indices for all matches,
//- optionally matching patch groups.
// \returns an empty list for an empty matcher
//- Return (sorted) patch indices for all matches.
// Optionally matches patch groups.
// A no-op (returns empty list) for an empty matcher
labelList indices
(
const wordRe& matcher,
const bool useGroups = true
) const;
//- The (sorted) patch indices for all matches,
//- optionally matching patch groups.
// \returns an empty list for an empty matcher
//- Return (sorted) patch indices for all matches.
// Optionally matches patch groups.
// A no-op (returns empty list) for an empty matcher
labelList indices
(
const wordRes& matcher,
const bool useGroups = true //!< Match patch groups
const bool useGroups = true
) const;
//- The (sorted) patch indices: logic as per Foam::wordRes::filter,
//- optionally matching patch groups.
//
// An empty \em allow accepts everything not in \em deny.
// A literal \em allow match has higher priority than any \em deny.
// A regex \em allow match has lower priority than any \em deny.
//
// \returns identity list when allow/deny are both empty.
//- Return (sorted) patch indices for all selected matches that
//- are not ignored.
//- The selection logic as per Foam::wordRes::filter.
// Optionally matches patch groups.
// A no-op (returns empty list) for an empty select matcher
labelList indices
(
const wordRes& allow,
const wordRes& deny,
const bool useGroups = true //!< Match patch groups
const wordRes& select,
const wordRes& ignore,
const bool useGroups = true
) const;
//- Return (sorted) patch indices for patches that match the

View File

@ -34,8 +34,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef Foam_wedgePolyPatch_H
#define Foam_wedgePolyPatch_H
#ifndef wedgePolyPatch_H
#define wedgePolyPatch_H
#include "polyPatch.H"
@ -52,7 +52,7 @@ class wedgePolyPatch
:
public polyPatch
{
// Private Data
// Private data
//- Axis of the wedge
vector axis_;
@ -173,27 +173,45 @@ public:
}
// Member Functions
// Member functions
// Access
// Access
//- Return axis of the wedge
const vector& axis() const noexcept { return axis_; }
//- Return axis of the wedge
const vector& axis() const
{
return axis_;
}
//- Return plane normal between the wedge boundaries
const vector& centreNormal() const noexcept { return centreNormal_; }
//- Return plane normal between the wedge boundaries
const vector& centreNormal() const
{
return centreNormal_;
}
//- Return the normal to the patch
const vector& n() const noexcept { return n_; }
//- Return the normal to the patch
const vector& n() const
{
return n_;
}
//- Return the cosine of the wedge angle
scalar cosAngle() const noexcept { return cosAngle_; }
//- Return the cosine of the wedge angle
scalar cosAngle() const
{
return cosAngle_;
}
//- Return face transformation tensor
const tensor& faceT() const noexcept { return faceT_; }
//- Return face transformation tensor
const tensor& faceT() const
{
return faceT_;
}
//- Return neighbour-cell transformation tensor
const tensor& cellT() const noexcept { return cellT_; }
//- Return neighbour-cell transformation tensor
const tensor& cellT() const
{
return cellT_;
}
};

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2020-2025 OpenCFD Ltd.
Copyright (C) 2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -47,27 +47,17 @@ namespace Foam
class dummyTransform
{
public:
template<class T>
void operator()
(
const vectorTensorTransform& vt,
const bool forward,
UList<T>& fld
) const
{}
template<class Type>
void operator()
(
const vectorTensorTransform& vt,
const bool forward,
List<List<Type>>& flds
List<T>& fld
) const
{}
template<class T>
void operator()(const coupledPolyPatch& cpp, UList<T>& fld) const
void operator()(const coupledPolyPatch& cpp, Field<T>& fld) const
{}
template<class T, template<class> class Container>

View File

@ -1135,7 +1135,11 @@ void Foam::syncTools::syncBoundaryFaceList
pp.start()-boundaryOffset
);
top(procPatch, recvFld);
auto& fakeList = const_cast<List<T>&>
(
static_cast<const List<T>&>(recvFld)
);
top(procPatch, fakeList);
SubList<T> patchValues
(

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016-2025 OpenCFD Ltd.
Copyright (C) 2016-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -205,11 +205,7 @@ void Foam::ZoneMesh<ZoneType, MeshType>::calcGroupIDs() const
// Remove groups that clash with zone names
forAll(zones, zonei)
{
if (groupLookup.empty())
{
break; // Early termination
}
else if (groupLookup.erase(zones[zonei].name()))
if (groupLookup.erase(zones[zonei].name()))
{
WarningInFunction
<< "Removed group '" << zones[zonei].name()
@ -545,7 +541,7 @@ Foam::labelList Foam::ZoneMesh<ZoneType, MeshType>::indices
// Only check groups if requested and they exist
const bool checkGroups = (useGroups && this->hasGroupIDs());
labelHashSet ids;
labelHashSet ids(0);
if (checkGroups)
{
@ -561,7 +557,7 @@ Foam::labelList Foam::ZoneMesh<ZoneType, MeshType>::indices
{
if (matcher(iter.key()))
{
// Add ids associated with the group
// Hash ids associated with the group
ids.insert(iter.val());
}
}
@ -593,7 +589,7 @@ Foam::labelList Foam::ZoneMesh<ZoneType, MeshType>::indices
if (iter.good())
{
// Add ids associated with the group
// Hash ids associated with the group
ids.insert(iter.val());
}
}
@ -619,7 +615,7 @@ Foam::labelList Foam::ZoneMesh<ZoneType, MeshType>::indices
return this->indices(matcher.front(), useGroups);
}
labelHashSet ids;
labelHashSet ids(0);
// Only check groups if requested and they exist
if (useGroups && this->hasGroupIDs())
@ -631,7 +627,7 @@ Foam::labelList Foam::ZoneMesh<ZoneType, MeshType>::indices
{
if (matcher(iter.key()))
{
// Add ids associated with the group
// Hash the ids associated with the group
ids.insert(iter.val());
}
}
@ -653,20 +649,19 @@ Foam::labelList Foam::ZoneMesh<ZoneType, MeshType>::indices
template<class ZoneType, class MeshType>
Foam::labelList Foam::ZoneMesh<ZoneType, MeshType>::indices
(
const wordRes& allow,
const wordRes& deny,
const wordRes& select,
const wordRes& ignore,
const bool useGroups
) const
{
if (allow.empty() && deny.empty())
if (ignore.empty())
{
// Fast-path: select all
return identity(this->size());
return this->indices(select, useGroups);
}
const wordRes::filter matcher(allow, deny);
const wordRes::filter matcher(select, ignore);
labelHashSet ids;
labelHashSet ids(0);
// Only check groups if requested and they exist
if (useGroups && this->hasGroupIDs())
@ -678,7 +673,7 @@ Foam::labelList Foam::ZoneMesh<ZoneType, MeshType>::indices
{
if (matcher(iter.key()))
{
// Add ids associated with the group
// Add patch ids associated with the group
ids.insert(iter.val());
}
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016-2025 OpenCFD Ltd.
Copyright (C) 2016-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -227,37 +227,34 @@ public:
wordList sortedNames(const wordRes& matcher) const;
//- The (sorted) patch indices for all matches,
//- optionally matching zone groups.
// \returns an empty list for an empty matcher
//- Return (sorted) zone indices for all matches
// Optionally matches zone groups.
// A no-op (returns empty list) for an empty matcher
labelList indices
(
const wordRe& matcher,
const bool useGroups = true
) const;
//- The (sorted) patch indices for all matches,
//- optionally matching zone groups.
// \returns an empty list for an empty matcher
//- Return (sorted) zone indices for all matches
// Optionally matches zone groups.
// A no-op (returns empty list) for an empty matcher
labelList indices
(
const wordRes& matcher,
const bool useGroups = true
) const;
//- The (sorted) patch indices: logic as per Foam::wordRes::filter,
//- optionally matching zone groups.
//
// An empty \em allow accepts everything not in \em deny.
// A literal \em allow match has higher priority than any \em deny.
// A regex \em allow match has lower priority than any \em deny.
//
// \returns identity list when allow/deny are both empty.
//- Return (sorted) zone indices for all selected matches that
//- are not ignored.
//- The selection logic as per Foam::wordRes::filter.
// Optionally matches patch groups.
// A no-op (returns empty list) for an empty select matcher
labelList indices
(
const wordRes& allow,
const wordRes& deny,
const bool useGroups = true //!< Match zone groups
const wordRes& select,
const wordRes& ignore,
const bool useGroups = true
) const;
//- Zone index for the first match, return -1 if not found

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019-2025 OpenCFD Ltd.
Copyright (C) 2019-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -92,7 +92,7 @@ public:
// Constructors
//- Construct initialized to zero
inline DiagTensor(Foam::zero);
inline DiagTensor(const Foam::zero);
//- Construct given VectorSpace
template<class Cmpt2>
@ -123,9 +123,6 @@ public:
// Diagonal access and manipulation
//- Extract the diagonal as a vector
inline Vector<Cmpt> diag() const;
//- The L2-norm squared of the diagonal
inline scalar diagSqr() const;
};

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2020-2025 OpenCFD Ltd.
Copyright (C) 2020-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -32,9 +32,9 @@ License
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Cmpt>
inline Foam::DiagTensor<Cmpt>::DiagTensor(Foam::zero)
inline Foam::DiagTensor<Cmpt>::DiagTensor(const Foam::zero)
:
VectorSpace<DiagTensor<Cmpt>, Cmpt, 3>(Foam::zero{})
VectorSpace<DiagTensor<Cmpt>, Cmpt, 3>(Zero)
{}
@ -81,13 +81,6 @@ inline Foam::DiagTensor<Cmpt>::DiagTensor(Istream& is)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Cmpt>
inline Foam::Vector<Cmpt> Foam::DiagTensor<Cmpt>::diag() const
{
return Vector<Cmpt>(this->xx(), this->yy(), this->zz());
}
template<class Cmpt>
inline Foam::scalar Foam::DiagTensor<Cmpt>::diagSqr() const
{

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019-2025 OpenCFD Ltd.
Copyright (C) 2019-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -94,7 +94,7 @@ public:
// Constructors
//- Construct initialized to zero
inline SymmTensor(Foam::zero);
inline SymmTensor(const Foam::zero);
//- Construct given VectorSpace of the same rank
template<class Cmpt2>
@ -234,12 +234,6 @@ public:
inline scalar diagSqr() const;
// Characteristics
//- Is identity tensor?
inline bool is_identity(const scalar tol = ROOTVSMALL) const;
// Tensor Operations
//- Return non-Hermitian transpose

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019-2025 OpenCFD Ltd.
Copyright (C) 2019-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -31,9 +31,9 @@ License
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Cmpt>
inline Foam::SymmTensor<Cmpt>::SymmTensor(Foam::zero)
inline Foam::SymmTensor<Cmpt>::SymmTensor(const Foam::zero)
:
SymmTensor::vsType(Foam::zero{})
SymmTensor::vsType(Zero)
{}
@ -238,21 +238,6 @@ inline Foam::scalar Foam::SymmTensor<Cmpt>::diagSqr() const
}
template<class Cmpt>
inline bool Foam::SymmTensor<Cmpt>::is_identity(const scalar tol) const
{
return
(
Foam::mag(xx() - pTraits<Cmpt>::one) < tol
&& Foam::mag(yy() - pTraits<Cmpt>::one) < tol
&& Foam::mag(zz() - pTraits<Cmpt>::one) < tol
&& Foam::mag(xy()) < tol
&& Foam::mag(xz()) < tol
&& Foam::mag(yz()) < tol
);
}
template<class Cmpt>
inline Cmpt Foam::SymmTensor<Cmpt>::det() const
{

View File

@ -410,12 +410,12 @@ inline bool Foam::Tensor<Cmpt>::is_identity(const scalar tol) const
{
return
(
Foam::mag(xx() - pTraits<Cmpt>::one) < tol
&& Foam::mag(yy() - pTraits<Cmpt>::one) < tol
&& Foam::mag(zz() - pTraits<Cmpt>::one) < tol
&& Foam::mag(xy()) < tol && Foam::mag(xz()) < tol
&& Foam::mag(yx()) < tol && Foam::mag(yz()) < tol
&& Foam::mag(zx()) < tol && Foam::mag(zy()) < tol
mag(xx() - pTraits<Cmpt>::one) < tol
&& mag(yy() - pTraits<Cmpt>::one) < tol
&& mag(zz() - pTraits<Cmpt>::one) < tol
&& mag(xy()) < tol && mag(xz()) < tol
&& mag(yx()) < tol && mag(yz()) < tol
&& mag(zx()) < tol && mag(zy()) < tol
);
}

View File

@ -6,7 +6,6 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -61,13 +60,6 @@ Foam::vectorTensorTransform::vectorTensorTransform(Istream& is)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::vectorTensorTransform::checkRotation(const scalar tol)
{
// Detect identity and zero rotations
hasR_ = !(R_.is_identity(tol) || Foam::mag(R_) < tol);
}
Foam::word Foam::name(const vectorTensorTransform& s)
{
OStringStream buf;
@ -78,6 +70,32 @@ Foam::word Foam::name(const vectorTensorTransform& s)
}
template<>
Foam::tmp<Foam::Field<bool>> Foam::vectorTensorTransform::transform
(
const Field<bool>& fld
) const
{
return fld;
}
template<>
Foam::tmp<Foam::Field<Foam::label>> Foam::vectorTensorTransform::transform
(
const Field<label>& fld
) const
{
return fld;
}
template<>
Foam::tmp<Foam::Field<Foam::scalar>> Foam::vectorTensorTransform::transform
(
const Field<scalar>& fld
) const
{
return fld;
}
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
Foam::Istream& Foam::operator>>(Istream& is, vectorTensorTransform& tr)

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