Compare commits

..

34 Commits

Author SHA1 Message Date
d6cc79fe76 FIX: incorrect DynamicList resizing logic (memory pool)
- reserve() did not set the addressable size to the current capacity
  before resizing, which meant that the delete[] would not have the true
  allocated size.
  Only affected memory-pool usage, which was not yet integrated
  (#3381)

ENH: remove unused DynamicList '*_unsafe()' methods

- could result in a mismatch between allocated and addressed sizes,
  which becomes important for memory-pool usage.
2025-06-23 11:08:46 +02:00
9dee2cad3e ENH: integrate memory pool support for List allocations (#3381)
- 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-06-23 11:08:38 +02:00
23adebdb86 FIX: missing specialisations for transformF[av]PatchField
- fix for 25139e492e
2025-06-18 11:07:28 +01:00
2b0e4dc97a ENH: potentialFoam: allow swirl bc. See #3211
Bypasses the constraint override. Contentious -
does field algebra or boundary constraints take
priority.
2025-06-16 17:13:31 +01:00
e803646228 Merge branch 'consistent-handling-of-filtered-names' into 'develop'
consistent handling of filtered patch/zone names. More inGroups handling for utilities etc.

See merge request Development/openfoam!748
2025-06-13 14:17:48 +01:00
be278abcc0 ENH: revise patch group selection to ensightMesh
- supports inGroup while also respecting allow/deny semantics

- support inGroup for cellZone/faceZone selection
2025-06-13 10:29:32 +02:00
93f980834b ENH: support patch group selection
- vtkWrite, foamToVTK, surfaceMeshExtract
2025-06-13 10:29:32 +02:00
e8dce32b0a ENH: consistent handling of filtered patch/zone names
- the indices(const wordRes& allow, const wordRes& deny) methods
  were not defined consistently with the wordRes::filter handling.

  wordRes::filter - allow/deny both empty:
      = no filtering (ie, accept everything)

  indices(allow,deny) - allow/deny both empty:
     = return identity list (NEW behaviour)
     = return empty list (OLD behaviour)

  Consider the old behaviour a minor bug since the limited number of
  callers had their own checks that avoided the poor behaviour.

  Example of the inconsistent behaviour:

     pbm.indices(wordRes(), wordRes({"non-existent"}))
        --> identity list (old, new behaviour)

     pbm.indices(wordRes(), wordRes())
         --> identity list (new behaviour)
         --> empty list    (old behaviour)
2025-06-13 09:15:58 +02:00
91925871d9 Merge branch 'fix-3374-questionable-const_cast' into 'develop'
avoid casting workarounds for syncTools::syncBoundaryFaceList

See merge request Development/openfoam!747
2025-06-12 12:49:26 +00:00
a5090c37a3 ENH: minor improvements to UPstream::communicator wrapper class
- robuster reset() method that handles self-assignment
- additional swap() and constCast() methods

STYLE: relocate UPstream::communicator declarations within header
2025-06-12 13:13:26 +02:00
0d7816b7fd ENH: avoid questionable const_cast of SubList (#3374) 2025-06-12 13:13:26 +02:00
9bdb75eeef ENH: add ListOps::equal() function
- tests for list equality with different but compatible data types.
  Eg, when comparing lists of int32 and int64 values.

STYLE: pass UList instead of List references into ListOps functors
2025-06-12 13:13:26 +02:00
a860d48637 ENH: make some vectorTensorTransform methods inplace
- avoids intermediate allocation and re-assignment to self (#3374)

BUG: checkMesh (application) with questionable memory handling (#3374)

- move the contents of the new points instead of attempting to transfer
  the entire list

COMP: replace mapDistribute specializations with if constexpr handling

- simplify future maintenance
2025-06-12 13:13:26 +02:00
97296043c0 ENH: snappyHexMesh: more warnings. See #3377
This one only tackles the per-region for refinementSurfaces.
Other ones tbd.
2025-06-12 10:10:16 +01:00
6bdceaf29f BUG: AMI: local communicators. Fixes #3376 2025-06-11 16:39:48 +01:00
34df4eaf40 ENH: ensightWrite: allow inGroup names in patches and excludePatches 2025-06-11 13:36:14 +01:00
75b2d0b656 BUG: masterStream forwards without communicator (fixes #3373)
- in messageStream::masterStream(int), it forwarded to stream()
  without the communicator, which meant it would incorrectly check
  UPstream::master(worldComm) and possibly not produce any output (or
  block).
2025-06-10 15:20:11 +02:00
9bc6f2f91f ENH: support 'rpm' input for propeller functionObject (as per rotorDisk)
- update code style for forces/propeller.
- simplify coordinate handling in propeller functionObject
2025-06-10 10:32:03 +02:00
96872f031f Merge branch 'feature-orientedSurface' into 'develop'
ENH: snappyHexMesh: work better on non-manifold. Fixes ##3361

See merge request Development/openfoam!740
2025-06-09 15:12:47 +00:00
55d89ac4d6 ENH: snappyHexMesh: work better on non-manifold. Fixes ##3361 2025-06-09 15:12:47 +00:00
fe0ba07a7a SUBMODULE: update OpenQBMM for v2506 2025-06-05 16:06:56 +02:00
164a3e8330 ENH: IOstream::unsetf() now returns old flags (eg, for toggling)
ENH: align MPI_Probe non-blocking handling with header description

- the header states that the commsType is non-blocking or not,
  but the implementation actually checked for 'buffered' or not.

STYLE: fix some spacing and some documentation
2025-06-05 16:06:56 +02:00
2f6581133c ENH: preserve matrix manipulation state in boundary consistency check
- add placeholder methods in faPatchField and move setter functions
  from protected to public access.
2025-06-05 15:09:25 +02:00
9e8e14e448 TUT: minor tutorial cleanup
- use functionObject writeInterval not timeInterval.
  No change in behaviour since the missing writeInterval is treated
  as '1' anyhow when using 'timeStep' for the writeControl

- consistent use of 'adjustable' vs 'adjustableRunTime'

- prefer '#eval{ vector(...) }' to calling '#eval' multiple times
2025-06-04 16:39:34 +02:00
ffea136955 BUG: correct constant definition in sigma LES model (fixes #3371) 2025-06-03 20:04:17 +01:00
5dbc2e5890 Merge branch 'patch_specializations' into 'develop'
Simplify specialization of patch fields, consolidate boundary evaluation

See merge request Development/openfoam!743
2025-05-29 11:20:25 +00:00
1be6991d3f CONFIG: set API level to 2502
- changes in patchField signatures
2025-05-28 17:50:55 +02:00
25139e492e ENH: replace patchField specializations with if constexpr
- simplifies future code changes

STYLE: noexcept access for wedgePatch methods
2025-05-28 17:50:55 +02:00
0189311026 ENH: avoid unneeded transform operations for scalar pointField BCs 2025-05-28 17:50:55 +02:00
d6e6450834 ENH: add missing construct GeometricField from primitive field (tmp)
ENH: improvements for GeometricBoundaryField evaluation

- early termination from evaluate_if() and evaluateCoupled().

- evaluateCoupled() now forwards to evaluate_if() and receives
  additional handling for a 'void' parameter type.

BREAKING: extra template parameter for overset correctBoundaryCondition

- the true/false flag as a template parameter instead of as an
  argument to use 'if constexpr' code
2025-05-28 17:50:55 +02:00
1d6c77f8f4 ENH: complement lookupPatchField with cfindPatchField
- encapsulates (foundObject && lookupPatchField) together,
  similar to cfindObject

STYLE: remove unnecessary dummy parameters from lookupPatchField

- these were a workaround for a very old gcc bug and are no longer
  needed. However, retain the (unneeded) second template parameter to
  continue with not breaking existing old code - it has no overhead.
2025-05-28 14:42:27 +02:00
83e73e4024 BREAKING: change in signature for {fa,fv}PatchField::patchInternalField()
Signature:

    void patchInternalField(UList<Type>& pfld) const;
    // OLD: void patchInternalField(Field<Type>& pfld) const;

    This change is necessary to allow collection into slices of a
    larger list.

ENH: add {fa,fv}PatchField::patchNeighbourField(UList<Type>&)

- a retrieval version similar to patchInternalField(...)

STYLE: adjust AMI patch field private method names

- rename private method

      patchNeighbourField(...) -> getNeighbourField(...)

  to avoid access clashes with public methods

- remove undefined method neighbourSideField()
2025-05-28 14:42:18 +02:00
8d9f4c54f3 COMP: suppress false positives from -Wdangling-reference (gcc)
- the number of false positives has reduced, but in a few remaining
  cases, the compiler cannot possibly "know" that the pointer stored
  on the registry will outlive the scope of the method (for example)

  gcc-13: suppressing these spurious warnings needs to be done at each
  caller, which is simply not worth it, since later compiler versions
  provide a cleaner solution.

  gcc-14: the [[gnu::no_dangling]] attribute on the declaration
  lets the compiler know the intent.

- additional FOAM_REAL_GNUC macro (defined in stdFoam.H) to define
  the "real" gcc version and ignoring other compilers masquerading
  as gcc.

COMP: rename MeshObject code to {cxx,txx}

- avoids issues on case-insensitive filesystems (#3316)
2025-05-27 18:25:58 +02:00
f7c8bfdce0 STYLE: retrieve tensor diagonal directly instead of via diagTensor 2025-05-27 11:09:27 +02:00
252 changed files with 3279 additions and 2830 deletions

View File

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

View File

@ -13,7 +13,14 @@ volVectorField U
);
// Initialise the velocity internal field to zero
U = dimensionedVector(U.dimensions(), 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();
}
surfaceScalarField phi
(

View File

@ -51,6 +51,7 @@ See also
#include "IndirectList.H"
#include "SubList.H"
#include "SliceList.H"
#include "SubField.H"
#include "ListPolicy.H"
#include <list>
@ -203,16 +204,6 @@ int main(int argc, char *argv[])
Info<<" " << *iter;
}
Info<< nl;
Info<< "data:" << Foam::name(ident.cdata())
<< " size:" << ident.size() << nl;
Info<< "resize_unsafe(10)" << nl;
ident.resize_unsafe(10);
Info<< "data:" << Foam::name(ident.cdata())
<< " size:" << ident.size() << nl;
}
if (false)
@ -281,6 +272,33 @@ 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.C
Test-parallel-broadcast.cxx
EXE = $(FOAM_USER_APPBIN)/Test-parallel-broadcast

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -131,7 +131,6 @@ 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);
@ -164,8 +163,7 @@ int main(int argc, char *argv[])
scalarField fld(is);
Info<< "from [" << probed.first
<< "] : " << flatOutput(fld) << endl;
Info<< "from [" << proci << "] : " << flatOutput(fld) << endl;
}
}

View File

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

View File

@ -1,3 +1,3 @@
Test-parallel-waitSome.C
Test-parallel-waitSome.cxx
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: v2412 |
| \\ / O peration | Version: v2506 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
@ -26,7 +26,7 @@ stopAt writeNow;
endTime 4;
writeControl adjustableRunTime;
writeControl adjustable;
writeInterval 0.1;

View File

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

View File

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

View File

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

View File

@ -210,6 +210,7 @@ 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-2023 OpenCFD Ltd.
Copyright (C) 2021-2025 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 && !fieldSelector().empty())
if (fieldSelector)
{
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-2022 OpenCFD Ltd.
Copyright (C) 2016-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -406,34 +406,27 @@ 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 if (doConvertFields)
else
{
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-2023 OpenCFD Ltd.
Copyright (C) 2018-2025 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 = getSelectedPatches(patches, patchSelector);
patchIds = patchSelector.indices(patches);
}
if (oneBoundary && patchIds.size())

View File

@ -166,56 +166,54 @@ Note
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
labelList getSelectedPatches
(
const polyBoundaryMesh& patches,
const autoPtr<wordRes::filter>& patchSelector
)
namespace Foam
{
labelList indices;
if (patchSelector && !patchSelector().empty())
// Simple wrapper for polyBoundaryMesh::indices() with some additional logic
struct polyBoundaryPatchSelector
{
wordRes allow_;
wordRes deny_;
void clear()
{
// Name-based selection
indices =
(
stringListOps::findMatching
(
patches,
patchSelector(),
nameOp<polyPatch>()
)
);
}
else
{
indices = identity(patches.size());
allow_.clear();
deny_.clear();
}
// Remove undesirable patches
label count = 0;
for (const label patchi : indices)
//- Forward to polyBoundaryMesh::indices() with additional handling.
// Prune emptyPolyPatch (always) and processorPolyPatch (in parallel)
labelList indices(const polyBoundaryMesh& pbm) const
{
const polyPatch& pp = patches[patchi];
labelList ids = pbm.indices(allow_, deny_);
if (isType<emptyPolyPatch>(pp))
const bool excludeProcPatches = UPstream::parRun();
// Prune undesirable patches
label count = 0;
for (const label patchi : ids)
{
continue;
}
else if (UPstream::parRun() && bool(isA<processorPolyPatch>(pp)))
{
break; // No processor patches for parallel output
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;
}
indices[count] = patchi;
++count;
ids.resize(count);
return ids;
}
};
indices.resize(count);
return indices;
}
} // End namespace Foam
//
@ -552,45 +550,38 @@ int main(int argc, char *argv[])
}
// Patch selection/deselection
wordRes includedPatches, excludedPatches;
autoPtr<wordRes::filter> patchSelector(nullptr);
polyBoundaryPatchSelector patchSelector;
if (doBoundary)
{
bool resetFilter = false;
if (args.readListIfPresent<wordRe>("patches", includedPatches))
if
(
auto& slot = patchSelector.allow_;
args.readListIfPresent<wordRe>("patches", slot)
)
{
resetFilter = true;
Info<< "Including patches "
<< flatOutput(includedPatches) << nl << endl;
Info<< "Including patches " << flatOutput(slot) << nl << endl;
}
if (args.readListIfPresent<wordRe>("exclude-patches", excludedPatches))
if
(
auto& slot = patchSelector.deny_;
args.readListIfPresent<wordRe>("exclude-patches", slot)
)
{
resetFilter = true;
Info<< "Excluding patches "
<< flatOutput(excludedPatches) << nl << endl;
}
if (resetFilter)
{
patchSelector =
autoPtr<wordRes::filter>::New(includedPatches, excludedPatches);
Info<< "Excluding patches " << flatOutput(slot) << nl << endl;
}
}
// 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)
@ -603,22 +594,22 @@ int main(int argc, char *argv[])
}
if (args.readListIfPresent<wordRe>("exclude-fields", excludedFields))
{
resetFilter = true;
Info<< "Excluding fields "
<< flatOutput(excludedFields) << nl << endl;
}
if (resetFilter && doConvertFields)
if (!doConvertFields)
{
fieldSelector =
autoPtr<wordRes::filter>::New(includedFields, excludedFields);
includedFields.clear();
excludedFields.clear();
}
}
else if (doConvertFields)
else
{
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));
@ -799,10 +790,10 @@ int main(int argc, char *argv[])
IOobjectOption::NO_REGISTER
);
if (fieldSelector && !fieldSelector().empty())
if (fieldSelector)
{
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-2023 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -39,74 +39,23 @@ namespace Foam
{
template<class Type>
void evaluateConstraintTypes(GeometricField<Type, fvPatchField, volMesh>& fld)
void evaluateConstraintTypes
(
GeometricField<Type, fvPatchField, volMesh>& fld
)
{
auto& bfld = fld.boundaryFieldRef();
const UPstream::commsTypes commsType = UPstream::defaultCommsType;
if
fld.boundaryFieldRef().evaluate_if
(
commsType == UPstream::commsTypes::buffered
|| commsType == UPstream::commsTypes::nonBlocking
)
{
const label startOfRequests = UPstream::nRequests();
for (auto& pfld : bfld)
[](const auto& pfld) -> bool
{
if
return
(
pfld.type() == pfld.patch().patch().type()
&& polyPatch::constraintType(pfld.patch().patch().type())
)
{
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);
}
}
}
}
);
},
UPstream::defaultCommsType
);
}

