ENH: DimensionedField/GeometricField provision for additional storage

- base DimensionedField on DynamicField instead of Field to allow
  convenient resizing

- initial infrastructure for unified GeometricField handling with
  the boundaryEvaluate() method

Co-authored-by: <Mark.Olesen@keysight.com>
This commit is contained in:
mattijs
2025-03-29 20:49:08 +00:00
committed by Mark Olesen
parent 53af711c6a
commit c108153d06
5 changed files with 159 additions and 43 deletions

View File

@ -77,7 +77,7 @@ Foam::DimensionedField<Type, GeoMesh>::DimensionedField
) )
: :
regIOobject(io), regIOobject(io),
Field<Type>(field), DynamicField<Type>(field),
mesh_(mesh), mesh_(mesh),
dimensions_(dims) dimensions_(dims)
{ {
@ -95,7 +95,7 @@ Foam::DimensionedField<Type, GeoMesh>::DimensionedField
) )
: :
regIOobject(io), regIOobject(io),
Field<Type>(std::move(field)), DynamicField<Type>(std::move(field)),
mesh_(mesh), mesh_(mesh),
dimensions_(dims) dimensions_(dims)
{ {
@ -113,7 +113,7 @@ Foam::DimensionedField<Type, GeoMesh>::DimensionedField
) )
: :
regIOobject(io), regIOobject(io),
Field<Type>(std::move(field)), DynamicField<Type>(std::move(field)),
mesh_(mesh), mesh_(mesh),
dimensions_(dims) dimensions_(dims)
{ {
@ -131,7 +131,7 @@ Foam::DimensionedField<Type, GeoMesh>::DimensionedField
) )
: :
regIOobject(io), regIOobject(io),
Field<Type>(tfield.constCast(), tfield.movable()), DynamicField<Type>(tfield.constCast(), tfield.movable()),
mesh_(mesh), mesh_(mesh),
dimensions_(dims) dimensions_(dims)
{ {
@ -146,11 +146,21 @@ Foam::DimensionedField<Type, GeoMesh>::DimensionedField
const IOobject& io, const IOobject& io,
const Mesh& mesh, const Mesh& mesh,
const dimensionSet& dims, const dimensionSet& dims,
const bool checkIOFlags const bool checkIOFlags,
const bool extraCapacity
) )
: :
regIOobject(io), regIOobject(io),
Field<Type>(GeoMesh::size(mesh)), DynamicField<Type>
(
// (size,capacity)
std::pair<label,label>
(
GeoMesh::size(mesh),
GeoMesh::size(mesh)
+ (extraCapacity ? GeoMesh::boundary_size(mesh) : label(0))
)
),
mesh_(mesh), mesh_(mesh),
dimensions_(dims) dimensions_(dims)
{ {
@ -168,11 +178,21 @@ Foam::DimensionedField<Type, GeoMesh>::DimensionedField
const Mesh& mesh, const Mesh& mesh,
const Type& value, const Type& value,
const dimensionSet& dims, const dimensionSet& dims,
const bool checkIOFlags const bool checkIOFlags,
const bool extraCapacity
) )
: :
regIOobject(io), regIOobject(io),
Field<Type>(GeoMesh::size(mesh)), DynamicField<Type>
(
// (size,capacity)
std::pair<label,label>
(
GeoMesh::size(mesh),
GeoMesh::size(mesh)
+ (extraCapacity ? GeoMesh::boundary_size(mesh) : label(0))
)
),
mesh_(mesh), mesh_(mesh),
dimensions_(dims) dimensions_(dims)
{ {
@ -190,7 +210,8 @@ Foam::DimensionedField<Type, GeoMesh>::DimensionedField
const IOobject& io, const IOobject& io,
const Mesh& mesh, const Mesh& mesh,
const dimensioned<Type>& dt, const dimensioned<Type>& dt,
const bool checkIOFlags const bool checkIOFlags,
const bool extraCapacity
) )
: :
DimensionedField<Type, GeoMesh> DimensionedField<Type, GeoMesh>
@ -199,7 +220,8 @@ Foam::DimensionedField<Type, GeoMesh>::DimensionedField
mesh, mesh,
dt.value(), dt.value(),
dt.dimensions(), dt.dimensions(),
checkIOFlags checkIOFlags,
extraCapacity
) )
{} {}
@ -211,7 +233,7 @@ Foam::DimensionedField<Type, GeoMesh>::DimensionedField
) )
: :
regIOobject(df), regIOobject(df),
Field<Type>(df), DynamicField<Type>(df),
mesh_(df.mesh_), mesh_(df.mesh_),
dimensions_(df.dimensions_), dimensions_(df.dimensions_),
oriented_(df.oriented_) oriented_(df.oriented_)
@ -236,7 +258,7 @@ Foam::DimensionedField<Type, GeoMesh>::DimensionedField
) )
: :
regIOobject(df, reuse), regIOobject(df, reuse),
Field<Type>(df, reuse), DynamicField<Type>(df, reuse),
mesh_(df.mesh_), mesh_(df.mesh_),
dimensions_(df.dimensions_), dimensions_(df.dimensions_),
oriented_(df.oriented_) oriented_(df.oriented_)
@ -263,7 +285,7 @@ Foam::DimensionedField<Type, GeoMesh>::DimensionedField
) )
: :
regIOobject(io), regIOobject(io),
Field<Type>(df), DynamicField<Type>(df),
mesh_(df.mesh_), mesh_(df.mesh_),
dimensions_(df.dimensions_), dimensions_(df.dimensions_),
oriented_(df.oriented_) oriented_(df.oriented_)
@ -290,7 +312,7 @@ Foam::DimensionedField<Type, GeoMesh>::DimensionedField
) )
: :
regIOobject(io, df), regIOobject(io, df),
Field<Type>(df, reuse), DynamicField<Type>(df, reuse),
mesh_(df.mesh_), mesh_(df.mesh_),
dimensions_(df.dimensions_), dimensions_(df.dimensions_),
oriented_(df.oriented_) oriented_(df.oriented_)
@ -318,7 +340,7 @@ Foam::DimensionedField<Type, GeoMesh>::DimensionedField
) )
: :
regIOobject(newName, df, newName != df.name()), regIOobject(newName, df, newName != df.name()),
Field<Type>(df), DynamicField<Type>(df),
mesh_(df.mesh_), mesh_(df.mesh_),
dimensions_(df.dimensions_), dimensions_(df.dimensions_),
oriented_(df.oriented_) oriented_(df.oriented_)
@ -345,7 +367,7 @@ Foam::DimensionedField<Type, GeoMesh>::DimensionedField
) )
: :
regIOobject(newName, df, true), regIOobject(newName, df, true),
Field<Type>(df, reuse), DynamicField<Type>(df, reuse),
mesh_(df.mesh_), mesh_(df.mesh_),
dimensions_(df.dimensions_), dimensions_(df.dimensions_),
oriented_(df.oriented_) oriented_(df.oriented_)
@ -421,7 +443,7 @@ void Foam::DimensionedField<Type, GeoMesh>::replace
>& df >& df
) )
{ {
Field<Type>::replace(d, df); DynamicField<Type>::replace(d, df);
} }
@ -523,7 +545,7 @@ void Foam::DimensionedField<Type, GeoMesh>::operator=
dimensions_ = df.dimensions(); dimensions_ = df.dimensions();
oriented_ = df.oriented(); oriented_ = df.oriented();
Field<Type>::operator=(df); DynamicField<Type>::operator=(df);
} }
@ -556,14 +578,14 @@ void Foam::DimensionedField<Type, GeoMesh>::operator=
) )
{ {
dimensions_ = dt.dimensions(); dimensions_ = dt.dimensions();
Field<Type>::operator=(dt.value()); DynamicField<Type>::operator=(dt.value());
} }
template<class Type, class GeoMesh> template<class Type, class GeoMesh>
void Foam::DimensionedField<Type, GeoMesh>::operator=(Foam::zero) void Foam::DimensionedField<Type, GeoMesh>::operator=(Foam::zero)
{ {
Field<Type>::operator=(Foam::zero{}); DynamicField<Type>::operator=(Foam::zero{});
} }
@ -579,7 +601,7 @@ void Foam::DimensionedField<Type, GeoMesh>::operator op \
\ \
dimensions_ op df.dimensions(); \ dimensions_ op df.dimensions(); \
oriented_ op df.oriented(); \ oriented_ op df.oriented(); \
Field<Type>::operator op(df); \ DynamicField<Type>::operator op(df); \
} \ } \
\ \
template<class Type, class GeoMesh> \ template<class Type, class GeoMesh> \
@ -599,7 +621,7 @@ void Foam::DimensionedField<Type, GeoMesh>::operator op \
) \ ) \
{ \ { \
dimensions_ op dt.dimensions(); \ dimensions_ op dt.dimensions(); \
Field<Type>::operator op(dt.value()); \ DynamicField<Type>::operator op(dt.value()); \
} }
COMPUTED_ASSIGNMENT(Type, +=) COMPUTED_ASSIGNMENT(Type, +=)

