Merge branch 'patch_specializations' into 'develop'

Simplify specialization of patch fields, consolidate boundary evaluation

See merge request Development/openfoam!743
This commit is contained in:
Mattijs Janssens
2025-05-29 11:20:25 +00:00
56 changed files with 689 additions and 974 deletions

View File

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

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

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

@ -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.
@ -64,6 +64,8 @@ bool Foam::GeometricBoundaryField<Type, PatchField, GeoMesh>::checkConsistency
//Note: areaFields (finiteArea) do not have manipulatedMatrix() flag. TBD.
//boolList oldManipulated(this->size());
label nEvaluated(0);
for (auto& pfld : bfld)
{
if (isA<CheckPatchFieldType>(pfld))
@ -72,19 +74,24 @@ bool Foam::GeometricBoundaryField<Type, PatchField, GeoMesh>::checkConsistency
oldUpdated[patchi] = pfld.updated();
oldBfld[patchi] = pfld;
//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,13 +103,15 @@ 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))
@ -110,16 +119,23 @@ bool Foam::GeometricBoundaryField<Type, PatchField, GeoMesh>::checkConsistency
const label patchi = pfld.patch().index();
const auto& oldPfld = oldBfld[patchi];
forAll(pfld, facei)
bool localOk(true);
if (allOk)
{
if (mag(pfld[facei]-oldPfld[facei]) > tol)
// Only check once
forAll(pfld, facei)
{
ok = false;
break;
if (mag(pfld[facei]-oldPfld[facei]) > tol)
{
allOk = false;
localOk = false;
break;
}
}
}
if (!ok)
if (!localOk)
{
if (doExit)
{
@ -133,7 +149,7 @@ bool Foam::GeometricBoundaryField<Type, PatchField, GeoMesh>::checkConsistency
<< ". Average of evaluated field = "
<< average(pfld)
<< ". Difference:" << average(pfld-oldPfld)
<< ". Tolerance:" << tol
<< ". Tolerance:" << tol << endl
<< exit(FatalError);
}
else
@ -148,25 +164,13 @@ bool Foam::GeometricBoundaryField<Type, PatchField, GeoMesh>::checkConsistency
<< ". Average of evaluated field = "
<< average(pfld)
<< ". Difference:" << average(pfld-oldPfld)
<< ". Tolerance:" << tol
<< endl;
// Skip other patches
break;
<< ". Tolerance:" << tol << endl;
}
}
}
}
// Restore bfld, updated
for (auto& pfld : bfld)
{
if (isA<CheckPatchFieldType>(pfld))
{
const label patchi = pfld.patch().index();
// Restore bfld, updated
pfld.setUpdated(oldUpdated[patchi]);
Field<Type>& vals = pfld;
vals = std::move(oldBfld[patchi]);
static_cast<Field<Type>&>(pfld) = std::move(oldBfld[patchi]);
//pfld.setManipulated(oldManipulated[patchi]);
}
}
@ -176,10 +180,10 @@ bool Foam::GeometricBoundaryField<Type, PatchField, GeoMesh>::checkConsistency
const auto& pfld0 = this->operator[](0);
PoutInFunction
<< " Result of checking for field "
<< pfld0.internalField().name() << " : " << ok << endl;
<< pfld0.internalField().name() << " : " << allOk << endl;
}
return ok;
return allOk;
}
@ -626,6 +630,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 +638,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 +787,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

@ -205,8 +205,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

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

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

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

@ -45,7 +45,6 @@ $(faPatchFields)/faPatchField/faPatchFieldBase.C
$(faPatchFields)/faPatchField/faPatchFields.C
basicFaPatchFields = $(faPatchFields)/basic
$(basicFaPatchFields)/basicSymmetry/basicSymmetryFaPatchFields.C
$(basicFaPatchFields)/calculated/calculatedFaPatchFields.C
$(basicFaPatchFields)/extrapolatedCalculated/extrapolatedCalculatedFaPatchFields.C
$(basicFaPatchFields)/coupled/coupledFaPatchFields.C

View File

