ENH: allow delayed construction of regionFaModel in volume bcs (#3419)

Ideally wish to delay construction of the finite-area mesh until
  updateCoeffs(), when it is actually needed.

  This helps avoid difficult to trace errors and avoids inadvertent
  parallel communication during construction from a dictionary.

  However, lazy evaluation fails at the later stage while attempting
  to load the corresponding initial fields, since the timeIndex has
  already advanced.

  Use the newly introduced regionModels::allowFaModels() switch
  to locally enable or disable lazy evaluation as needed.

  This allows selective disabling (eg, in post-processing utilities)
  where loading the volume field should not activate the associated
  regionFaModel and loading a finite-area mesh too (which may not
  exist or be defined at that point).
This commit is contained in:
Mark Olesen
2025-10-09 13:46:45 +02:00
committed by Andrew Heather
parent c7b5f1e3eb
commit e02b4be7ca
14 changed files with 251 additions and 118 deletions

View File

@ -418,8 +418,14 @@ int main(int argc, char *argv[])
// Allow explicit -constant, have zero from time range
timeSelector::addOptions(true, false); // constant(true), zero(false)
// Prevent volume BCs from triggering finite-area
regionModels::allowFaModels(false);
#include "setRootCase.H"
// ------------------------------------------------------------------------
// Configuration
const bool writeCellDist = args.found("cellDist");
// Most of these are ignored for dry-run (not triggered anywhere)

View File

@ -135,9 +135,14 @@ int main(int argc, char *argv[])
"Only reconstruct new times (i.e. that do not exist already)"
);
// Prevent volume BCs from triggering finite-area
regionModels::allowFaModels(false);
#include "setRootCase.H"
#include "createTime.H"
// ------------------------------------------------------------------------
// Configuration
const bool doFields = !args.found("no-fields");
wordRes selectedFields;

View File

@ -780,11 +780,17 @@ int main(int argc, char *argv[])
#include "addAllRegionOptions.H"
// Prevent volume BCs from triggering finite-area
regionModels::allowFaModels(false);
#include "setRootCase.H"
#include "createTime.H"
printWarning();
// ------------------------------------------------------------------------
// Configuration
const bool fullMatch = args.found("fullMatch");
const bool procMatch = args.found("procMatch");
const bool writeCellDist = args.found("cellDist");

View File

@ -1257,6 +1257,8 @@ int main(int argc, char *argv[])
true // Advanced option
);
// Prevent volume BCs from triggering finite-area
regionModels::allowFaModels(false);
//- Disable caching of times/processor dirs etc. Cause massive parallel
// problems when e.g decomposing.
@ -1269,6 +1271,7 @@ int main(int argc, char *argv[])
argList args(argc, argv);
// ------------------------------------------------------------------------
// As much as possible avoid synchronised operation. To be looked at more
// closely for the three scenarios:

View File

@ -323,6 +323,9 @@ int main(int argc, char *argv[])
);
argList::addOptionCompat("cellZones", {"cellZone", 1912});
// Prevent volume BCs from triggering finite-area
regionModels::allowFaModels(false);
#include "setRootCase.H"
// ------------------------------------------------------------------------

View File