View File

@ -42,7 +42,7 @@ SourceFiles
#define Foam_DimensionedField_H #define Foam_DimensionedField_H
#include "regIOobject.H" #include "regIOobject.H"
#include "Field.H" #include "DynamicField.H"
#include "dimensionedType.H" #include "dimensionedType.H"
#include "orientedType.H" #include "orientedType.H"
@ -77,7 +77,7 @@ template<class Type, class GeoMesh>
class DimensionedField class DimensionedField
: :
public regIOobject, public regIOobject,
public Field<Type> public DynamicField<Type>
{ {
public: public:
@ -93,6 +93,7 @@ public:
typedef DimensionedField<Type, GeoMesh> Internal; typedef DimensionedField<Type, GeoMesh> Internal;
//- Type of the field from which this DimensionedField is derived //- Type of the field from which this DimensionedField is derived
// Use Field (not DynamicField) here.
typedef Field<Type> FieldType; typedef Field<Type> FieldType;
//- Component type of the field elements //- Component type of the field elements
@ -197,7 +198,10 @@ public:
const IOobject& io, const IOobject& io,
const Mesh& mesh, const Mesh& mesh,
const dimensionSet& dims, const dimensionSet& dims,
const bool checkIOFlags = true //! Handle mandatory/optional reading?
const bool checkIOFlags = true,
//! Additional space for geometric boundary size?
const bool extraCapacity = false
); );
//- Construct from components, setting dimensions and initial //- Construct from components, setting dimensions and initial
@ -208,7 +212,10 @@ public:
const Mesh& mesh, const Mesh& mesh,
const Type& value, const Type& value,
const dimensionSet& dims, const dimensionSet& dims,
const bool checkIOFlags = true //! Handle mandatory/optional reading?
const bool checkIOFlags = true,
//! Additional space for geometric boundary size?
const bool extraCapacity = false
); );
//- Construct from components, setting dimensions and initial //- Construct from components, setting dimensions and initial
@ -219,15 +226,20 @@ public:
const IOobject& io, const IOobject& io,
const Mesh& mesh, const Mesh& mesh,
const dimensioned<Type>& dt, const dimensioned<Type>& dt,
const bool checkIOFlags = true //! Handle mandatory/optional reading?
const bool checkIOFlags = true,
//! Additional space for geometric boundary size?
const bool extraCapacity = false
); );
//- Construct from Istream. //- Construct from Istream (uses an intermediate dictionary)
DimensionedField DimensionedField
( (
const IOobject& io, const IOobject& io,
const Mesh& mesh, const Mesh& mesh,
const word& fieldDictEntry = "value" const word& fieldDictEntry = "value",
//! Additional space for geometric boundary size?
const bool extraCapacity = false
); );
//- Construct from dictionary //- Construct from dictionary
@ -236,7 +248,9 @@ public:
const IOobject& io, const IOobject& io,
const Mesh& mesh, const Mesh& mesh,
const dictionary& fieldDict, const dictionary& fieldDict,
const word& fieldDictEntry = "value" const word& fieldDictEntry = "value",
//! Additional space for geometric boundary size?
const bool extraCapacity = false
); );
//- Copy construct //- Copy construct
@ -572,6 +586,15 @@ public:
//- Return reference to the primitive field values //- Return reference to the primitive field values
Field<Type>& field() noexcept { return *this; } Field<Type>& field() noexcept { return *this; }
//- Return const-reference to the primitive field storage.
//- Use sparingly.
const DynamicField<Type>& dyn_field() const noexcept { return *this; }
//- Return reference to the primitive field storage.
//- Use sparingly.
DynamicField<Type>& dyn_field() noexcept { return *this; }
//- Return a component field of the field //- Return a component field of the field
tmp<DimensionedField<cmptType, GeoMesh>> component tmp<DimensionedField<cmptType, GeoMesh>> component
( (

View File

@ -50,12 +50,19 @@ void Foam::DimensionedField<Type, GeoMesh>::readField
oriented_.read(fieldDict); // The "oriented" entry (if present) oriented_.read(fieldDict); // The "oriented" entry (if present)
} }
const label meshSize = GeoMesh::size(mesh_);
// The primitive field // The primitive field : dyn_field()
auto& fld = static_cast<Field<Type>&>(*this); auto& fld = static_cast<DynamicField<Type>&>(*this);
fld.resize_nocopy(GeoMesh::size(mesh_)); // Resize primitive field to make space for the internal field
fld.assign(fieldDictEntry, fieldDict, fld.size()); // <- MUST_READ // - avoid size doubling
// - without copying any existing content
fld.clear(); // ie, ignore any existing content
fld.reserve_exact(meshSize);
fld.resize_nocopy(meshSize);
fld.assign(fieldDictEntry, fieldDict, meshSize); // <- MUST_READ
} }
@ -116,12 +123,20 @@ Foam::DimensionedField<Type, GeoMesh>::DimensionedField
( (
const IOobject& io, const IOobject& io,
const Mesh& mesh, const Mesh& mesh,
const word& fieldDictEntry const word& fieldDictEntry,
const bool extraCapacity
) )
: :
regIOobject(io), regIOobject(io),
mesh_(mesh) mesh_(mesh)
{ {
if (extraCapacity)
{
DynamicField<Type>::reserve_exact
(
GeoMesh::size(mesh) + GeoMesh::boundary_size(mesh)
);
}
readField(fieldDictEntry); readField(fieldDictEntry);
} }
@ -132,12 +147,20 @@ Foam::DimensionedField<Type, GeoMesh>::DimensionedField
const IOobject& io, const IOobject& io,
const Mesh& mesh, const Mesh& mesh,
const dictionary& fieldDict, const dictionary& fieldDict,
const word& fieldDictEntry const word& fieldDictEntry,
const bool extraCapacity
) )
: :
regIOobject(io), regIOobject(io),
mesh_(mesh) mesh_(mesh)
{ {
if (extraCapacity)
{
DynamicField<Type>::reserve_exact
(
GeoMesh::size(mesh) + GeoMesh::boundary_size(mesh)
);
}
readField(fieldDict, fieldDictEntry); readField(fieldDict, fieldDictEntry);
} }
@ -159,7 +182,7 @@ bool Foam::DimensionedField<Type, GeoMesh>::writeData
os << nl; os << nl;
} }
Field<Type>::writeEntry(fieldDictEntry, os); DynamicField<Type>::writeEntry(fieldDictEntry, os);
os.check(FUNCTION_NAME); os.check(FUNCTION_NAME);
return os.good(); return os.good();