@ -93,16 +93,12 @@ Foam::wedgeFaPatch::wedgeFaPatch
<< this->name() << exit(FatalError);
}
const auto* wedgePtr = isA<wedgePolyPatch>
wedgePolyPatchPtr_ = isA<wedgePolyPatch>
(
bm.mesh().mesh().boundaryMesh()[ngbPolyPatchIndex()]
);
if (wedgePtr)
{
wedgePolyPatchPtr_ = wedgePtr;
}
else
if (!wedgePolyPatchPtr_)
{
FatalErrorInFunction
<< "Neighbour polyPatch is not of type "

View File

@ -77,7 +77,9 @@ public:
//- Runtime type information
TypeName("wedge");
//- Construct from dictionary
//- Construct from dictionary.
// Fatal if ngbPolyPatchIndex is not defined
// or does not correspond to a wedgePolyPatch
wedgeFaPatch
(
const word& name,
@ -97,25 +99,25 @@ public:
// Access
//- Return axis of the wedge
const vector& axis() const
const vector& axis() const noexcept
{
return wedgePolyPatchPtr_->axis();
}
//- Return plane normal between the wedge boundaries
const vector& centreNormal() const
const vector& centreNormal() const noexcept
{
return wedgePolyPatchPtr_->centreNormal();
}
//- Return face transformation tensor
const tensor& edgeT() const
const tensor& edgeT() const noexcept
{
return wedgePolyPatchPtr_->faceT();
}
//- Return neighbour-cell transformation tensor
const tensor& faceT() const
const tensor& faceT() const noexcept
{
return wedgePolyPatchPtr_->cellT();
}

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -85,13 +86,25 @@ template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::basicSymmetryFaPatchField<Type>::snGrad() const
{
const vectorField nHat(this->patch().edgeNormals());
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type : treat like zero-gradient
return tmp<Field<Type>>::New(this->size(), Foam::zero{});
}
else
{
tmp<vectorField> nHat = this->patch().edgeNormals();
return
(
transform(I - 2.0*sqr(nHat), this->patchInternalField())
- this->patchInternalField()
)*(this->patch().deltaCoeffs()/2.0);
const auto& dc = this->patch().deltaCoeffs();
const Field<Type> pif(this->patchInternalField());
return
(
(0.5*dc)
* (transform(I - 2.0*sqr(nHat), pif) - pif)
);
}
}
@ -103,14 +116,22 @@ void Foam::basicSymmetryFaPatchField<Type>::evaluate(const Pstream::commsTypes)
this->updateCoeffs();
}
const vectorField nHat(this->patch().edgeNormals());
Field<Type>::operator=
(
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type : treat like zero-gradient
this->extrapolateInternal();
}
else
{
tmp<vectorField> nHat = this->patch().edgeNormals();
const Field<Type> pif(this->patchInternalField());
Field<Type>::operator=
(
this->patchInternalField()
+ transform(I - 2.0*sqr(nHat), this->patchInternalField())
)/2.0
);
0.5*(pif + transform(I - 2.0*sqr(nHat), pif))
);
}
transformFaPatchField<Type>::evaluate();
}

View File

@ -143,18 +143,6 @@ public:
};
// * * * * * * * * * * * Template Specialisations * * * * * * * * * * * * * //
template<>
tmp<scalarField> basicSymmetryFaPatchField<scalar>::snGrad() const;
template<>
void basicSymmetryFaPatchField<scalar>::evaluate
(
const Pstream::commsTypes commsType
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -1,59 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "basicSymmetryFaPatchField.H"
#include "areaFields.H"
// No run-time selection
// * * * * * * * * * * * * * * * Specialisations * * * * * * * * * * * * * * //
template<>
Foam::tmp<Foam::scalarField>
Foam::basicSymmetryFaPatchField<Foam::scalar>::snGrad() const
{
return tmp<scalarField>::New(size(), Zero);
}
template<>
void Foam::basicSymmetryFaPatchField<Foam::scalar>::evaluate
(
const Pstream::commsTypes
)
{
if (!updated())
{
updateCoeffs();
}
scalarField::operator=(patchInternalField());
transformFaPatchField<scalar>::evaluate();
}
// ************************************************************************* //

View File

@ -37,7 +37,7 @@ Foam::transformFaPatchField<Type>::transformFaPatchField
const DimensionedField<Type, areaMesh>& iF
)
:
faPatchField<Type>(p, iF)
faPatchField<Type>(p, iF)
{}

View File

@ -148,12 +148,6 @@ public:
};
// * * * * * * * * * * * Template Specialisations * * * * * * * * * * * * * //
template<>
tmp<scalarField> transformFaPatchField<scalar>::gradientInternalCoeffs() const;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -37,14 +37,4 @@ namespace Foam
}
// * * * * * * * * * * * * * * * Specialisations * * * * * * * * * * * * * * //
template<>
Foam::tmp<Foam::scalarField>
Foam::transformFaPatchField<Foam::scalar>::gradientInternalCoeffs() const
{
return tmp<scalarField>::New(size(), Zero);
}
// ************************************************************************* //

View File