View File

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

View File

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

View File

@ -203,7 +203,7 @@ public:
//- Change the value for the list capacity directly (ADVANCED, UNSAFE)
//- Does not perform any memory management or resizing.
void setCapacity_unsafe(const label len) noexcept { capacity_ = len; }
void setCapacity_unsafe(label len) noexcept { capacity_ = len; }
//- Reserve allocation space for at least this size, allocating new
//- space if required and \em retaining old content.
@ -251,11 +251,6 @@ public:
//- Shrink the allocated space to the number of elements used.
inline void shrink_to_fit();
//- Shrink the internal bookkeeping of the allocated space to the
//- number of addressed elements without affecting allocation.
// \note when empty() it will delete any allocated memory.
inline void shrink_unsafe();
// Edit

View File

@ -68,7 +68,9 @@ inline void Foam::DynamicList<T, SizeMin>::doCapacity
// Addressable length, possibly truncated by new capacity
const label currLen = Foam::min(List<T>::size(), newCapacity);
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
if (nocopy)
{
List<T>::resize_nocopy(newCapacity);
@ -95,6 +97,9 @@ inline void Foam::DynamicList<T, SizeMin>::doReserve
// Preserve addressed size
const label currLen = List<T>::size();
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
// Increase capacity (eg, doubling)
capacity_ =
Foam::ListPolicy::reserve_size<SizeMin, 2>(len, capacity_);
@ -105,8 +110,10 @@ inline void Foam::DynamicList<T, SizeMin>::doReserve
}
else
{
List<T>::resize(capacity_);
List<T>::resize_copy(currLen, capacity_);
}
capacity_ = List<T>::size();
List<T>::setAddressableSize(currLen);
}
}
@ -271,7 +278,7 @@ inline Foam::DynamicList<T, SizeMin>::DynamicList
List<T>(std::move(static_cast<List<T>&>(list))),
capacity_(list.capacity())
{
list.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
list.setCapacity_unsafe(0); // All contents moved
}
@ -285,7 +292,7 @@ inline Foam::DynamicList<T, SizeMin>::DynamicList
List<T>(std::move(static_cast<List<T>&>(list))),
capacity_(list.capacity())
{
list.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
list.setCapacity_unsafe(0); // All contents moved
}
@ -361,8 +368,15 @@ inline void Foam::DynamicList<T, SizeMin>::reserve_exact
// Preserve addressed size
const label currLen = List<T>::size();
capacity_ = len;
List<T>::resize(capacity_);
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
// if (!nocopy)
{
List<T>::resize_copy(currLen, len);
}
capacity_ = List<T>::size();
List<T>::setAddressableSize(currLen);
}
}
@ -449,18 +463,6 @@ inline void Foam::DynamicList<T, SizeMin>::shrink_to_fit()
}
template<class T, int SizeMin>
inline void Foam::DynamicList<T, SizeMin>::shrink_unsafe()
{
if (List<T>::empty())
{
// Delete storage if empty
List<T>::clear();
}
capacity_ = List<T>::size();
}
template<class T, int SizeMin>
inline void
Foam::DynamicList<T, SizeMin>::swap(List<T>& list)