@ -479,8 +479,14 @@ int main(int argc, char *argv[])
"Directory name for VTK output (default: 'VTK')"
);
// Prevent volume BCs from triggering finite-area
regionModels::allowFaModels(false);
#include "setRootCase.H"
// ------------------------------------------------------------------------
// Configuration
/// const int optVerbose = args.verbose();
const bool decomposePoly = args.found("poly-decomp");
const bool doBoundary = !args.found("no-boundary");

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020-2022 OpenCFD Ltd.
Copyright (C) 2020-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,6 +27,7 @@ License
#include "velocityFilmShellFvPatchVectorField.H"
#include "dictionaryContent.H"
#include "regionProperties.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -34,6 +35,20 @@ License
namespace Foam
{
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void velocityFilmShellFvPatchVectorField::create_baffle()
{
if (!baffle_)
{
baffle_.reset
(
baffleType::New(this->patch().boundaryMesh().mesh(), dict_)
);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
velocityFilmShellFvPatchVectorField::velocityFilmShellFvPatchVectorField
@ -42,8 +57,7 @@ velocityFilmShellFvPatchVectorField::velocityFilmShellFvPatchVectorField
const DimensionedField<vector, volMesh>& iF
)
:
mixedFvPatchField<vector>(p, iF),
baffle_(nullptr),
parent_bctype(p, iF),
dict_(),
curTimeIndex_(-1),
zeroWallVelocity_(true)
@ -62,14 +76,7 @@ velocityFilmShellFvPatchVectorField::velocityFilmShellFvPatchVectorField
const fvPatchFieldMapper& mapper
)
:
mixedFvPatchField<vector>
(
ptf,
p,
iF,
mapper
),
baffle_(nullptr),
parent_bctype(ptf, p, iF, mapper),
dict_(ptf.dict_),
curTimeIndex_(-1),
zeroWallVelocity_(true)
@ -83,8 +90,7 @@ velocityFilmShellFvPatchVectorField::velocityFilmShellFvPatchVectorField
const dictionary& dict
)
:
mixedFvPatchField<vector>(p, iF),
baffle_(nullptr),
parent_bctype(p, iF),
dict_
(
// Copy dictionary, but without "heavy" data chunks
@ -116,9 +122,11 @@ velocityFilmShellFvPatchVectorField::velocityFilmShellFvPatchVectorField
valueFraction() = 1;
}
if (!baffle_)
// Create baffle now.
// Lazy evaluation has issues with loading the finite-area fields
if (regionModels::allowFaModels())
{
baffle_.reset(baffleType::New(p.boundaryMesh().mesh(), dict_));
create_baffle();
}
}
@ -129,8 +137,7 @@ velocityFilmShellFvPatchVectorField::velocityFilmShellFvPatchVectorField
const DimensionedField<vector, volMesh>& iF
)
:
mixedFvPatchField<vector>(ptf, iF),
baffle_(nullptr),
parent_bctype(ptf, iF),
dict_(ptf.dict_),
curTimeIndex_(-1),
zeroWallVelocity_(true)
@ -146,14 +153,22 @@ void velocityFilmShellFvPatchVectorField::updateCoeffs()
return;
}
// Create baffle if needed
if (!baffle_)
{
create_baffle();
}
// Execute the change only once per time-step
if (curTimeIndex_ != this->db().time().timeIndex())
{
baffle_->evolve();
vectorField& pfld = *this;
baffle_->vsm().mapToVolumePatch(baffle_->Us(), pfld, patch().index());
auto& baffle = baffle_();
baffle.evolve();
baffle.vsm().mapToVolumePatch(baffle.Us(), pfld, patch().index());
refGrad() = Zero;
valueFraction() = 1;
@ -170,13 +185,13 @@ void velocityFilmShellFvPatchVectorField::updateCoeffs()
curTimeIndex_ = this->db().time().timeIndex();
}
mixedFvPatchField<vector>::updateCoeffs();
parent_bctype::updateCoeffs();
}
void velocityFilmShellFvPatchVectorField::write(Ostream& os) const
{
mixedFvPatchField<vector>::write(os);
parent_bctype::write(os);
dict_.write(os, false);
}

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 OpenCFD Ltd.
Copyright (C) 2020-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -134,15 +134,15 @@ class velocityFilmShellFvPatchVectorField
{
// Typedefs
//- The parent boundary condition type
typedef mixedFvPatchField<vector> parent_bctype;
//- The finite-area region model
typedef regionModels::areaSurfaceFilmModels::liquidFilmBase baffleType;
// Private Data
//- The liquid film model
autoPtr<baffleType> baffle_;
//- Dictionary
mutable dictionary dict_;
@ -152,6 +152,15 @@ class velocityFilmShellFvPatchVectorField
//- Flag to set velocity to zero or film velocity
bool zeroWallVelocity_;
//- The liquid film model
autoPtr<baffleType> baffle_;
// Private Methods
//- Create film baffle (if required)
void create_baffle();
public:
@ -186,13 +195,23 @@ public:
const fvPatchFieldMapper&
);
//- Construct as copy setting internal field reference
//- Copy construct with internal field reference
velocityFilmShellFvPatchVectorField
(
const velocityFilmShellFvPatchVectorField&,
const DimensionedField<vector, volMesh>&
const velocityFilmShellFvPatchVectorField& pfld,
const DimensionedField<vector, volMesh>& iF
);
//- Copy construct
velocityFilmShellFvPatchVectorField
(
const velocityFilmShellFvPatchVectorField& pfld
)
:
velocityFilmShellFvPatchVectorField(pfld, pfld.internalField())
{}
//- Return a clone
virtual tmp<fvPatchField<vector>> clone() const
{

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2022 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -26,8 +26,9 @@ License
\*---------------------------------------------------------------------------*/
#include "thermalShellFvPatchScalarField.H"
#include "addToRunTimeSelectionTable.H"
#include "dictionaryContent.H"
#include "regionProperties.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -36,6 +37,20 @@ namespace Foam
namespace compressible
{
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void thermalShellFvPatchScalarField::create_baffle()
{
if (!baffle_)
{
baffle_.reset
(
baffleType::New(this->patch().boundaryMesh().mesh(), dict_)
);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
thermalShellFvPatchScalarField::thermalShellFvPatchScalarField
@ -44,8 +59,7 @@ thermalShellFvPatchScalarField::thermalShellFvPatchScalarField
const DimensionedField<scalar, volMesh>& iF
)
:
fixedValueFvPatchField<scalar>(p, iF),
baffle_(nullptr),
parent_bctype(p, iF),
dict_()
{}
@ -58,14 +72,7 @@ thermalShellFvPatchScalarField::thermalShellFvPatchScalarField
const fvPatchFieldMapper& mapper
)
:
fixedValueFvPatchField<scalar>
(
ptf,
p,
iF,
mapper
),
baffle_(nullptr),
parent_bctype(ptf, p, iF, mapper),
dict_(ptf.dict_)
{}
@ -77,8 +84,7 @@ thermalShellFvPatchScalarField::thermalShellFvPatchScalarField
const dictionary& dict
)
:
fixedValueFvPatchField<scalar>(p, iF, dict),
baffle_(nullptr),
parent_bctype(p, iF, dict),
dict_
(
// Copy dictionary, but without "heavy" data chunks
@ -94,9 +100,11 @@ thermalShellFvPatchScalarField::thermalShellFvPatchScalarField
)
)
{
if (!baffle_)
// Create baffle now.
// Lazy evaluation has issues with loading the finite-area fields
if (regionModels::allowFaModels())
{
baffle_.reset(baffleType::New(p.boundaryMesh().mesh(), dict_));
create_baffle();
}
}
@ -107,8 +115,7 @@ thermalShellFvPatchScalarField::thermalShellFvPatchScalarField
const DimensionedField<scalar, volMesh>& iF
)
:
fixedValueFvPatchField<scalar>(ptf, iF),
baffle_(nullptr),
parent_bctype(ptf, iF),
dict_(ptf.dict_)
{}
@ -122,19 +129,27 @@ void thermalShellFvPatchScalarField::updateCoeffs()
return;
}
baffle_->evolve();
scalarField& pfld = *this;
baffle_->vsm().mapToVolumePatch(baffle_->T(), pfld, patch().index());
// Create baffle if needed
if (!baffle_)
{
create_baffle();
}
fixedValueFvPatchField<scalar>::updateCoeffs();
auto& baffle = baffle_();
baffle.evolve();
baffle.vsm().mapToVolumePatch(baffle.T(), pfld, patch().index());
parent_bctype::updateCoeffs();
}
void thermalShellFvPatchScalarField::write(Ostream& os) const
{
fixedValueFvPatchField<scalar>::write(os);
parent_bctype::write(os);
dict_.write(os, false);
}

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2022 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -91,17 +91,26 @@ class thermalShellFvPatchScalarField
{
// Typedefs
//- The parent boundary condition type
typedef fixedValueFvPatchField<scalar> parent_bctype;
//- The finite-area region model
typedef regionModels::thermalShellModel baffleType;
// Private Data
//- Dictionary
dictionary dict_;
//- The thermal baffle
autoPtr<baffleType> baffle_;
//- Dictionary
dictionary dict_;
// Private Methods
//- Create thermal baffle (if required)
void create_baffle();
public:
@ -137,13 +146,23 @@ public:
const fvPatchFieldMapper&
);
//- Construct as copy setting internal field reference
//- Copy construct with internal field reference
thermalShellFvPatchScalarField
(
const thermalShellFvPatchScalarField&,
const DimensionedField<scalar, volMesh>&
const thermalShellFvPatchScalarField& pfld,
const DimensionedField<scalar, volMesh>& iF
);
//- Copy construct
thermalShellFvPatchScalarField
(
const thermalShellFvPatchScalarField& pfld
)
:
thermalShellFvPatchScalarField(pfld, pfld.internalField())
{}
//- Return a clone
virtual tmp<fvPatchField<scalar>> clone() const
{

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2022 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,6 +27,7 @@ License
#include "vibrationShellFvPatchScalarField.H"
#include "dictionaryContent.H"
#include "regionProperties.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -34,6 +35,20 @@ License
namespace Foam
{
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void vibrationShellFvPatchScalarField::create_baffle()
{
if (!baffle_)
{
baffle_.reset
(
baffleType::New(this->patch().boundaryMesh().mesh(), dict_)
);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
vibrationShellFvPatchScalarField::vibrationShellFvPatchScalarField
@ -42,8 +57,7 @@ vibrationShellFvPatchScalarField::vibrationShellFvPatchScalarField
const DimensionedField<scalar, volMesh>& iF
)
:
mixedFvPatchField<scalar>(p, iF),
baffle_(nullptr),
parent_bctype(p, iF),
dict_()
{
refValue() = Zero;
@ -60,14 +74,7 @@ vibrationShellFvPatchScalarField::vibrationShellFvPatchScalarField
const fvPatchFieldMapper& mapper
)
:
mixedFvPatchField<scalar>
(
ptf,
p,
iF,
mapper
),
baffle_(nullptr),
parent_bctype(ptf, p, iF, mapper),
dict_(ptf.dict_)
{}
@ -79,8 +86,7 @@ vibrationShellFvPatchScalarField::vibrationShellFvPatchScalarField
const dictionary& dict
)
:
mixedFvPatchField<scalar>(p, iF),
baffle_(nullptr),
parent_bctype(p, iF),
dict_
(
// Copy dictionary, but without "heavy" data chunks
@ -110,9 +116,11 @@ vibrationShellFvPatchScalarField::vibrationShellFvPatchScalarField
valueFraction() = 1;
}
if (!baffle_)
// Create baffle now.
// Lazy evaluation has issues with loading the finite-area fields
if (regionModels::allowFaModels())
{
baffle_.reset(baffleType::New(p.boundaryMesh().mesh(), dict_));
create_baffle();
}
}
@ -123,8 +131,7 @@ vibrationShellFvPatchScalarField::vibrationShellFvPatchScalarField
const DimensionedField<scalar, volMesh>& iF
)
:
mixedFvPatchField<scalar>(ptf, iF),
baffle_(nullptr),
parent_bctype(ptf, iF),
dict_(ptf.dict_)
{}
@ -138,31 +145,38 @@ void vibrationShellFvPatchScalarField::updateCoeffs()
return;
}
// Create baffle if needed
if (!baffle_)
{
create_baffle();
}
auto& baffle = baffle_();
const auto& transportProperties =
db().lookupObject<IOdictionary>("transportProperties");
dimensionedScalar rho("rho", dimDensity, transportProperties);
baffle_->evolve();
baffle.evolve();
// rho * acceleration
refGrad() = Zero; // safety (for any unmapped values)
baffle_->vsm().mapToVolumePatch(baffle_->a(), refGrad(), patch().index());
baffle.vsm().mapToVolumePatch(baffle.a(), refGrad(), patch().index());
refGrad() *= rho.value();
refValue() = Zero;
valueFraction() = Zero;
mixedFvPatchField<scalar>::updateCoeffs();
parent_bctype::updateCoeffs();
}
void vibrationShellFvPatchScalarField::write(Ostream& os) const
{
mixedFvPatchField<scalar>::write(os);
parent_bctype::write(os);
dict_.write(os, false);
}

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -82,17 +82,26 @@ class vibrationShellFvPatchScalarField
{
// Typedefs
//- The parent boundary condition type
typedef mixedFvPatchField<scalar> parent_bctype;
//- The finite-area region model
typedef regionModels::vibrationShellModel baffleType;
// Private Data
//- Dictionary
dictionary dict_;
//- The vibration shell model
autoPtr<baffleType> baffle_;
//- Dictionary
dictionary dict_;
// Private Methods
//- Create vibration baffle (if required)
void create_baffle();
public:
@ -128,13 +137,23 @@ public:
const fvPatchFieldMapper&
);
//- Construct as copy setting internal field reference
//- Copy construct with internal field reference
vibrationShellFvPatchScalarField
(
const vibrationShellFvPatchScalarField&,
const DimensionedField<scalar, volMesh>&
const vibrationShellFvPatchScalarField& pfld,
const DimensionedField<scalar, volMesh>& iF
);
//- Copy construct
vibrationShellFvPatchScalarField
(
const vibrationShellFvPatchScalarField& pfld
)
:
vibrationShellFvPatchScalarField(pfld, pfld.internalField())
{}
//- Return a clone
virtual tmp<fvPatchField<scalar>> clone() const
{

View File

@ -27,6 +27,7 @@ License
\*---------------------------------------------------------------------------*/
#include "thermalBaffleFvPatchScalarField.H"
#include "dictionaryContent.H"
#include "addToRunTimeSelectionTable.H"
#include "emptyPolyPatch.H"
#include "mappedWallPolyPatch.H"
@ -46,12 +47,10 @@ thermalBaffleFvPatchScalarField::thermalBaffleFvPatchScalarField
const DimensionedField<scalar, volMesh>& iF
)
:
turbulentTemperatureRadCoupledMixedFvPatchScalarField(p, iF),
parent_bctype(p, iF),
owner_(false),
internal_(true),
baffle_(nullptr),
dict_(),
extrudeMeshPtr_()
dict_()
{}
@ -63,18 +62,10 @@ thermalBaffleFvPatchScalarField::thermalBaffleFvPatchScalarField
const fvPatchFieldMapper& mapper
)
:
turbulentTemperatureRadCoupledMixedFvPatchScalarField
(
ptf,
p,
iF,
mapper
),
parent_bctype(ptf, p, iF, mapper),
owner_(ptf.owner_),
internal_(ptf.internal_),
baffle_(nullptr),
dict_(ptf.dict_),
extrudeMeshPtr_()
dict_(ptf.dict_)
{}
@ -85,12 +76,23 @@ thermalBaffleFvPatchScalarField::thermalBaffleFvPatchScalarField
const dictionary& dict
)
:
turbulentTemperatureRadCoupledMixedFvPatchScalarField(p, iF, dict),
parent_bctype(p, iF, dict),
owner_(false),
internal_(true),
baffle_(nullptr),
dict_(dict),
extrudeMeshPtr_()
dict_
(
// Copy dictionary, but without "heavy" data chunks
dictionaryContent::copyDict
(
dict,
wordList(), // allow
wordList // deny
({
"type", // redundant
"value"
})
)
)
{
const fvMesh& thisMesh = patch().boundaryMesh().mesh();
@ -104,8 +106,8 @@ thermalBaffleFvPatchScalarField::thermalBaffleFvPatchScalarField
if
(
!thisMesh.time().foundObject<fvMesh>(regionName)
&& regionName != "none"
(regionName != "none")
&& !thisMesh.time().foundObject<fvMesh>(regionName)
)
{
if (!extrudeMeshPtr_)
@ -126,12 +128,10 @@ thermalBaffleFvPatchScalarField::thermalBaffleFvPatchScalarField
const DimensionedField<scalar, volMesh>& iF
)
:
turbulentTemperatureRadCoupledMixedFvPatchScalarField(ptf, iF),
parent_bctype(ptf, iF),
owner_(ptf.owner_),
internal_(ptf.internal_),
baffle_(nullptr),
dict_(ptf.dict_),
extrudeMeshPtr_()
dict_(ptf.dict_)
{}
@ -309,13 +309,13 @@ void thermalBaffleFvPatchScalarField::updateCoeffs()
baffle_->evolve();
}
turbulentTemperatureRadCoupledMixedFvPatchScalarField::updateCoeffs();
parent_bctype::updateCoeffs();
}
void thermalBaffleFvPatchScalarField::write(Ostream& os) const
{
turbulentTemperatureRadCoupledMixedFvPatchScalarField::write(os);
parent_bctype::write(os);
if (owner_)
{

View File

@ -203,11 +203,9 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef thermalBaffleFvPatchScalarField_H
#define thermalBaffleFvPatchScalarField_H
#ifndef Foam_thermalBaffleFvPatchScalarField_H
#define Foam_thermalBaffleFvPatchScalarField_H
#include "autoPtr.H"
#include "regionModel.H"
#include "thermalBaffleModel.H"
#include "extrudePatchMesh.H"
@ -231,6 +229,11 @@ class thermalBaffleFvPatchScalarField
{
// Typedefs
//- The parent boundary condition type
typedef
turbulentTemperatureRadCoupledMixedFvPatchScalarField
parent_bctype;
//- The baffle region model
typedef
regionModels::thermalBaffleModels::thermalBaffleModel
@ -253,12 +256,12 @@ class thermalBaffleFvPatchScalarField
//- Is the baffle internal
bool internal_;
//- Thermal baffle
autoPtr<baffleType> baffle_;
//- Dictionary
dictionary dict_;
//- Thermal baffle
autoPtr<baffleType> baffle_;
//- Auto pointer to extrapolated mesh from patch
autoPtr<extrudePatchMesh> extrudeMeshPtr_;