@ -104,13 +104,25 @@ Foam::wedgeFaPatchField<Type>::wedgeFaPatchField
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::wedgeFaPatchField<Type>::snGrad() const
{
const Field<Type> pif (this->patchInternalField());
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type: treat like zero-gradient
return tmp<Field<Type>>::New(this->size(), Foam::zero{});
}
else
{
const auto& rot = refCast<const wedgeFaPatch>(this->patch()).faceT();
return
(
transform(refCast<const wedgeFaPatch>(this->patch()).faceT(), pif)
- pif
)*(0.5*this->patch().deltaCoeffs());
const Field<Type> pif(this->patchInternalField());
const auto& dc = this->patch().deltaCoeffs();
return
(
(0.5*dc)
* (transform(rot, pif) - pif)
);
}
}
@ -122,14 +134,20 @@ void Foam::wedgeFaPatchField<Type>::evaluate(const Pstream::commsTypes)
this->updateCoeffs();
}
faPatchField<Type>::operator==
(
transform
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type: treat like zero-gradient
this->extrapolateInternal();
}
else
{
const auto& rot = refCast<const wedgeFaPatch>(this->patch()).edgeT();
faPatchField<Type>::operator==
(
refCast<const wedgeFaPatch>(this->patch()).edgeT(),
this->patchInternalField()
)
);
transform(rot, this->patchInternalField())
);
}
}

View File

@ -133,18 +133,6 @@ public:
};
// * * * * * * * * * * * Template Specialisations * * * * * * * * * * * * * //
template<>
tmp<scalarField> wedgeFaPatchField<scalar>::snGrad() const;
template<>
void wedgeFaPatchField<scalar>::evaluate
(
const Pstream::commsTypes commsType
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -36,26 +36,4 @@ namespace Foam
makeFaPatchFields(wedge);
}
// * * * * * * * * * * * * * * * Specialisations * * * * * * * * * * * * * * //
template<>
Foam::tmp<Foam::scalarField>
Foam::wedgeFaPatchField<Foam::scalar>::snGrad() const
{
return tmp<scalarField>::New(size(), Zero);
}
template<>
void Foam::wedgeFaPatchField<Foam::scalar>::evaluate(const Pstream::commsTypes)
{
if (!updated())
{
updateCoeffs();
}
this->operator==(patchInternalField());
}
// ************************************************************************* //

View File

@ -128,7 +128,6 @@ $(fvPatchFields)/fvPatchField/fvPatchFieldBase.C
$(fvPatchFields)/fvPatchField/fvPatchFields.C
basicFvPatchFields = $(fvPatchFields)/basic
$(basicFvPatchFields)/basicSymmetry/basicSymmetryFvPatchFields.C
$(basicFvPatchFields)/calculated/calculatedFvPatchFields.C
$(basicFvPatchFields)/extrapolatedCalculated/extrapolatedCalculatedFvPatchFields.C
$(basicFvPatchFields)/coupled/coupledFvPatchFields.C

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.
@ -85,13 +86,25 @@ template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::basicSymmetryFvPatchField<Type>::snGrad() const
{
tmp<vectorField> nHat = this->patch().nf();
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type : treat like zero-gradient
return tmp<Field<Type>>::New(this->size(), Foam::zero{});
}
else
{
tmp<vectorField> nHat = this->patch().nf();
const Field<Type> iF(this->patchInternalField());
const auto& dc = this->patch().deltaCoeffs();
return
(transform(I - 2.0*sqr(nHat), iF) - iF)
*(this->patch().deltaCoeffs()/2.0);
const Field<Type> pif(this->patchInternalField());
return
(
(0.5*dc)
* (transform(I - 2.0*sqr(nHat), pif) - pif)
);
}
}
@ -103,14 +116,22 @@ void Foam::basicSymmetryFvPatchField<Type>::evaluate(const Pstream::commsTypes)
this->updateCoeffs();
}
tmp<vectorField> nHat = this->patch().nf();
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type : treat like zero-gradient
this->extrapolateInternal();
}
else
{
tmp<vectorField> nHat = this->patch().nf();
const Field<Type> iF(this->patchInternalField());
const Field<Type> pif(this->patchInternalField());
Field<Type>::operator=
(
(iF + transform(I - 2.0*sqr(nHat), iF))/2.0
);
Field<Type>::operator=
(
0.5*(pif + transform(I - 2.0*sqr(nHat), pif))
);
}
transformFvPatchField<Type>::evaluate();
}

View File