View File

@ -236,13 +236,6 @@ public:
// Otherwise the contents will be uninitialized.
inline void resize_nocopy(const label len);
//- Change the addressed list size directly without affecting
//- any memory management (advanced usage).
//
// It is left to the caller to avoid \em unsafe lengthening beyond
// the allocated memory region.
inline void resize_unsafe(const label len) noexcept;
//- Alias for resize()
void setSize(const label n) { this->resize(n); }

View File

@ -178,13 +178,6 @@ inline void Foam::List<T>::resize_nocopy(const label len)
}
template<class T>
inline void Foam::List<T>::resize_unsafe(const label len) noexcept
{
UList<T>::setAddressableSize(len);
}
template<class T>
inline T& Foam::List<T>::newElmt(const label i)
{

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2018-2024 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -28,8 +28,6 @@ License
#include "ListOps.H"
#include "CompactListList.H"
#include "HashSet.H"
#include <numeric>
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
@ -115,7 +113,8 @@ Foam::Map<Foam::label> Foam::invertToMap(const labelUList& values)
{
const label len = values.size();
Map<label> inverse(2*len);
Map<label> inverse;
inverse.reserve(len);
for (label i = 0 ; i < len; ++i)
{
@ -280,13 +279,14 @@ void Foam::inplaceReorder
void Foam::ListOps::unionEqOp::operator()
(
labelList& x,
const labelList& y
const labelUList& 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-2024 OpenCFD Ltd.
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -485,7 +485,6 @@ 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
@ -508,7 +507,7 @@ label findSortedIndex
// <code> lessOp<T>(list[i], val) </code> for the test.
//
// \tparam ListType The input list type
// \tparam T The value type (is often the same as ListType::value_type)
// \tparam T The value type (usually the same as ListType::value_type)
// \tparam ComparePredicate The type of the comparison functor that
// returns true for sorting below.
//
@ -585,23 +584,33 @@ namespace ListOps
template<class T>
struct appendEqOp
{
void operator()(List<T>& x, const List<T>& y) const;
void operator()(List<T>& x, const UList<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 List<T>& y) const;
void operator()(List<T>& x, const UList<T>& y) const;
};
//- List helper to add y unique elements to x
struct unionEqOp
{
void operator()(labelList& x, const labelList& y) const;
void operator()(labelList& x, const labelUList& 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 List<T>& y
const UList<T>& y
) const
{
if (y.size())
@ -1102,7 +1102,7 @@ template<class T>
void Foam::ListOps::uniqueEqOp<T>::operator()
(
List<T>& x,
const List<T>& y
const UList<T>& y
) const
{
if (y.size())
@ -1111,6 +1111,7 @@ void Foam::ListOps::uniqueEqOp<T>::operator()
{
for (const T& val : y)
{
// Not very efficient
x.push_uniq(val);
}
}
@ -1122,6 +1123,37 @@ 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

@ -112,23 +112,26 @@ public:
//- Change the value for the list capacity directly (ADVANCED, UNSAFE)
//- Does not perform any memory management or resizing.
void setCapacity_unsafe(const label len) noexcept { capacity_ = len; }
void setCapacity_unsafe(label len) noexcept { capacity_ = len; }
//- Reserve allocation space for at least this size.
// New entries are initialized to nullptr.
inline void reserve(const label len);
//- Reserve allocation space for at least this size.
//- If allocation is required, uses the specified size
//- without any other resizing logic.
// New entries are initialized to nullptr.
inline void reserve_exact(const label len);
//- Alter the addressed list size.
inline void resize(const label newLen);
// New entries are initialized to nullptr.
inline void resize(const label len);
//- Set the addressed list to the given size,
//- deleting all existing entries.
//- Afterwards the list contains all \c nullptr entries.
inline void resize_null(const label newLen);
inline void resize_null(const label len);
//- Clear the addressed list, i.e. set the size to zero.
// Allocated size does not change
@ -140,11 +143,6 @@ public:
//- Shrink the allocated space to the number of elements used.
inline void shrink_to_fit();
//- Shrink the internal bookkeeping of the allocated space to the
//- number of addressed elements without affecting allocation.
// \note when empty() it will delete any allocated memory.
inline void shrink_unsafe();
//- Alias for shrink_to_fit()
void shrink() { this->shrink_to_fit(); }

View File

@ -82,10 +82,7 @@ inline Foam::PtrDynList<T, SizeMin>::PtrDynList
PtrList<T>(std::move(list)),
capacity_(list.capacity())
{
// FUTURE:
// list.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
list.clearStorage(); // capacity=0 etc.
list.setCapacity_unsafe(0); // All contents moved
}
@ -99,10 +96,7 @@ inline Foam::PtrDynList<T, SizeMin>::PtrDynList
PtrList<T>(std::move(list)),
capacity_(list.capacity())
{
// FUTURE:
// list.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
list.clearStorage(); // capacity=0 etc.
list.setCapacity_unsafe(0); // All contents moved
}
@ -135,11 +129,17 @@ inline void Foam::PtrDynList<T, SizeMin>::reserve(const label len)
// Preserve addressed size
const label currLen = PtrList<T>::size();
// Consistent allocated sizing
PtrList<T>::setAddressableSize(capacity_);
// Increase capacity (eg, doubling)
capacity_ =
Foam::ListPolicy::reserve_size<SizeMin, 2>(len, capacity_);
// No PtrList<T>::resize_copy(...) -> copying nullptr is cheap
PtrList<T>::resize(capacity_);
capacity_ = PtrList<T>::size();
PtrList<T>::setAddressableSize(currLen);
}
}
@ -153,8 +153,13 @@ inline void Foam::PtrDynList<T, SizeMin>::reserve_exact(const label len)
// Preserve addressed size
const label currLen = PtrList<T>::size();
capacity_ = len;
PtrList<T>::resize(capacity_);
// Consistent allocated sizing
PtrList<T>::setAddressableSize(capacity_);
// No PtrList<T>::resize_copy(...) -> copying nullptr is cheap
PtrList<T>::resize(len);
capacity_ = PtrList<T>::size();
PtrList<T>::setAddressableSize(currLen);
}
}
@ -164,16 +169,12 @@ template<class T, int SizeMin>
inline void Foam::PtrDynList<T, SizeMin>::resize(const label newLen)
{
auto& ptrs = this->ptrs_;
const label oldLen = ptrs.size();
if (capacity_ < newLen)
{
// Increase capacity (eg, doubling)
capacity_ =
Foam::ListPolicy::reserve_size<SizeMin, 2>(newLen, capacity_);
PtrList<T>::resize(capacity_);
// Extend list
this->reserve(newLen);
}
else if (newLen != oldLen)
{
@ -191,13 +192,16 @@ inline void Foam::PtrDynList<T, SizeMin>::resize(const label newLen)
template<class T, int SizeMin>
inline void Foam::PtrDynList<T, SizeMin>::resize_null(const label newLen)
inline void Foam::PtrDynList<T, SizeMin>::resize_null(const label len)
{
if (capacity_ < newLen)
if (capacity_ < len)
{
// Consistent allocated sizing
PtrList<T>::setAddressableSize(capacity_);
// Increase capacity (eg, doubling)
capacity_ =
Foam::ListPolicy::reserve_size<SizeMin, 2>(newLen, capacity_);
Foam::ListPolicy::reserve_size<SizeMin, 2>(len, capacity_);
PtrList<T>::resize_null(capacity_);
}
@ -207,7 +211,7 @@ inline void Foam::PtrDynList<T, SizeMin>::resize_null(const label newLen)
}
// Adjust addressed size
PtrList<T>::setAddressableSize(newLen);
PtrList<T>::setAddressableSize(len);
}
@ -240,18 +244,6 @@ inline void Foam::PtrDynList<T, SizeMin>::shrink_to_fit()
}
template<class T, int SizeMin>
inline void Foam::PtrDynList<T, SizeMin>::shrink_unsafe()
{
if (PtrList<T>::empty())
{
// Delete empty list
PtrList<T>::clear();
}
capacity_ = PtrList<T>::size();
}
template<class T, int SizeMin>
inline Foam::label Foam::PtrDynList<T, SizeMin>::squeezeNull()
{

View File

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

View File

@ -179,6 +179,9 @@ public:
// Public Classes
//- Wrapper for OpenFOAM internal communicator index
class communicator; // Forward Declaration
//- Wrapper for MPI_Comm
class Communicator; // Forward Declaration
@ -378,6 +381,25 @@ 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);
}
};
@ -850,7 +872,7 @@ public:
const bool withComponents = true
);
//- Creaet new communicator with sub-ranks on the parent communicator
//- Create new communicator with sub-ranks on the parent communicator
static label newCommunicator
(
//! The parent communicator
@ -896,126 +918,6 @@ 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);
@ -1839,6 +1741,168 @@ 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,18 +470,10 @@ 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 "Pstream.H"
#include "UPstream.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -106,22 +106,34 @@ Foam::messageStream::messageStream(const dictionary& dict)
Foam::OSstream& Foam::messageStream::stream
(
OSstream* alternative
OSstream* alternative,
int communicator
)
{
if (communicator < 0)
{
communicator = UPstream::worldComm;
}
if (level)
{
// Serlal (master only) output?
const bool serialOnly
// Master-only output?
const bool masterOnly
(
!UPstream::parRun()
|| ((severity_ & ~errorSeverity::USE_STDERR) == errorSeverity::INFO)
|| ((severity_ & ~errorSeverity::USE_STDERR) == errorSeverity::WARNING)
);
if (serialOnly && (UPstream::parRun() && !UPstream::master()))
if
(
masterOnly
&& (UPstream::parRun() && !UPstream::master(communicator))
)
{
return Snull; // Non-serial, non-master: exit early
// Requested master-only output but is non-master (in parallel)
// -> early exit
return Snull;
}
@ -139,10 +151,9 @@ Foam::OSstream& Foam::messageStream::stream
OSstream* osptr;
if (serialOnly)
if (masterOnly)
{
// Use supplied alternative? Valid for serial only
// Use supplied alternative? Valid for master-only output
osptr =
(
alternative
@ -152,7 +163,6 @@ Foam::OSstream& Foam::messageStream::stream
}
else
{
// Non-serial
osptr = (use_stderr ? &Perr : &Pout);
}
@ -175,8 +185,13 @@ Foam::OSstream& Foam::messageStream::stream
}
Foam::OSstream& Foam::messageStream::masterStream(const int communicator)
Foam::OSstream& Foam::messageStream::masterStream(int communicator)
{
if (communicator < 0)
{
communicator = UPstream::worldComm;
}
if (UPstream::warnComm >= 0 && communicator != UPstream::warnComm)
{
Perr<< "** messageStream with comm:" << communicator << endl;
@ -185,7 +200,7 @@ Foam::OSstream& Foam::messageStream::masterStream(const int communicator)
if (communicator == UPstream::worldComm || UPstream::master(communicator))
{
return this->stream();
return this->stream(nullptr, communicator);
}
return Snull;
@ -194,6 +209,7 @@ Foam::OSstream& Foam::messageStream::masterStream(const int communicator)
std::ostream& Foam::messageStream::stdStream()
{
// Currently do not need communicator != worldComm
return this->stream().stdStream();
}
@ -400,13 +416,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,12 +191,15 @@ public:
OSstream& stream
(
//! An alternative output stream (serial-only)
OSstream* alternative = nullptr
OSstream* alternative = nullptr,
//! Communicator. Negative is treated like UPstream::worldComm
int communicator = -1
);
//- Return OSstream for output operations on the master process only,
//- Snull on other processes.
OSstream& masterStream(const int communicator);
// A negative communicator is treated like UPstream::worldComm
OSstream& masterStream(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 DimensionedField<Type, GeoMesh>& null() noexcept
static const this_type& null() noexcept
{
return NullObjectRef<DimensionedField<Type, GeoMesh>>();
return NullObjectRef<this_type>();
}
@ -373,6 +373,33 @@ 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-2024 OpenCFD Ltd.
Copyright (C) 2022-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -163,6 +163,49 @@ 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

@ -217,7 +217,7 @@ public:
//- Change the value for the list capacity directly (ADVANCED, UNSAFE)
//- Does not perform any memory management or resizing.
void setCapacity_unsafe(const label len) noexcept { capacity_ = len; }
void setCapacity_unsafe(label len) noexcept { capacity_ = len; }
//- Reserve allocation space for at least this size, allocating new
//- space if required and \em retaining old content.
@ -265,11 +265,6 @@ public:
//- Shrink the allocated space to the number of elements used.
inline void shrink_to_fit();
//- Shrink the internal bookkeeping of the allocated space to the
//- number of addressed elements without affecting allocation.
// \note when empty() it will delete any allocated memory.
inline void shrink_unsafe();
// Edit

View File

@ -66,7 +66,9 @@ inline void Foam::DynamicField<T, SizeMin>::doCapacity
// Addressable length, possibly truncated by new capacity
const label currLen = Foam::min(List<T>::size(), newCapacity);
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
if (nocopy)
{
List<T>::resize_nocopy(newCapacity);
@ -93,6 +95,9 @@ inline void Foam::DynamicField<T, SizeMin>::doReserve
// Preserve addressed size
const label currLen = List<T>::size();
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
// Increase capacity (eg, doubling)
capacity_ =
Foam::ListPolicy::reserve_size<SizeMin, 2>(len, capacity_);
@ -103,8 +108,10 @@ inline void Foam::DynamicField<T, SizeMin>::doReserve
}
else
{
List<T>::resize(capacity_);
List<T>::resize_copy(currLen, capacity_);
}
capacity_ = List<T>::size();
List<T>::setAddressableSize(currLen);
}
}
@ -246,7 +253,7 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
Field<T>(std::move(static_cast<List<T>&>(content))),
capacity_(content.capacity())
{
content.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
content.setCapacity_unsafe(0); // All contents moved
}
@ -259,7 +266,7 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
Field<T>(std::move(static_cast<List<T>&>(content))),
capacity_(content.capacity())
{
content.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
content.setCapacity_unsafe(0); // All contents moved
}
@ -273,7 +280,7 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
Field<T>(std::move(static_cast<List<T>&>(content))),
capacity_(content.capacity())
{
content.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
content.setCapacity_unsafe(0); // All contents moved
}
@ -292,7 +299,7 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
{
Field<T>::transfer(static_cast<List<T>&>(content));
capacity_ = content.capacity();
content.setCapacity_unsafe(0);
content.setCapacity_unsafe(0); // All contents moved
}
else
{
@ -317,7 +324,7 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
{
Field<T>::transfer(static_cast<List<T>&>(content));
capacity_ = content.capacity();
content.setCapacity_unsafe(0);
content.setCapacity_unsafe(0); // All contents moved
}
else
{
@ -462,8 +469,15 @@ inline void Foam::DynamicField<T, SizeMin>::reserve_exact
// Preserve addressed size
const label currLen = List<T>::size();
capacity_ = len;
List<T>::resize(capacity_);
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
// if (!nocopy)
{
List<T>::resize_copy(currLen, len);
}
capacity_ = List<T>::size();
List<T>::setAddressableSize(currLen);
}
}
@ -551,18 +565,6 @@ inline void Foam::DynamicField<T, SizeMin>::shrink_to_fit()
}
template<class T, int SizeMin>
inline void Foam::DynamicField<T, SizeMin>::shrink_unsafe()
{
if (List<T>::empty())
{
// Delete storage if empty
List<T>::clear();
}
capacity_ = List<T>::size();
}
template<class T, int SizeMin>
inline void
Foam::DynamicField<T, SizeMin>::swap(List<T>& list)

View File

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

View File

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

View File

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

View File

@ -156,9 +156,9 @@ public:
// Static Member Functions
//- Return a null GeometricField (reference to a nullObject).
static const GeometricField<Type, PatchField, GeoMesh>& null() noexcept
static const this_type& null() noexcept
{
return NullObjectRef<GeometricField<Type, PatchField, GeoMesh>>();
return NullObjectRef<this_type>();
}
@ -251,7 +251,7 @@ public:
const PtrList<PatchField<Type>>& ptfl
);
//- Move construct from internal field and a patch list to clone
//- Construct from internal field (tmp) and a patch list to clone
GeometricField
(
const IOobject& io,
@ -273,7 +273,7 @@ public:
const PtrList<PatchField<Type>>& ptfl
);
//- Copy construct from internal field, with specified patch type
//- Copy construct from primitive field, with specified patch type
GeometricField
(
const IOobject& io,
@ -283,7 +283,7 @@ public:
const word& patchFieldType = PatchField<Type>::calculatedType()
);
//- Move construct from internal field, with specified patch type
//- Move construct from primitive field, with specified patch type
GeometricField
(
const IOobject& io,
@ -293,7 +293,17 @@ public:
const word& patchFieldType = PatchField<Type>::calculatedType()
);
//- Copy construct from components
//- 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
GeometricField
(
const IOobject& io,
@ -303,7 +313,7 @@ public:
const PtrList<PatchField<Type>>& ptfl
);
//- Move construct from internal field and a patch list to clone
//- Move construct from primitive field and a patch list to clone
GeometricField
(
const IOobject& io,
@ -319,7 +329,7 @@ public:
const IOobject& io,
const Mesh& mesh,
const dimensionSet& dims,
const tmp<Field<Type>>& tiField,
const tmp<Field<Type>>& tfield,
const PtrList<PatchField<Type>>& ptfl
);
@ -508,6 +518,37 @@ 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-2024 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -215,6 +215,53 @@ 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,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -87,20 +88,27 @@ void Foam::basicSymmetryPointPatchField<Type>::evaluate
const Pstream::commsTypes
)
{
const vectorField& nHat = this->patch().pointNormals();
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type : no-op
}
else
{
const vectorField& nHat = this->patch().pointNormals();
tmp<Field<Type>> tvalues =
(
const Field<Type> pif(this->patchInternalField());
// Could write as loop instead...
tmp<Field<Type>> tvalues
(
this->patchInternalField()
+ transform(I - 2.0*sqr(nHat), this->patchInternalField())
)/2.0
);
0.5*(pif + transform(I - 2.0*sqr(nHat), pif))
);
// 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

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