View File

@ -182,7 +182,7 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
const word& patchFieldType const word& patchFieldType
) )
: :
Internal(io, mesh, dims, false), Internal(io, mesh, dims, false, FieldBase::unifiedGeometricField),
timeIndex_(this->time().timeIndex()), timeIndex_(this->time().timeIndex()),
boundaryField_(mesh.boundary(), *this, patchFieldType) boundaryField_(mesh.boundary(), *this, patchFieldType)
{ {
@ -203,7 +203,7 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
const wordList& actualPatchTypes const wordList& actualPatchTypes
) )
: :
Internal(io, mesh, dims, false), Internal(io, mesh, dims, false, FieldBase::unifiedGeometricField),
timeIndex_(this->time().timeIndex()), timeIndex_(this->time().timeIndex()),
boundaryField_(mesh.boundary(), *this, patchFieldTypes, actualPatchTypes) boundaryField_(mesh.boundary(), *this, patchFieldTypes, actualPatchTypes)
{ {
@ -224,7 +224,7 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
const word& patchFieldType const word& patchFieldType
) )
: :
Internal(io, mesh, value, dims, false), Internal(io, mesh, value, dims, false, FieldBase::unifiedGeometricField),
timeIndex_(this->time().timeIndex()), timeIndex_(this->time().timeIndex()),
boundaryField_(mesh.boundary(), *this, patchFieldType) boundaryField_(mesh.boundary(), *this, patchFieldType)
{ {
@ -248,7 +248,7 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
const wordList& actualPatchTypes const wordList& actualPatchTypes
) )
: :
Internal(io, mesh, value, dims, false), Internal(io, mesh, value, dims, false, FieldBase::unifiedGeometricField),
timeIndex_(this->time().timeIndex()), timeIndex_(this->time().timeIndex()),
boundaryField_(mesh.boundary(), *this, patchFieldTypes, actualPatchTypes) boundaryField_(mesh.boundary(), *this, patchFieldTypes, actualPatchTypes)
{ {
@ -530,7 +530,7 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
const bool readOldTime const bool readOldTime
) )
: :
Internal(io, mesh, dimless, false), Internal(io, mesh, dimless, false, FieldBase::unifiedGeometricField),
timeIndex_(this->time().timeIndex()), timeIndex_(this->time().timeIndex()),
boundaryField_(mesh.boundary()) boundaryField_(mesh.boundary())
{ {
@ -567,7 +567,7 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
const dictionary& dict const dictionary& dict
) )
: :
Internal(io, mesh, dimless, false), Internal(io, mesh, dimless, false, FieldBase::unifiedGeometricField),
timeIndex_(this->time().timeIndex()), timeIndex_(this->time().timeIndex()),
boundaryField_(mesh.boundary()) boundaryField_(mesh.boundary())
{ {
@ -1087,6 +1087,46 @@ correctLocalBoundaryConditions()
} }
template<class Type, template<class> class PatchField, class GeoMesh>
template<class Cop>
Foam::label Foam::GeometricField<Type, PatchField, GeoMesh>::
boundaryEvaluate(const Cop& cop)
{
const label meshSize = GeoMesh::size(this->mesh());
const label totalSize = GeoMesh::boundary_size(this->mesh()) + meshSize;
if (FOAM_UNLIKELY(meshSize != this->size() && totalSize != this->size()))
{
FatalErrorInFunction
<< "Problem : field:" << this->name()
<< " size:" << this->size()
<< " capacity:" << this->capacity()
<< " is not mesh size:" << meshSize
<< " or total size:" << totalSize
<< exit(FatalError);
}
auto& fld = static_cast<DynamicField<Type>&>(*this);
// Resize primitive field to allow for internal+boundary fields
// - avoid size doubling
// - only copying the internal field without boundaries
fld.reserve_exact(totalSize);
fld.resize_copy(meshSize, totalSize);
// Populate the extra space with the flattened boundary values:
for (const auto& pfld : this->boundaryField())
{
const label start = (meshSize + pfld.patch().offset());
SubList<Type> slice(fld, pfld.size(), start);
cop(pfld, slice);
}
return meshSize;
}
template<class Type, template<class> class PatchField, class GeoMesh> template<class Type, template<class> class PatchField, class GeoMesh>
bool Foam::GeometricField<Type, PatchField, GeoMesh>::needReference() const bool Foam::GeometricField<Type, PatchField, GeoMesh>::needReference() const
{ {

View File

@ -923,6 +923,14 @@ public:
// Is dummy for processor boundary conditions etc // Is dummy for processor boundary conditions etc
void correctLocalBoundaryConditions(); void correctLocalBoundaryConditions();
//- Evaluate boundary functions using the field storage:
// - extends the internal field storage
// - applies passed-in operator to fill in the slots
// .
// \returns The nominal geometric field size
template<class Cop>
label boundaryEvaluate(const Cop& cop);
//- Does the field need a reference level for solution //- Does the field need a reference level for solution
bool needReference() const; bool needReference() const;