@ -139,18 +139,6 @@ public:
};
// * * * * * * * * * * * Template Specialisations * * * * * * * * * * * * * //
template<>
tmp<scalarField> basicSymmetryFvPatchField<scalar>::snGrad() const;
template<>
void basicSymmetryFvPatchField<scalar>::evaluate
(
const Pstream::commsTypes commsType
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -1,59 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2013 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "basicSymmetryFvPatchField.H"
#include "volFields.H"
// No run-time selection
// * * * * * * * * * * * * * * * Specialisations * * * * * * * * * * * * * * //
template<>
Foam::tmp<Foam::scalarField>
Foam::basicSymmetryFvPatchField<Foam::scalar>::snGrad() const
{
return tmp<scalarField>::New(size(), Zero);
}
template<>
void Foam::basicSymmetryFvPatchField<Foam::scalar>::evaluate
(
const Pstream::commsTypes
)
{
if (!updated())
{
updateCoeffs();
}
scalarField::operator=(patchInternalField());
transformFvPatchField<scalar>::evaluate();
}
// ************************************************************************* //

View File

@ -157,18 +157,6 @@ public:
};
// * * * * * * * * * * * Template Specialisations * * * * * * * * * * * * * //
template<>
tmp<scalarField> transformFvPatchField<scalar>::valueInternalCoeffs
(
const tmp<scalarField>&
) const;
template<>
tmp<scalarField> transformFvPatchField<scalar>::gradientInternalCoeffs() const;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -37,25 +37,4 @@ namespace Foam
}
// * * * * * * * * * * * * * * * Specialisations * * * * * * * * * * * * * * //
template<>
Foam::tmp<Foam::scalarField>
Foam::transformFvPatchField<Foam::scalar>::valueInternalCoeffs
(
const tmp<scalarField>&
) const
{
return tmp<scalarField>::New(size(), 1.0);
}
template<>
Foam::tmp<Foam::scalarField>
Foam::transformFvPatchField<Foam::scalar>::gradientInternalCoeffs() const
{
return tmp<scalarField>::New(size(), Zero);
}
// ************************************************************************* //

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013-2016 OpenFOAM Foundation
Copyright (C) 2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,7 +28,6 @@ License
#include "symmetryPlaneFvPatchField.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Type>
@ -120,13 +120,25 @@ template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::symmetryPlaneFvPatchField<Type>::snGrad() const
{
vector nHat(symmetryPlanePatch_.n());
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type: treat like zero-gradient
return tmp<Field<Type>>::New(this->size(), Foam::zero{});
}
else
{
const symmTensor rot(I - 2.0*sqr(symmetryPlanePatch_.n()));
const Field<Type> iF(this->patchInternalField());
const Field<Type> pif(this->patchInternalField());
return
(transform(I - 2.0*sqr(nHat), iF) - iF)
*(this->patch().deltaCoeffs()/2.0);
const auto& dc = this->patch().deltaCoeffs();
return
(
(0.5*dc)
* (transform(rot, pif) - pif)
);
}
}
@ -138,14 +150,19 @@ void Foam::symmetryPlaneFvPatchField<Type>::evaluate(const Pstream::commsTypes)
this->updateCoeffs();
}
vector nHat(symmetryPlanePatch_.n());
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type: treat like zero-gradient
this->extrapolateInternal();
}
else
{
const symmTensor rot(I - 2.0*sqr(symmetryPlanePatch_.n()));
const Field<Type> iF(this->patchInternalField());
const Field<Type> pif(this->patchInternalField());
Field<Type>::operator=
(
(iF + transform(I - 2.0*sqr(nHat), iF))/2.0
);
Field<Type>::operator=(0.5*(pif + transform(rot, pif)));
}
transformFvPatchField<Type>::evaluate();
}

View File

