ENH: add cfindPatch() method to boundary meshes

- find patch by name and return pointer to it. Similar to cfindZone()

ENH: robuster PatchFunction1 handling for uniformFixedValuePointPatchField

COMP: use 'if constexpr' with is_contiguous check

STYLE: consistent patch slicing parameters

- slice UList values, not List values
This commit is contained in:
Mark Olesen
2025-08-05 15:31:15 +02:00
parent 631b6e5111
commit fcc8e62e47
20 changed files with 235 additions and 198 deletions

View File

@ -178,8 +178,8 @@ public:
// Access
//- Return size
label size() const
//- Return the field size
label size() const noexcept
{
return Field<Type>::size();
}

View File

@ -455,7 +455,7 @@ public:
// Access
//- Return the patch size
label size() const
label size() const noexcept
{
return patch().size();
}

View File

@ -568,6 +568,21 @@ Foam::label Foam::pointBoundaryMesh::findPatchID
}
const Foam::pointPatch*
Foam::pointBoundaryMesh::cfindPatch(const word& patchName) const
{
const pointPatchList& patches = *this;
if (!patchName.empty())
{
// Note: get() handles out-of-range access properly
return patches.get(PtrListOps::firstMatching(patches, patchName));
}
return nullptr;
}
void Foam::pointBoundaryMesh::calcGeometry()
{
PstreamBuffers pBufs(Pstream::defaultCommsType);

View File

@ -176,6 +176,10 @@ public:
const bool allowNotFound = true
) const;
//- Find patch by name and return const pointer.
//- \returns nullptr if not found or for an empty patchName
const pointPatch* cfindPatch(const word& patchName) const;
//- The patch indices per patch group
const HashTable<labelList>& groupPatchIDs() const;

View File

@ -957,7 +957,7 @@ void Foam::mapDistributeBase::distribute
const label startOfRequests = UPstream::nRequests();
if (!is_contiguous<T>::value)
if constexpr (!is_contiguous_v<T>)
{
PstreamBuffers pBufs(comm, tag);

View File

@ -989,6 +989,21 @@ Foam::label Foam::polyBoundaryMesh::findPatchID
}
const Foam::polyPatch*
Foam::polyBoundaryMesh::cfindPatch(const word& patchName) const
{
const polyPatchList& patches = *this;
if (!patchName.empty())
{
// Note: get() handles out-of-range access properly
return patches.get(PtrListOps::firstMatching(patches, patchName));
}
return nullptr;
}
Foam::labelPair
Foam::polyBoundaryMesh::whichPatchFace(const label meshFacei) const
{

View File

@ -316,6 +316,10 @@ public:
const bool allowNotFound = true
) const;
//- Find patch by name and return const pointer.
//- \returns nullptr on error or for an empty patchName
const polyPatch* cfindPatch(const word& patchName) const;
//- Find patch indices for a given polyPatch type (uses \c isA test).
template<class PatchType>
labelHashSet findPatchIDs() const;

View File

@ -411,15 +411,6 @@ public:
return typename List<T>::subList(values, this->size(), start_);
}
//- This patch slice from the list of boundary values, which has size
//- mesh::nBoundaryFaces(), using the number of patch faces.
template<class T>
const typename List<T>::subList
boundarySlice(const List<T>& values) const
{
return typename List<T>::subList(values, this->size(), offset());
}
//- Slice Field to patch, using the number of patch faces.
template<class T>
const typename Field<T>::subField
@ -428,6 +419,15 @@ public:
return typename Field<T>::subField(values, this->size(), start_);
}
//- This patch slice from the list of boundary values, which has size
//- mesh::nBoundaryFaces(), using the number of patch faces.
template<class T>
const typename List<T>::subList
boundarySlice(const UList<T>& values) const
{
return typename List<T>::subList(values, this->size(), offset());
}
//- Write the polyPatch data as a dictionary
virtual void write(Ostream& os) const;

View File