View File

@ -84,20 +84,27 @@ Foam::cyclicSlipPointPatchField<Type>::cyclicSlipPointPatchField
template<class Type>
void Foam::cyclicSlipPointPatchField<Type>::evaluate(const Pstream::commsTypes)
{
const vectorField& nHat = this->patch().pointNormals();
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type : no-op
}
else
{
const vectorField& nHat = this->patch().pointNormals();
tmp<Field<Type>> tvalues =
(
const Field<Type> pif(this->patchInternalField());
// Could write as loop instead...
tmp<Field<Type>> tvalues
(
this->patchInternalField()
+ transform(I - 2.0*sqr(nHat), this->patchInternalField())
)/2.0
);
0.5*(pif + transform(I - 2.0*sqr(nHat), pif))
);
// 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

@ -91,20 +91,27 @@ void Foam::nonuniformTransformCyclicPointPatchField<Type>::evaluate
const Pstream::commsTypes
)
{
const vectorField& nHat = this->patch().pointNormals();
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type : no-op
}
else
{
const vectorField& nHat = this->patch().pointNormals();
tmp<Field<Type>> tvalues =
(
const Field<Type> pif(this->patchInternalField());
// Could write as loop instead...
tmp<Field<Type>> tvalues
(
this->patchInternalField()
+ transform(I - 2.0*sqr(nHat), this->patchInternalField())
)/2.0
);
0.5*(pif + transform(I - 2.0*sqr(nHat), pif))
);
// 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

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