@ -49,8 +49,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef symmetryPlaneFvPatchField_H
#define symmetryPlaneFvPatchField_H
#ifndef Foam_symmetryPlaneFvPatchField_H
#define Foam_symmetryPlaneFvPatchField_H
#include "basicSymmetryFvPatchField.H"
#include "symmetryPlaneFvPatch.H"
@ -61,7 +61,7 @@ namespace Foam
{
/*---------------------------------------------------------------------------*\
Class symmetryPlaneFvPatchField Declaration
Class symmetryPlaneFvPatchField Declaration
\*---------------------------------------------------------------------------*/
template<class Type>
@ -153,18 +153,6 @@ public:
};
// * * * * * * * * * * * Template Specialisations * * * * * * * * * * * * * //
template<>
tmp<scalarField> symmetryPlaneFvPatchField<scalar>::snGrad() const;
template<>
void symmetryPlaneFvPatchField<scalar>::evaluate
(
const Pstream::commsTypes commsType
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -37,30 +37,4 @@ namespace Foam
}
// * * * * * * * * * * * * * * * Specialisations * * * * * * * * * * * * * * //
template<>
Foam::tmp<Foam::scalarField>
Foam::symmetryPlaneFvPatchField<Foam::scalar>::snGrad() const
{
return tmp<scalarField>::New(size(), Zero);
}
template<>
void Foam::symmetryPlaneFvPatchField<Foam::scalar>::evaluate
(
const Pstream::commsTypes
)
{
if (!updated())
{
updateCoeffs();
}
scalarField::operator=(patchInternalField());
transformFvPatchField<scalar>::evaluate();
}
// ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2024 OpenCFD Ltd.
Copyright (C) 2024-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -119,12 +119,25 @@ Foam::wedgeFvPatchField<Type>::wedgeFvPatchField
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::wedgeFvPatchField<Type>::snGrad() const
{
const Field<Type> pif(this->patchInternalField());
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type : treat like zero-gradient
return tmp<Field<Type>>::New(this->size(), Foam::zero{});
}
else
{
const auto& rot = refCast<const wedgeFvPatch>(this->patch()).cellT();
return
(
transform(refCast<const wedgeFvPatch>(this->patch()).cellT(), pif) - pif
)*(0.5*this->patch().deltaCoeffs());
const Field<Type> pif(this->patchInternalField());
const auto& dc = this->patch().deltaCoeffs();
return
(
(0.5*dc)
* (transform(rot, pif) - pif)
);
}
}
@ -136,14 +149,20 @@ void Foam::wedgeFvPatchField<Type>::evaluate(const Pstream::commsTypes)
this->updateCoeffs();
}
fvPatchField<Type>::operator==
(
transform
if constexpr (!is_rotational_vectorspace_v<Type>)
{
// Rotational-invariant type : treat like zero-gradient
this->extrapolateInternal();
}
else
{
const auto& rot = refCast<const wedgeFvPatch>(this->patch()).faceT();
fvPatchField<Type>::operator==
(
refCast<const wedgeFvPatch>(this->patch()).faceT(),
this->patchInternalField()
)
);
transform(rot, this->patchInternalField())
);
}
}

View File

@ -138,7 +138,7 @@ public:
}
// Member functions
// Member Functions
//- Return gradient at boundary
virtual tmp<Field<Type>> snGrad() const;
@ -154,18 +154,6 @@ public:
};
// * * * * * * * * * * * Template Specialisations * * * * * * * * * * * * * //
template<>
tmp<scalarField> wedgeFvPatchField<scalar>::snGrad() const;
template<>
void wedgeFvPatchField<scalar>::evaluate
(
const Pstream::commsTypes commsType
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -37,29 +37,4 @@ namespace Foam
}
// * * * * * * * * * * * * * * * Specialisations * * * * * * * * * * * * * * //
template<>
Foam::tmp<Foam::scalarField>
Foam::wedgeFvPatchField<Foam::scalar>::snGrad() const
{
return tmp<scalarField>::New(size(), Zero);
}
template<>
void Foam::wedgeFvPatchField<Foam::scalar>::evaluate
(
const Pstream::commsTypes
)
{
if (!updated())
{
updateCoeffs();
}
this->operator==(patchInternalField());
}
// ************************************************************************* //

View File