@ -784,6 +784,23 @@ Foam::label Foam::faBoundaryMesh::findPatchID
}
const Foam::faPatch* Foam::faBoundaryMesh::cfindPatch
(
const word& patchName
) const
{
const faPatchList& patches = *this;
if (!patchName.empty())
{
// Note: get() handles out-of-range access properly
return patches.get(PtrListOps::firstMatching(patches, patchName));
}
return nullptr;
}
Foam::label Foam::faBoundaryMesh::whichPatch(const label edgeIndex) const
{
if (edgeIndex < mesh().nInternalEdges())

View File

@ -269,6 +269,10 @@ public:
const bool allowNotFound = true
) const;
//- Find patch by name and return const pointer.
//- \returns nullptr if not found or for an empty patchName
const faPatch* cfindPatch(const word& patchName) const;
//- Return patch index for a given edge label
label whichPatch(const label edgeIndex) const;

View File

@ -327,7 +327,8 @@ public:
//- This patch slice from the complete list of values, which has
//- size mesh::nEdges(), using the virtual patch size.
template<class T>
const typename List<T>::subList patchSlice(const List<T>& values) const
const typename List<T>::subList
patchSlice(const UList<T>& values) const
{
return typename List<T>::subList(values, size(), start());
}
@ -336,14 +337,9 @@ public:
//- size mesh::nBoundaryEdges(), using the virtual patch size.
template<class T>
const typename List<T>::subList
boundarySlice(const List<T>& values) const
boundarySlice(const UList<T>& values) const
{
return typename List<T>::subList
(
values,
size(),
offset()
);
return typename List<T>::subList(values, size(), offset());
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2023 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -114,6 +114,21 @@ Foam::label Foam::fvBoundaryMesh::findPatchID(const word& patchName) const
}
const Foam::fvPatch*
Foam::fvBoundaryMesh::cfindPatch(const word& patchName) const
{
const fvPatchList& patches = *this;
if (!patchName.empty())
{
// Note: get() handles out-of-range access properly
return patches.get(PtrListOps::firstMatching(patches, patchName));
}
return nullptr;
}
void Foam::fvBoundaryMesh::movePoints()
{
fvPatchList& patches = *this;

View File

@ -143,6 +143,10 @@ public:
// A no-op (returns -1) for an empty patchName
label findPatchID(const word& patchName) const;
//- Find patch by name and return const pointer.
//- \returns nullptr if not found or for an empty patchName
const fvPatch* cfindPatch(const word& patchName) const;
//- Correct patches after moving points
void movePoints();

View File

@ -64,10 +64,7 @@ void Foam::fvPatchMapper::calcAddressing() const
// Direct mapping - slice to size
directAddrPtr_ = std::make_unique<labelList>
(
patch_.patchSlice
(
static_cast<const labelList&>(faceMap_.directAddressing())
)
patch_.patchSlice(faceMap_.directAddressing())
);
auto& addr = *directAddrPtr_;

View File

@ -224,7 +224,7 @@ public:
//- mesh::nFaces(), using the virtual patch size.
template<class T>
const typename List<T>::subList
patchSlice(const List<T>& values) const
patchSlice(const UList<T>& values) const
{
return typename List<T>::subList(values, size(), start());
}
@ -233,14 +233,9 @@ public:
//- mesh::nBoundaryFaces(), using the virtual patch size.
template<class T>
const typename List<T>::subList
boundarySlice(const List<T>& values) const
boundarySlice(const UList<T>& values) const
{
return typename List<T>::subList
(
values,
size(),
polyPatch_.offset()
);
return typename List<T>::subList(values, size(), offset());
}
//- Return faceCells

View File

@ -76,18 +76,20 @@ void Foam::surfaceSlipDisplacementPointPatchVectorField::calcProjection
// Get fixed points (bit of a hack)
const pointZone* zonePtr = nullptr;
const pointZone* zonePtr = mesh.pointZones().cfindZone(frozenPointsZone_);
if (frozenPointsZone_.size() > 0)
if (zonePtr)
{
const pointZoneMesh& pZones = mesh.pointZones();
zonePtr = &pZones[frozenPointsZone_];
Pout<< "surfaceSlipDisplacementPointPatchVectorField : Fixing all "
<< zonePtr->size() << " points in pointZone " << zonePtr->name()
<< endl;
}
else if (!frozenPointsZone_.empty())
{
FatalErrorInFunction
<< "Cannot find frozen point zone: " << frozenPointsZone_ << nl
<< exit(FatalError);
}
// Get the starting locations from the motionSolver
const pointField& points0 = mesh.lookupObject<displacementMotionSolver>
@ -331,19 +333,20 @@ surfaceSlipDisplacementPointPatchVectorField
),
wedgePlane_(dict.getOrDefault("wedgePlane", -1)),
frozenPointsZone_(dict.getOrDefault("frozenPointsZone", word::null)),
scalePtr_
(
isA<facePointPatch>(p)
? PatchFunction1<scalar>::NewIfPresent
(
refCast<const facePointPatch>(p).patch(),
"scale",
dict,
false // point values
)
: nullptr
)
{}
scalePtr_(nullptr)
{
if (const auto* fpp = isA<facePointPatch>(this->patch()))
{
scalePtr_ =
PatchFunction1<scalar>::NewIfPresent
(
fpp->patch(),
"scale",
dict,
false // point values (faceValues = false)
);
}
}
Foam::surfaceSlipDisplacementPointPatchVectorField::
@ -361,37 +364,13 @@ surfaceSlipDisplacementPointPatchVectorField
projectDir_(ppf.projectDir_),
wedgePlane_(ppf.wedgePlane_),
frozenPointsZone_(ppf.frozenPointsZone_),
scalePtr_
(
isA<facePointPatch>(p)
? ppf.scalePtr_.clone(refCast<const facePointPatch>(p).patch())
: nullptr
)
{}
Foam::surfaceSlipDisplacementPointPatchVectorField::
surfaceSlipDisplacementPointPatchVectorField
(
const surfaceSlipDisplacementPointPatchVectorField& ppf
)
:
pointPatchVectorField(ppf),
surfacesDict_(ppf.surfacesDict_),
projectMode_(ppf.projectMode_),
projectDir_(ppf.projectDir_),
wedgePlane_(ppf.wedgePlane_),
frozenPointsZone_(ppf.frozenPointsZone_),
scalePtr_
(
isA<facePointPatch>(ppf.patch())
? ppf.scalePtr_.clone
(
refCast<const facePointPatch>(ppf.patch()).patch()
)
: nullptr
)
{}
scalePtr_(nullptr)
{
if (const auto* fpp = isA<facePointPatch>(this->patch()))
{
scalePtr_ = ppf.scalePtr_.clone(fpp->patch());
}
}
Foam::surfaceSlipDisplacementPointPatchVectorField::
@ -407,16 +386,13 @@ surfaceSlipDisplacementPointPatchVectorField
projectDir_(ppf.projectDir_),
wedgePlane_(ppf.wedgePlane_),
frozenPointsZone_(ppf.frozenPointsZone_),
scalePtr_
(
isA<facePointPatch>(ppf.patch())
? ppf.scalePtr_.clone
(
refCast<const facePointPatch>(ppf.patch()).patch()
)
: nullptr
)
{}
scalePtr_(nullptr)
{
if (const auto* fpp = isA<facePointPatch>(this->patch()))
{
scalePtr_ = ppf.scalePtr_.clone(fpp->patch());
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //

View File

@ -57,8 +57,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef surfaceSlipDisplacementPointPatchVectorField_H
#define surfaceSlipDisplacementPointPatchVectorField_H
#ifndef Foam_surfaceSlipDisplacementPointPatchVectorField_H
#define Foam_surfaceSlipDisplacementPointPatchVectorField_H
#include "pointPatchFields.H"
#include "searchableSurfaces.H"
@ -77,10 +77,9 @@ class surfaceSlipDisplacementPointPatchVectorField
:
public pointPatchVectorField
{
public:
// Public data types
// Public Data Types
enum projectMode
{
@ -162,19 +161,27 @@ public:
const pointPatchFieldMapper&
);
//- Construct as copy
surfaceSlipDisplacementPointPatchVectorField
(
const surfaceSlipDisplacementPointPatchVectorField&
);
//- Construct as copy setting internal field reference
//- Copy construct with internal field reference
surfaceSlipDisplacementPointPatchVectorField
(
const surfaceSlipDisplacementPointPatchVectorField&,
const DimensionedField<vector, pointMesh>&
);
//- Copy construct
surfaceSlipDisplacementPointPatchVectorField
(
const surfaceSlipDisplacementPointPatchVectorField& pfld
)
:
surfaceSlipDisplacementPointPatchVectorField
(
pfld,
pfld.internalField()
)
{}
//- Return a clone
virtual autoPtr<pointPatchField<vector>> clone() const
{

View File

@ -33,23 +33,23 @@ License
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
// Alternative
// refCast<const facePointPatch>(p).patch()
// {
// if (const auto* fpp = isA<facePointPatch>(p).patch())
// {
// return fpp->patch();
// }
// else
// {
// return nullptr;
// }
// }
template<class Type>
const Foam::polyPatch*
Foam::uniformFixedValuePointPatchField<Type>::getPatch(const pointPatch& p)
Foam::uniformFixedValuePointPatchField<Type>::getPolyPatch(const pointPatch& p)
{
const polyMesh& mesh = p.boundaryMesh().mesh()();
label patchi = mesh.boundaryMesh().findPatchID(p.name());
if (patchi == -1)
{
return nullptr;
}
else
{
return &mesh.boundaryMesh()[patchi];
}
return mesh.boundaryMesh().cfindPatch(p.name());
}
@ -63,9 +63,7 @@ uniformFixedValuePointPatchField
const DimensionedField<Type, pointMesh>& iF
)
:
fixedValuePointPatchField<Type>(p, iF),
refValueFunc_(nullptr),
refPointValueFunc_(nullptr)
fixedValuePointPatchField<Type>(p, iF)
{}
@ -78,31 +76,26 @@ uniformFixedValuePointPatchField
const dictionary& dict
)
:
fixedValuePointPatchField<Type>(p, iF, dict, IOobjectOption::NO_READ),
refValueFunc_
(
this->getPatch(p)
? PatchFunction1<Type>::New
(
*(this->getPatch(p)),
"uniformValue",
dict,
false // generate point values
)
: nullptr
),
refPointValueFunc_
(
this->getPatch(p)
? nullptr
: Function1<Type>::New
(
"uniformValue",
dict,
&this->internalField().db()
)
)
fixedValuePointPatchField<Type>(p, iF, dict, IOobjectOption::NO_READ)
{
if (const polyPatch* pp = this->getPolyPatch(this->patch()))
{
refValueFunc_ = PatchFunction1<Type>::New
(
*pp,
"uniformValue",
dict,
false // point values (faceValues = false)
);
}
// Fallback
refPointValueFunc_ = Function1<Type>::New
(
"uniformValue",
dict,
&this->internalField().db()
);
if (!this->readValueEntry(dict))
{
// Ensure field has reasonable initial values
@ -124,10 +117,15 @@ uniformFixedValuePointPatchField
const pointPatchFieldMapper& mapper
)
:
fixedValuePointPatchField<Type>(ptf, p, iF, mapper),
refValueFunc_(ptf.refValueFunc_.clone(*(this->getPatch(p)))),
refPointValueFunc_(ptf.refPointValueFunc_.clone())
fixedValuePointPatchField<Type>(ptf, p, iF, mapper)
{
if (const polyPatch* pp = this->getPolyPatch(this->patch()))
{
refValueFunc_ = ptf.refValueFunc_.clone(*pp);
}
// Fallback
refPointValueFunc_ = ptf.refPointValueFunc_.clone();
if (mapper.direct() && !mapper.hasUnmapped())
{
// Use mapping instead of re-evaluation
@ -145,27 +143,19 @@ template<class Type>
Foam::uniformFixedValuePointPatchField<Type>::
uniformFixedValuePointPatchField
(
const uniformFixedValuePointPatchField<Type>& ptf
)
:
fixedValuePointPatchField<Type>(ptf),
refValueFunc_(ptf.refValueFunc_.clone(*(this->getPatch(this->patch())))),
refPointValueFunc_(ptf.refPointValueFunc_.clone())
{}
template<class Type>
Foam::uniformFixedValuePointPatchField<Type>::
uniformFixedValuePointPatchField
(
const uniformFixedValuePointPatchField<Type>& ptf,
const uniformFixedValuePointPatchField<Type>& pfld,
const DimensionedField<Type, pointMesh>& iF
)
:
fixedValuePointPatchField<Type>(ptf, iF),
refValueFunc_(ptf.refValueFunc_.clone(*(this->getPatch(this->patch())))),
refPointValueFunc_(ptf.refPointValueFunc_.clone())
{}
fixedValuePointPatchField<Type>(pfld, iF)
{
if (const polyPatch* pp = this->getPolyPatch(this->patch()))
{
refValueFunc_ = pfld.refValueFunc_.clone(*pp);
}
// Fallback
refPointValueFunc_ = pfld.refPointValueFunc_.clone();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
@ -178,24 +168,31 @@ void Foam::uniformFixedValuePointPatchField<Type>::autoMap
{
fixedValuePointPatchField<Type>::autoMap(mapper);
bool canEvaluate(false);
if (refValueFunc_)
{
refValueFunc_().autoMap(mapper);
if (refValueFunc_().constant())
// If mapper is not dependent on time we're ok to evaluate
if (refValueFunc_->constant())
{
// If mapper is not dependent on time we're ok to evaluate
this->evaluate();
canEvaluate = true;
}
}
if (refPointValueFunc_)
{
if (refPointValueFunc_().constant())
// If mapper is not dependent on time we're ok to evaluate
if (refPointValueFunc_->constant())
{
// If mapper is not dependent on time we're ok to evaluate
this->evaluate();
canEvaluate = true;
}
}
if (canEvaluate)
{
this->evaluate();
}
}
@ -208,8 +205,7 @@ void Foam::uniformFixedValuePointPatchField<Type>::rmap
{
fixedValuePointPatchField<Type>::rmap(ptf, addr);
const uniformFixedValuePointPatchField& tiptf =
refCast<const uniformFixedValuePointPatchField>(ptf);
const auto& tiptf = refCast<const uniformFixedValuePointPatchField>(ptf);
if (refValueFunc_ && tiptf.refValueFunc_)
{
@ -249,7 +245,7 @@ write(Ostream& os) const
{
refValueFunc_->writeData(os);
}
if (refPointValueFunc_)
else if (refPointValueFunc_)
{
refPointValueFunc_->writeData(os);
}

View File

@ -92,7 +92,8 @@ class uniformFixedValuePointPatchField
// Private Member Functions
static const polyPatch* getPatch(const pointPatch&);
//- Find polyPatch with the same name as the pointPatch
static const polyPatch* getPolyPatch(const pointPatch& p);
public:
@ -127,19 +128,22 @@ public:
const pointPatchFieldMapper&
);
//- Construct as copy
uniformFixedValuePointPatchField
(
const uniformFixedValuePointPatchField<Type>&
);
//- Construct as copy setting internal field reference
//- Copy construct with internal field reference
uniformFixedValuePointPatchField
(
const uniformFixedValuePointPatchField<Type>&,
const DimensionedField<Type, pointMesh>&
);
//- Copy construct
uniformFixedValuePointPatchField
(
const uniformFixedValuePointPatchField<Type>& pfld
)
:
uniformFixedValuePointPatchField<Type>(pfld, pfld.internalField())
{}
//- Return a clone
virtual autoPtr<pointPatchField<Type>> clone() const

View File

@ -295,18 +295,12 @@ bool Foam::movingConeTopoFvMesh::init(const bool doInit)
curLeft_ = average
(
faceZones()
[
faceZones().findZoneID("leftExtrusionFaces")
]().localPoints()
faceZones()["leftExtrusionFaces"].patch().localPoints()
).x() - SMALL;
curRight_ = average
(
faceZones()
[
faceZones().findZoneID("rightExtrusionFaces")
]().localPoints()
faceZones()["rightExtrusionFaces"].patch().localPoints()
).x() + SMALL;
motionMask_ = vertexMarkup
@ -407,18 +401,12 @@ bool Foam::movingConeTopoFvMesh::update()
curLeft_ = average
(
faceZones()
[
faceZones().findZoneID("leftExtrusionFaces")
]().localPoints()
faceZones()["leftExtrusionFaces"].patch().localPoints()
).x() - SMALL;
curRight_ = average
(
faceZones()
[
faceZones().findZoneID("rightExtrusionFaces")
]().localPoints()
faceZones()["rightExtrusionFaces"].patch().localPoints()
).x() + SMALL;
return true;