View File

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

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

View File

@ -98,16 +98,6 @@ 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:
@ -228,13 +218,24 @@ public:
return updated_;
}
//- Set updated state
void setUpdated(bool state) noexcept
{
updated_ = state;
}
//- True if the matrix has already been manipulated.
//- Currently ignored (always false) for pointPatchField
//- Currently 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
@ -262,6 +263,9 @@ 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

@ -71,6 +71,21 @@ 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) 2018-2024 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -168,10 +168,12 @@ 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,
@ -320,7 +322,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "MeshObject.C"
#include "MeshObject.txx"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2018-2024 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -89,7 +89,11 @@ void Foam::pointBoundaryMesh::calcGroupIDs() const
// Remove groups that clash with patch names
forAll(patches, patchi)
{
if (groupLookup.erase(patches[patchi].name()))
if (groupLookup.empty())
{
break; // Early termination
}
else if (groupLookup.erase(patches[patchi].name()))
{
WarningInFunction
<< "Removed group '" << patches[patchi].name()
@ -370,7 +374,7 @@ Foam::labelList Foam::pointBoundaryMesh::indices
// Only check groups if requested and they exist
const bool checkGroups = (useGroups && this->hasGroupIDs());
labelHashSet ids(0);
labelHashSet ids;
if (matcher.isPattern())
{
@ -381,7 +385,7 @@ Foam::labelList Foam::pointBoundaryMesh::indices
{
if (matcher(iter.key()))
{
// Add patch ids associated with the group
// Add ids associated with the group
ids.insert(iter.val());
}
}
@ -413,7 +417,7 @@ Foam::labelList Foam::pointBoundaryMesh::indices
if (iter.good())
{
// Hash ids associated with the group
// Add ids associated with the group
ids.insert(iter.val());
}
}
@ -438,7 +442,7 @@ Foam::labelList Foam::pointBoundaryMesh::indices
return this->indices(matcher.front(), useGroups);
}
labelHashSet ids(0);
labelHashSet ids;
// Only check groups if requested and they exist
if (useGroups && this->hasGroupIDs())
@ -450,7 +454,7 @@ Foam::labelList Foam::pointBoundaryMesh::indices
{
if (matcher(iter.key()))
{
// Add patch ids associated with the group
// Add ids associated with the group
ids.insert(iter.val());
}
}
@ -471,20 +475,20 @@ Foam::labelList Foam::pointBoundaryMesh::indices
Foam::labelList Foam::pointBoundaryMesh::indices
(
const wordRes& select,
const wordRes& ignore,
const wordRes& allow,
const wordRes& deny,
const bool useGroups
) const
{
//return mesh().boundaryMesh().indices(select, ignore, useGroups);
if (ignore.empty())
if (allow.empty() && deny.empty())
{
return this->indices(select, useGroups);
// Fast-path: select all
return identity(this->size());
}
const wordRes::filter matcher(select, ignore);
const wordRes::filter matcher(allow, deny);
labelHashSet ids(0);
labelHashSet ids;
// Only check groups if requested and they exist
if (useGroups && this->hasGroupIDs())
@ -496,7 +500,7 @@ Foam::labelList Foam::pointBoundaryMesh::indices
{
if (matcher(iter.key()))
{
// Add patch ids associated with the group
// Add 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-2024 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -28,7 +28,9 @@ Class
Foam::pointBoundaryMesh
Description
Foam::pointBoundaryMesh
A pointBoundaryMesh is a pointPatch list with registered IO,
a reference to the associated pointMesh,
with additional search methods etc.
SourceFiles
pointBoundaryMesh.C
@ -102,10 +104,10 @@ public:
// Constructors
//- Construct from polyBoundaryMesh
//- Construct from pointMesh and polyBoundaryMesh
pointBoundaryMesh(const pointMesh&, const polyBoundaryMesh&);
//- Construct from IOobject and polyBoundaryMesh
//- Construct from IOobject, pointMesh and polyBoundaryMesh
pointBoundaryMesh
(
const IOobject& io,
@ -141,24 +143,29 @@ public:
//- Return a list of physical types
wordList physicalTypes() const;
//- Return (sorted) patch indices for all matches.
// A no-op (returns empty list) for an empty matcher
//- The (sorted) patch indices for all matches,
//- optionally matching patch groups.
// \returns an empty list for an empty matcher
labelList indices(const wordRe& matcher, const bool useGroups) const;
//- Return (sorted) patch indices for all matches.
// A no-op (returns empty list) for an empty matcher
//- The (sorted) patch indices for all matches,
//- optionally matching patch groups.
// \returns an empty list for an empty matcher
labelList indices(const wordRes& matcher, const bool useGroups) const;
//- 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
//- 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.
labelList indices
(
const wordRes& select,
const wordRes& ignore,
const bool useGroups
const wordRes& allow,
const wordRes& deny,
const bool useGroups //!< Match patch groups
) const;
//- Find patch index given a name

View File

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

View File

@ -34,8 +34,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef wedgePointPatch_H
#define wedgePointPatch_H
#ifndef Foam_wedgePointPatch_H
#define Foam_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 symmetryPlane patch
//- Local reference cast into the wedgePolyPatch patch
const wedgePolyPatch& wedgePolyPatch_;
@ -120,8 +120,8 @@ public:
pointConstraint&
) const;
//- Return symmetry plane normal
const vector& n() const
//- Return the normal to the patch
const vector& n() const noexcept
{
return wedgePolyPatch_.n();
}

View File

@ -40,96 +40,6 @@ 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-2023 OpenCFD Ltd.
Copyright (C) 2015-2025 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(List<T>& field) const;
void applyDummyTransforms(UList<T>& field) const;
template<class T, class TransformOp>
void applyTransforms
(
const globalIndexAndTransform& globalTransforms,
List<T>& field,
UList<T>& field,
const TransformOp& top
) const;
//- Helper function: copy transformElements without transformation
template<class T>
void applyDummyInverseTransforms(List<T>& field) const;
void applyDummyInverseTransforms(UList<T>& field) const;
template<class T, class TransformOp>
void applyInverseTransforms
(
const globalIndexAndTransform& globalTransforms,
List<T>& field,
UList<T>& field,
const TransformOp& top
) const;
@ -219,11 +219,14 @@ public:
(
const vectorTensorTransform& vt,
const bool forward,
List<Type>& fld
UList<Type>& fld
) const
{
const tensor T(forward ? vt.R() : vt.R().T());
transformList(T, fld);
if constexpr (is_rotational_vectorspace_v<Type>)
{
const tensor rot(forward ? vt.R() : vt.R().T());
transformList(rot, fld);
}
}
template<class Type>
@ -234,9 +237,13 @@ public:
List<List<Type>>& flds
) const
{
for (List<Type>& fld : flds)
if constexpr (is_rotational_vectorspace_v<Type>)
{
operator()(vt, forward, fld);
const tensor rot(forward ? vt.R() : vt.R().T());
for (auto& fld : flds)
{
transformList(rot, fld);
}
}
}
@ -244,9 +251,12 @@ public:
template<class Type>
void operator()(const coupledPolyPatch& cpp, UList<Type>& fld) const
{
if (!cpp.parallel())
if constexpr (is_rotational_vectorspace_v<Type>)
{
transformList(cpp.forwardT(), fld);
if (!cpp.parallel())
{
transformList(cpp.forwardT(), fld);
}
}
}
@ -255,9 +265,12 @@ public:
void operator()(const coupledPolyPatch& cpp, Container<Type>& map)
const
{
if (!cpp.parallel())
if constexpr (is_rotational_vectorspace_v<Type>)
{
transformList(cpp.forwardT(), map);
if (!cpp.parallel())
{
transformList(cpp.forwardT(), map);
}
}
}
};
@ -271,17 +284,16 @@ public:
(
const vectorTensorTransform& vt,
const bool forward,
List<point>& fld
UList<point>& fld
) const
{
pointField pfld(std::move(fld));
if (forward)
{
fld = vt.transformPosition(pfld);
vt.transformPositionList(fld);
}
else
{
fld = vt.invTransformPosition(pfld);
vt.invTransformPositionList(fld);
}
}
@ -292,9 +304,19 @@ public:
List<List<point>>& flds
) const
{
for (List<point>& fld : flds)
if (forward)
{
operator()(vt, forward, fld);
for (auto& fld : flds)
{
vt.transformPositionList(fld);
}
}
else
{
for (auto& fld : flds)
{
vt.invTransformPositionList(fld);
}
}
}
@ -682,86 +704,6 @@ 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
List<T>& lhs,
UList<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
List<T>& output,
//! [out] The input values
UList<T>& output,
//! 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
(
//! [out] The input values
//! 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 List<labelPair>& schedule,
const UList<labelPair>& schedule,
const label constructSize,
const labelListList& subMap,
const bool subHasFlip,
@ -918,7 +918,7 @@ public:
static void distribute
(
const UPstream::commsTypes commsType,
const List<labelPair>& schedule,
const UList<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 List<T>& field) const;
void send(PstreamBuffers& pBufs, const UList<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
(
List<T>& lhs,
UList<T>& lhs,
const UList<T>& rhs,
const labelUList& map,
@ -46,6 +46,9 @@ 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)
@ -82,7 +85,7 @@ void Foam::mapDistributeBase::flipAndCombine
template<class T, class NegateOp>
void Foam::mapDistributeBase::accessAndFlip
(
List<T>& output,
UList<T>& output,
const UList<T>& values,
const labelUList& map,
const bool hasFlip,
@ -91,6 +94,7 @@ void Foam::mapDistributeBase::accessAndFlip
{
const label len = map.size();
// FULLDEBUG: if (values.size() < max(map)) FatalError ...;
// FULLDEBUG: if (output.size() < len) FatalError ...;
if (hasFlip)
@ -447,7 +451,7 @@ template<class T, class CombineOp, class NegateOp>
void Foam::mapDistributeBase::distribute
(
const UPstream::commsTypes commsType,
const List<labelPair>& schedule,
const UList<labelPair>& schedule,
const label constructSize,
const labelListList& subMap,
const bool subHasFlip,
@ -894,7 +898,7 @@ template<class T, class NegateOp>
void Foam::mapDistributeBase::distribute
(
const UPstream::commsTypes commsType,
const List<labelPair>& schedule,
const UList<labelPair>& schedule,
const label constructSize,
const labelListList& subMap,
const bool subHasFlip,
@ -1332,7 +1336,7 @@ template<class T>
void Foam::mapDistributeBase::send
(
PstreamBuffers& pBufs,
const List<T>& field
const UList<T>& field
) const
{
// Stream data into buffer
@ -1482,13 +1486,11 @@ void Foam::mapDistributeBase::distribute
const int tag
) const
{
values.shrink();
List<T> work(std::move(values));
List<T>& list = static_cast<List<T>&>(values);
distribute(commsType, work, tag);
distribute(commsType, list, tag);
values.setCapacity(list.size());
values = std::move(work);
}

View File

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

View File

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

View File

@ -28,8 +28,9 @@ Class
Foam::polyBoundaryMesh
Description
A polyBoundaryMesh is a polyPatch list with additional search methods
and registered IO.
A polyBoundaryMesh is a polyPatch list with registered IO,
a reference to the associated polyMesh,
with additional search methods etc.
SourceFiles
polyBoundaryMesh.C
@ -259,34 +260,37 @@ public:
labelRange range(const label patchi) const;
//- Return (sorted) patch indices for all matches.
// Optionally matches patch groups.
// A no-op (returns empty list) for an empty matcher
//- The (sorted) patch indices for all matches,
//- optionally matching patch groups.
// \returns an empty list for an empty matcher
labelList indices
(
const wordRe& matcher,
const bool useGroups = true
) const;
//- Return (sorted) patch indices for all matches.
// Optionally matches patch groups.
// A no-op (returns empty list) for an empty matcher
//- The (sorted) patch indices for all matches,
//- optionally matching patch groups.
// \returns an empty list for an empty matcher
labelList indices
(
const wordRes& matcher,
const bool useGroups = true
const bool useGroups = true //!< Match patch groups
) const;
//- 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
//- 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.
labelList indices
(
const wordRes& select,
const wordRes& ignore,
const bool useGroups = true
const wordRes& allow,
const wordRes& deny,
const bool useGroups = true //!< Match patch groups
) const;
//- Return (sorted) patch indices for patches that match the

View File

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

View File

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

View File

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

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016-2024 OpenCFD Ltd.
Copyright (C) 2016-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -205,7 +205,11 @@ void Foam::ZoneMesh<ZoneType, MeshType>::calcGroupIDs() const
// Remove groups that clash with zone names
forAll(zones, zonei)
{
if (groupLookup.erase(zones[zonei].name()))
if (groupLookup.empty())
{
break; // Early termination
}
else if (groupLookup.erase(zones[zonei].name()))
{
WarningInFunction
<< "Removed group '" << zones[zonei].name()
@ -541,7 +545,7 @@ Foam::labelList Foam::ZoneMesh<ZoneType, MeshType>::indices
// Only check groups if requested and they exist
const bool checkGroups = (useGroups && this->hasGroupIDs());
labelHashSet ids(0);
labelHashSet ids;
if (checkGroups)
{
@ -557,7 +561,7 @@ Foam::labelList Foam::ZoneMesh<ZoneType, MeshType>::indices
{
if (matcher(iter.key()))
{
// Hash ids associated with the group
// Add ids associated with the group
ids.insert(iter.val());
}
}
@ -589,7 +593,7 @@ Foam::labelList Foam::ZoneMesh<ZoneType, MeshType>::indices
if (iter.good())
{
// Hash ids associated with the group
// Add ids associated with the group
ids.insert(iter.val());
}
}
@ -615,7 +619,7 @@ Foam::labelList Foam::ZoneMesh<ZoneType, MeshType>::indices
return this->indices(matcher.front(), useGroups);
}
labelHashSet ids(0);
labelHashSet ids;
// Only check groups if requested and they exist
if (useGroups && this->hasGroupIDs())
@ -627,7 +631,7 @@ Foam::labelList Foam::ZoneMesh<ZoneType, MeshType>::indices
{
if (matcher(iter.key()))
{
// Hash the ids associated with the group
// Add ids associated with the group
ids.insert(iter.val());
}
}
@ -649,19 +653,20 @@ Foam::labelList Foam::ZoneMesh<ZoneType, MeshType>::indices
template<class ZoneType, class MeshType>
Foam::labelList Foam::ZoneMesh<ZoneType, MeshType>::indices
(
const wordRes& select,
const wordRes& ignore,
const wordRes& allow,
const wordRes& deny,
const bool useGroups
) const
{
if (ignore.empty())
if (allow.empty() && deny.empty())
{
return this->indices(select, useGroups);
// Fast-path: select all
return identity(this->size());
}
const wordRes::filter matcher(select, ignore);
const wordRes::filter matcher(allow, deny);
labelHashSet ids(0);
labelHashSet ids;
// Only check groups if requested and they exist
if (useGroups && this->hasGroupIDs())
@ -673,7 +678,7 @@ Foam::labelList Foam::ZoneMesh<ZoneType, MeshType>::indices
{
if (matcher(iter.key()))
{
// Add patch ids associated with the group
// Add 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-2024 OpenCFD Ltd.
Copyright (C) 2016-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -227,34 +227,37 @@ public:
wordList sortedNames(const wordRes& matcher) const;
//- Return (sorted) zone indices for all matches
// Optionally matches zone groups.
// A no-op (returns empty list) for an empty matcher
//- The (sorted) patch indices for all matches,
//- optionally matching zone groups.
// \returns an empty list for an empty matcher
labelList indices
(
const wordRe& matcher,
const bool useGroups = true
) const;
//- Return (sorted) zone indices for all matches
// Optionally matches zone groups.
// A no-op (returns empty list) for an empty matcher
//- The (sorted) patch indices for all matches,
//- optionally matching zone groups.
// \returns an empty list for an empty matcher
labelList indices
(
const wordRes& matcher,
const bool useGroups = true
) const;
//- 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
//- 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.
labelList indices
(
const wordRes& select,
const wordRes& ignore,
const bool useGroups = true
const wordRes& allow,
const wordRes& deny,
const bool useGroups = true //!< Match zone groups
) 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-2023 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -92,7 +92,7 @@ public:
// Constructors
//- Construct initialized to zero
inline DiagTensor(const Foam::zero);
inline DiagTensor(Foam::zero);
//- Construct given VectorSpace
template<class Cmpt2>
@ -123,6 +123,9 @@ 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-2023 OpenCFD Ltd.
Copyright (C) 2020-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -32,9 +32,9 @@ License
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Cmpt>
inline Foam::DiagTensor<Cmpt>::DiagTensor(const Foam::zero)
inline Foam::DiagTensor<Cmpt>::DiagTensor(Foam::zero)
:
VectorSpace<DiagTensor<Cmpt>, Cmpt, 3>(Zero)
VectorSpace<DiagTensor<Cmpt>, Cmpt, 3>(Foam::zero{})
{}
@ -81,6 +81,13 @@ 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-2023 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -94,7 +94,7 @@ public:
// Constructors
//- Construct initialized to zero
inline SymmTensor(const Foam::zero);
inline SymmTensor(Foam::zero);
//- Construct given VectorSpace of the same rank
template<class Cmpt2>
@ -234,6 +234,12 @@ 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-2023 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -31,9 +31,9 @@ License
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Cmpt>
inline Foam::SymmTensor<Cmpt>::SymmTensor(const Foam::zero)
inline Foam::SymmTensor<Cmpt>::SymmTensor(Foam::zero)
:
SymmTensor::vsType(Zero)
SymmTensor::vsType(Foam::zero{})
{}
@ -238,6 +238,21 @@ 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
(
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
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
);
}

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -60,6 +61,13 @@ 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;
@ -70,32 +78,6 @@ 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)

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd.
Copyright (C) 2020-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -34,12 +34,12 @@ Description
SourceFiles
vectorTensorTransformI.H
vectorTensorTransform.C
vectorTensorTransformTemplates.C
vectorTensorTransform.txx
\*---------------------------------------------------------------------------*/
#ifndef vectorTensorTransform_H
#define vectorTensorTransform_H
#ifndef Foam_vectorTensorTransform_H
#define Foam_vectorTensorTransform_H
#include "tensor.H"
#include "word.H"
@ -126,39 +126,57 @@ public:
// Member Functions
// Access
// Access
inline const vector& t() const;
//- True if it has a non-identity rotation tensor
bool hasR() const noexcept { return hasR_; }
inline const tensor& R() const;
//- The translation vector
const vector& t() const noexcept { return t_; }
inline bool hasR() const;
//- The (forward) rotation tensor
const tensor& R() const noexcept { return R_; }
// Edit
// Edit
inline vector& t();
//- Non-const access to the translation vector
vector& t() noexcept { return t_; }
inline tensor& R();
//- Non-const access to the rotation tensor. Sets hasR = true
inline tensor& R() noexcept;
//- Test for identity rotation and set hasR accordingly
void checkRotation(const scalar tol = ROOTVSMALL);
// Transform
// Transform
//- Transform the given position
inline vector transformPosition(const vector& v) const;
//- Transform the given position
inline vector transformPosition(const vector& v) const;
//- Transform the given pointField
inline pointField transformPosition(const pointField& pts) const;
//- Transform the given field of points
inline pointField transformPosition(const pointField& pts) const;
//- Inverse transform the given position
inline vector invTransformPosition(const vector& v) const;
//- Inplace transform the given points
inline void transformPositionList(UList<point>& pts) const;
//- Inverse transform the given pointField
inline pointField invTransformPosition(const pointField& pts) const;
//- Inverse transform the given position
inline vector invTransformPosition(const vector& v) const;
//- Transform the given field
template<class Type>
tmp<Field<Type>> transform(const Field<Type>&) const;
//- Inverse transform the given field of points
inline pointField invTransformPosition(const pointField& pts) const;
//- Inplace inverse transform the given points
inline void invTransformPositionList(UList<point>& pts) const;
//- Transform the given field
template<class Type>
tmp<Field<Type>> transform(const Field<Type>& fld) const;
//- Inplace transform the given field
template<class Type>
void transformList(UList<Type>& fld) const;
// Member Operators
@ -196,18 +214,6 @@ inline vectorTensorTransform inv(const vectorTensorTransform& tr);
//- Return a string representation of a vectorTensorTransform
word name(const vectorTensorTransform&);
//- Template specialisations
template<>
tmp<Field<bool>> vectorTensorTransform::transform(const Field<bool>&) const;
template<>
tmp<Field<label>> vectorTensorTransform::transform(const Field<label>&) const;
template<>
tmp<Field<scalar>> vectorTensorTransform::transform(const Field<scalar>&)
const;
// * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * //
inline bool operator==
@ -262,7 +268,7 @@ inline vectorTensorTransform operator&
#include "vectorTensorTransformI.H"
#ifdef NoRepository
#include "vectorTensorTransformTemplates.C"
#include "vectorTensorTransform.txx"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -33,9 +34,16 @@ Foam::tmp<Foam::Field<Type>> Foam::vectorTensorTransform::transform
const Field<Type>& fld
) const
{
if (hasR_)
if constexpr (is_rotational_vectorspace_v<Type>)
{
return R() & fld;
if (hasR_)
{
return (R() & fld);
}
else
{
return fld;
}
}
else
{
@ -44,4 +52,23 @@ Foam::tmp<Foam::Field<Type>> Foam::vectorTensorTransform::transform
}
template<class Type>
void Foam::vectorTensorTransform::transformList
(
UList<Type>& fld
) const
{
if constexpr (is_rotational_vectorspace_v<Type>)
{
if (hasR_)
{
for (auto& val : fld)
{
val = (R() & val);
}
}
}
}
// ************************************************************************* //

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -66,35 +67,10 @@ inline Foam::vectorTensorTransform::vectorTensorTransform(const tensor& R)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline const Foam::vector& Foam::vectorTensorTransform::t() const
{
return t_;
}
inline const Foam::tensor& Foam::vectorTensorTransform::R() const
{
return R_;
}
inline bool Foam::vectorTensorTransform::hasR() const
{
return hasR_;
}
inline Foam::vector& Foam::vectorTensorTransform::t()
{
return t_;
}
inline Foam::tensor& Foam::vectorTensorTransform::R()
inline Foam::tensor& Foam::vectorTensorTransform::R() noexcept
{
// Assume that non-const access to R changes it from I, so set
// hasR to true
hasR_ = true;
return R_;
@ -136,6 +112,28 @@ inline Foam::pointField Foam::vectorTensorTransform::transformPosition
}
inline void Foam::vectorTensorTransform::transformPositionList
(
UList<point>& pts
) const
{
if (hasR_)
{
for (auto& p : pts)
{
p = t() + (R() & p);
}
}
else
{
for (auto& p : pts)
{
p += t();
}
}
}
inline Foam::vector Foam::vectorTensorTransform::invTransformPosition
(
const vector& v
@ -171,6 +169,30 @@ inline Foam::pointField Foam::vectorTensorTransform::invTransformPosition
}
inline void Foam::vectorTensorTransform::invTransformPositionList
(
UList<point>& pts
) const
{
if (hasR_)
{
const auto rot = R().T();
for (auto& p : pts)
{
p = (rot & (p - t()));
}
}
else
{
for (auto& p : pts)
{
p -= t();
}
}
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
inline void Foam::vectorTensorTransform::operator&=

View File

@ -447,7 +447,7 @@ public:
inline constexpr IntType operator-
(
const const_reverse_iterator& iter
)const noexcept;
) const noexcept;
// Comparison

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2022 OpenCFD Ltd.
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -370,12 +370,12 @@ labelList findMatching
AccessOp aop = identityOp()
);
//- Return ids for items with matching names.
// Uses a combination of allow and deny lists
//- Return ids for items with matching names,
//- using a combination of allow and deny lists as per wordRes::filter
//
// An empty 'allow' accepts everything not in 'deny'.
// A literal 'allow' match has higher priority than any 'deny'.
// A regex 'allow' match has lower priority than any 'deny'.
// 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.
//
// Example (when applied to a list of words),
// \verbatim
@ -386,7 +386,7 @@ labelList findMatching
// result: (abc other val val1 wall1 wall2)
// \endverbatim
//
// \return List indices for matches
// \returns identity list when allow/deny are both empty.
template<class StringListType, class AccessOp = identityOp>
labelList findMatching
(

View File

@ -143,7 +143,7 @@ Foam::labelList Foam::stringListOps::findMatching
if (pred.empty())
{
// Accept all
// Fast-path: select all
return identity(len);
}
@ -177,11 +177,10 @@ Foam::labelList Foam::stringListOps::findMatching
{
if (allow.empty() && deny.empty())
{
// Accept all
// Fast-path: select all
return identity(input.size());
}
// Use combined accept/reject filter
const wordRes::filter pred(allow, deny);
return stringListOps::findMatching(input, pred, aop);

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