@ -33,23 +33,23 @@ License
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
defineTypeNameAndDebug(wedgeFvPatch, 0);
addToRunTimeSelectionTable(fvPatch, wedgeFvPatch, polyPatch);
} // End namespace Foam
// * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * * * * //
wedgeFvPatch::wedgeFvPatch(const polyPatch& patch, const fvBoundaryMesh& bm)
Foam::wedgeFvPatch::wedgeFvPatch
(
const polyPatch& patch,
const fvBoundaryMesh& bm
)
:
fvPatch(patch, bm),
wedgePolyPatch_(refCast<const wedgePolyPatch>(patch))
{}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -34,8 +34,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef wedgeFvPatch_H
#define wedgeFvPatch_H
#ifndef Foam_wedgeFvPatch_H
#define Foam_wedgeFvPatch_H
#include "fvPatch.H"
#include "wedgePolyPatch.H"
@ -53,7 +53,7 @@ class wedgeFvPatch
:
public fvPatch
{
// Private data
// Private Data
const wedgePolyPatch& wedgePolyPatch_;
@ -70,21 +70,21 @@ public:
wedgeFvPatch(const polyPatch& patch, const fvBoundaryMesh& bm);
// Member functions
// Member Functions
// Access
// Access
//- Return face transformation tensor
const tensor& faceT() const
{
return wedgePolyPatch_.faceT();
}
//- Return face transformation tensor
const tensor& faceT() const noexcept
{
return wedgePolyPatch_.faceT();
}
//- Return neighbour-cell transformation tensor
const tensor& cellT() const
{
return wedgePolyPatch_.cellT();
}
//- Return neighbour-cell transformation tensor
const tensor& cellT() const noexcept
{
return wedgePolyPatch_.cellT();
}
};

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2023 OpenCFD Ltd.
Copyright (C) 2023-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -88,12 +88,14 @@ bool Foam::patchDistMethods::meshWaveAddressing::correct
// since the supplied options (wall patchIDs and correctWalls)
// are not assumed to be different from the defaults of other usage.
const labelList patchIds(patchIDs_.sortedToc());
// Calculate distance and addressing
const auto& wDist = wallDistAddressing::New
(
"wall",
mesh_,
patchIDs_.sortedToc(),
patchIds,
correctWalls_
);
@ -102,31 +104,18 @@ bool Foam::patchDistMethods::meshWaveAddressing::correct
// Note: copying value only so might not be consistent with supplied
// patch types (e.g. zeroGradient when called from wallDist). Assume
// only affected ones are the supplied patches ...
{
auto& bfld = y.boundaryFieldRef();
const label startOfRequests = UPstream::nRequests();
for (const label patchi : patchIDs_)
{
bfld[patchi].initEvaluate(UPstream::commsTypes::nonBlocking);
}
// Wait for outstanding requests
UPstream::waitRequests(startOfRequests);
for (const label patchi : patchIDs_)
{
bfld[patchi].evaluate(UPstream::commsTypes::nonBlocking);
}
}
y.boundaryFieldRef().evaluateSelected(patchIds);
// Only calculate n if the field is defined
if (notNull(n))
{
for (const label patchi : patchIDs_)
auto& bfld = n.boundaryFieldRef();
for (const label patchi : patchIds)
{
auto& pnf = n.boundaryFieldRef()[patchi];
pnf == pnf.patch().nf();
bfld[patchi] == bfld[patchi].patch().nf();
}
// No problem with inconsistency as for y (see above) since doing

View File

@ -39,79 +39,17 @@ License
// GeometricField<Type, fvPatchField, volMesh>& fld
//) const
//{
// auto& fldBf = fld.boundaryFieldRef();
//
// const UPstream::commsTypes commsType = UPstream::defaultCommsType;
// const label startOfRequests = UPstream::nRequests();
//
// if
// fld.boundaryFieldRef().evaluate_if
// (
// commsType == UPstream::commsTypes::blocking
// || commsType == UPstream::commsTypes::nonBlocking
// )
// {
// forAll(fldBf, patchi)
// [](const auto& pfld) -> bool
// {
// fvPatchField<Type>& tgtField = fldBf[patchi];
//
// if
// return
// (
// tgtField.type() == tgtField.patch().patch().type()
// && polyPatch::constraintType(tgtField.patch().patch().type())
// )
// {
// tgtField.initEvaluate(commsType);
// }
// pfld.type() == pfld.patch().patch().type()
// && polyPatch::constraintType(pfld.patch().patch().type())
// );
// }
//
// // Wait for outstanding requests
// if (commsType == UPstream::commsTypes::nonBlocking)
// {
// UPstream::waitRequests(startOfRequests);
// }
//
// forAll(fldBf, patchi)
// {
// fvPatchField<Type>& tgtField = fldBf[patchi];
//
// if
// (
// tgtField.type() == tgtField.patch().patch().type()
// && polyPatch::constraintType(tgtField.patch().patch().type())
// )
// {
// tgtField.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;
//
// fvPatchField<Type>& tgtField = fldBf[patchi];
//
// if
// (
// tgtField.type() == tgtField.patch().patch().type()
// && polyPatch::constraintType(tgtField.patch().patch().type())
// )
// {
// if (schedEval.init)
// {
// tgtField.initEvaluate(commsType);
// }
// else
// {
// tgtField.evaluate(commsType);
// }
// }
// }
// }
// );
//}
template<class Type>

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2022 OpenCFD Ltd.
Copyright (C) 2016-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -36,72 +36,18 @@ void Foam::functionObjects::mapFields::evaluateConstraintTypes
GeometricField<Type, fvPatchField, volMesh>& fld
) const
{
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

@ -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.
@ -182,31 +182,16 @@ void Foam::cellCellStencil::correctBoundaryConditions
GeoField& psi
)
{
// Version of GeoField::correctBoundaryConditions that exclude evaluation
// of oversetFvPatchFields
// correctBoundaryConditions excluding oversetFvPatchFields
auto& bfld = psi.boundaryFieldRef();
const label startOfRequests = UPstream::nRequests();
for (auto& pfld : bfld)
{
if (!isA<SuppressBC>(pfld))
psi.boundaryFieldRef().evaluate_if
(
[](const auto& pfld)
{
pfld.initEvaluate(UPstream::commsTypes::nonBlocking);
}
}
// Wait for outstanding requests (non-blocking)
UPstream::waitRequests(startOfRequests);
for (auto& pfld : bfld)
{
if (!isA<SuppressBC>(pfld))
{
pfld.evaluate(UPstream::commsTypes::nonBlocking);
}
}
return (!isA<SuppressBC>(pfld));
},
UPstream::commsTypes::nonBlocking
);
}

View File

@ -1033,8 +1033,9 @@ bool Foam::cellCellStencils::cellVolumeWeight::update()
oversetFvMeshBase::correctBoundaryConditions
<
volScalarField,
oversetFvPatchField<scalar>
>(cellInterpolationWeight_.boundaryFieldRef(), false);
oversetFvPatchField<scalar>,
false
>(cellInterpolationWeight_.boundaryFieldRef());
DynamicList<label> interpolationCells;
forAll(cellStencil_, cellI)

View File

@ -2351,8 +2351,9 @@ bool Foam::cellCellStencils::inverseDistance::update()
oversetFvMeshBase::correctBoundaryConditions
<
volScalarField,
oversetFvPatchField<scalar>
>(cellInterpolationWeight_.boundaryFieldRef(), false);
oversetFvPatchField<scalar>,
false
>(cellInterpolationWeight_.boundaryFieldRef());
if ((debug & 2) && mesh_.time().writeTime())
@ -2435,8 +2436,9 @@ bool Foam::cellCellStencils::inverseDistance::update()
oversetFvMeshBase::correctBoundaryConditions
<
volScalarField,
oversetFvPatchField<scalar>
>(tfld.ref().boundaryFieldRef(), false);
oversetFvPatchField<scalar>,
false
>(tfld.ref().boundaryFieldRef());
tfld().write();
}
@ -2450,8 +2452,9 @@ bool Foam::cellCellStencils::inverseDistance::update()
oversetFvMeshBase::correctBoundaryConditions
<
volScalarField,
oversetFvPatchField<scalar>
>(tfld.ref().boundaryFieldRef(), false);
oversetFvPatchField<scalar>,
false
>(tfld.ref().boundaryFieldRef());
tfld().write();
}

View File

@ -1059,8 +1059,9 @@ bool Foam::cellCellStencils::trackingInverseDistance::update()
oversetFvMeshBase::correctBoundaryConditions
<
volScalarField,
oversetFvPatchField<scalar>
>(cellInterpolationWeight_.boundaryFieldRef(), false);
oversetFvPatchField<scalar>,
false
>(cellInterpolationWeight_.boundaryFieldRef());
if ((debug & 2) && mesh_.time().writeTime())

View File

@ -445,11 +445,12 @@ void Foam::oversetFvMeshBase::writeAgglomeration
fld[celli] = cellToCoarse[celli];
}
fld /= max(fld);
correctBoundaryConditions
oversetFvMeshBase::correctBoundaryConditions
<
volScalarField,
oversetFvPatchField<scalar>
>(scalarAgglomeration.boundaryFieldRef(), false);
oversetFvPatchField<scalar>,
false
>(scalarAgglomeration.boundaryFieldRef());
scalarAgglomeration.write();
Info<< "Writing initial cell distribution to "
@ -503,11 +504,12 @@ void Foam::oversetFvMeshBase::writeAgglomeration
//{
// fld /= max(fld);
//}
correctBoundaryConditions
oversetFvMeshBase::correctBoundaryConditions
<
volScalarField,
oversetFvPatchField<scalar>
>(scalarAgglomeration.boundaryFieldRef(), false);
oversetFvPatchField<scalar>,
false
>(scalarAgglomeration.boundaryFieldRef());
scalarAgglomeration.write();
}
}

View File

@ -257,13 +257,12 @@ public:
template<class GeoField>
static void checkCoupledBC(const GeoField& fld);
//- Correct boundary conditions of certain type (typeOnly = true)
//- or explicitly not of the type (typeOnly = false)
template<class GeoField, class PatchType>
//- Correct boundary conditions of certain type (TypeOnly = true)
//- or explicitly not of the type (TypeOnly = false)
template<class GeoField, class PatchType, bool TypeOnly>
static void correctBoundaryConditions
(
typename GeoField::Boundary& bfld,
const bool typeOnly
typename GeoField::Boundary& bfld
);
//- Determine normalisation for interpolation. This equals the

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2014-2022 OpenCFD Ltd.
Copyright (C) 2014-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -73,44 +73,31 @@ void Foam::oversetFvMeshBase::scaleConnection
}
}
template<class GeoField, class PatchType>
template<class GeoField, class PatchType, bool TypeOnly>
void Foam::oversetFvMeshBase::correctBoundaryConditions
(
typename GeoField::Boundary& bfld,
const bool typeOnly
typename GeoField::Boundary& bfld
)
{
// Alternative (C++14)
//
// bfld.evaluate_if
// (
// [typeOnly](const auto& pfld) -> bool
// {
// return (typeOnly == bool(isA<PatchType>(pfld)));
// },
// UPstream::defaultCommsType
// );
const UPstream::commsTypes commsType = UPstream::defaultCommsType;
const label startOfRequests = UPstream::nRequests();
for (auto& pfld : bfld)
if constexpr (TypeOnly)
{
if (typeOnly == bool(isA<PatchType>(pfld)))
{
pfld.initEvaluate(commsType);
}
}
// Wait for outstanding requests (non-blocking)
UPstream::waitRequests(startOfRequests);
for (auto& pfld : bfld)
bfld.evaluate_if
(
[](const auto& pfld)
{
return (bool(isA<PatchType>(pfld)));
}
);
}
else
{
if (typeOnly == bool(isA<PatchType>(pfld)))
{
pfld.evaluate(commsType);
}
bfld.evaluate_if
(
[](const auto& pfld)
{
return (!bool(isA<PatchType>(pfld)));
}
);
}
}
@ -766,11 +753,12 @@ Foam::SolverPerformance<Type> Foam::oversetFvMeshBase::solveOverset
dimensionedScalar(dimless, Zero)
);
scale.ref().field() = norm;
correctBoundaryConditions
oversetFvMeshBase::correctBoundaryConditions
<
volScalarField,
oversetFvPatchField<scalar>
>(scale.boundaryFieldRef(), false);
oversetFvPatchField<scalar>,
false
>(scale.boundaryFieldRef());
scale.write();
if (debug)
@ -802,11 +790,12 @@ Foam::SolverPerformance<Type> Foam::oversetFvMeshBase::solveOverset
m.boundaryManipulate(bpsi);
// Swap psi values so added patches have patchNeighbourField
correctBoundaryConditions<GeoField, calculatedProcessorFvPatchField<Type>>
(
bpsi,
oversetFvMeshBase::correctBoundaryConditions
<
GeoField,
calculatedProcessorFvPatchField<Type>,
true
);
>(bpsi);
// Use lower level solver
//SolverPerformance<Type> s(dynamicMotionSolverFvMesh::solve(m, dict));
@ -993,32 +982,8 @@ void Foam::oversetFvMeshBase::write
template<class GeoField>
void Foam::oversetFvMeshBase::correctCoupledBoundaryConditions(GeoField& fld)
{
auto& bfld = fld.boundaryFieldRef();
const UPstream::commsTypes commsType = UPstream::defaultCommsType;
const label startOfRequests = UPstream::nRequests();
for (auto& pfld : bfld)
{
if (pfld.coupled())
{
//Pout<< "initEval of " << pfld.patch().name() << endl;
pfld.initEvaluate(commsType);
}
}
// Wait for outstanding requests (non-blocking)
UPstream::waitRequests(startOfRequests);
for (auto& pfld : bfld)
{
if (pfld.coupled())
{
//Pout<< "eval of " << pfld.patch().name() << endl;
pfld.evaluate(commsType);
}
}
// Evaluate all coupled fields
fld.boundaryFieldRef().template evaluateCoupled<void>();
}
@ -1030,13 +995,13 @@ void Foam::oversetFvMeshBase::checkCoupledBC(const GeoField& fld)
GeoField fldCorr(fld.name()+"_correct", fld);
correctCoupledBoundaryConditions(fldCorr);
const typename GeoField::Boundary& bfld = fld.boundaryField();
const typename GeoField::Boundary& bfldCorr = fldCorr.boundaryField();
const auto& bfld = fld.boundaryField();
const auto& bfldCorr = fldCorr.boundaryField();
forAll(bfld, patchi)
{
const typename GeoField::Patch& pfld = bfld[patchi];
const typename GeoField::Patch& pfldCorr = bfldCorr[patchi];
const auto& pfld = bfld[patchi];
const auto& pfldCorr = bfldCorr[patchi];
Pout<< "Patch:" << pfld.patch().name() << endl;

View File

@ -1,5 +1,5 @@
#-------------------------------*- makefile -*---------------------------------
WM_VERSION = OPENFOAM=2501
WM_VERSION = OPENFOAM=2502
AR = ar
ARFLAGS = cr