ENH: atmopshericModels: avoid storing common fields in fvOptions

This commit is contained in:
Kutalmis Bercin
2022-10-21 09:12:39 +01:00
committed by Andrew Heather
parent b50591166e
commit 5fb0cd77f1
4 changed files with 190 additions and 133 deletions

View File

@ -43,14 +43,45 @@ namespace fv
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
Foam::volScalarField& Foam::fv::atmPlantCanopyTurbSource::getOrReadField
(
const word& fieldName
) const
{
auto* ptr = mesh_.getObjectPtr<volScalarField>(fieldName);
if (!ptr)
{
ptr = new volScalarField
(
IOobject
(
fieldName,
mesh_.time().timeName(),
mesh_,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh_
);
mesh_.objectRegistry::store(ptr);
}
return *ptr;
}
Foam::tmp<Foam::volScalarField::Internal> Foam::tmp<Foam::volScalarField::Internal>
Foam::fv::atmPlantCanopyTurbSource::calcPlantCanopyTerm Foam::fv::atmPlantCanopyTurbSource::calcPlantCanopyTerm
( (
const volVectorField::Internal& U const volVectorField::Internal& U
) const ) const
{ {
const volScalarField& Cd = getOrReadField(CdName_);
const volScalarField& LAD = getOrReadField(LADname_);
// (SP:Eq. 42) // (SP:Eq. 42)
return 12.0*Foam::sqrt(Cmu_)*Cd_()*LAD_()*mag(U); return 12.0*Foam::sqrt(Cmu_)*Cd()*LAD()*mag(U);
} }
@ -65,36 +96,15 @@ Foam::fv::atmPlantCanopyTurbSource::atmPlantCanopyTurbSource
) )
: :
fv::cellSetOption(sourceName, modelType, dict, mesh), fv::cellSetOption(sourceName, modelType, dict, mesh),
isEpsilon_(false), isEpsilon_(true),
rhoName_(coeffs_.getOrDefault<word>("rho", "rho")),
Cmu_(Zero), Cmu_(Zero),
C1_(Zero), C1_(Zero),
C2_(Zero), C2_(Zero),
Cd_ CdName_(),
( LADname_()
IOobject
(
"Cd",
mesh.time().timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
),
LAD_
(
IOobject
(
"LAD",
mesh.time().timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
)
{ {
read(dict);
const auto* turbPtr = const auto* turbPtr =
mesh_.findObject<turbulenceModel> mesh_.findObject<turbulenceModel>
( (
@ -113,9 +123,8 @@ Foam::fv::atmPlantCanopyTurbSource::atmPlantCanopyTurbSource
tmp<volScalarField> tepsilon = turbPtr->epsilon(); tmp<volScalarField> tepsilon = turbPtr->epsilon();
tmp<volScalarField> tomega = turbPtr->omega(); tmp<volScalarField> tomega = turbPtr->omega();
if (tepsilon.is_reference()) if (!tepsilon.isTmp())
{ {
isEpsilon_ = true;
fieldNames_[0] = tepsilon().name(); fieldNames_[0] = tepsilon().name();
const dictionary& turbDict = turbPtr->coeffDict(); const dictionary& turbDict = turbPtr->coeffDict();
@ -123,7 +132,7 @@ Foam::fv::atmPlantCanopyTurbSource::atmPlantCanopyTurbSource
C1_.read("C1", turbDict); C1_.read("C1", turbDict);
C2_.read("C2", turbDict); C2_.read("C2", turbDict);
} }
else if (tomega.is_reference()) else if (!tomega.isTmp())
{ {
isEpsilon_ = false; isEpsilon_ = false;
fieldNames_[0] = tomega().name(); fieldNames_[0] = tomega().name();
@ -214,4 +223,21 @@ void Foam::fv::atmPlantCanopyTurbSource::addSup
} }
bool Foam::fv::atmPlantCanopyTurbSource::read(const dictionary& dict)
{
if (!fv::cellSetOption::read(dict))
{
return false;
}
CdName_ = dict.getOrDefault<word>("Cd", "Cd");
LADname_ = dict.getOrDefault<word>("LAD", "LAD");
(void) getOrReadField(CdName_);
(void) getOrReadField(LADname_);
return true;
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2020 ENERCON GmbH Copyright (C) 2020 ENERCON GmbH
Copyright (C) 2020 OpenCFD Ltd. Copyright (C) 2020-2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -36,15 +36,16 @@ Description
Corrections applied to either of the below, if exist: Corrections applied to either of the below, if exist:
\verbatim \verbatim
epsilon | Turbulent kinetic energy dissipation rate [m2/s3] epsilon | Turbulent kinetic energy dissipation rate [m^2/s^3]
omega | Specific dissipation rate [1/s] omega | Specific dissipation rate [1/s]
\endverbatim \endverbatim
Required fields: Required fields:
\verbatim \verbatim
epsilon/omega | Dissipation rate OR Spec. dissipation rate [m2/s3]/[1/s] Cd | Canopy drag coefficient [-]
Cd | Plant canopy drag coefficient [-] LAD | Leaf area density [m^2/m^3]
LAD | Leaf area density [1/m] epsilon | Turbulent kinetic energy dissipation rate [m^2/s^3]
omega | Specific dissipation rate [1/s]
\endverbatim \endverbatim
References: References:
@ -61,28 +62,24 @@ Usage
\verbatim \verbatim
atmPlantCanopyTurbSource1 atmPlantCanopyTurbSource1
{ {
// Mandatory entries (unmodifiable) // Mandatory entries
type atmPlantCanopyTurbSource; type atmPlantCanopyTurbSource;
atmPlantCanopyTurbSourceCoeffs // Optional entries
{ Cd <word>;
// Mandatory (inherited) entries (unmodifiable) LAD <word>;
selectionMode all;
// Optional entries (unmodifiable) // Inherited entries
rho rho;
}
// Optional (inherited) entries
... ...
} }
\endverbatim \endverbatim
where the entries mean: where the entries mean:
\table \table
Property | Description | Type | Req'd | Dflt Property | Description | Type | Reqd | Deflt
type | Type name: atmPlantCanopyTurbSource | word | yes | - type | Type name: atmPlantCanopyTurbSource | word | yes | -
rho | Name of density field | word | no | rho Cd | Name of operand canopy drag coefficient field | word | no | Cd
LAD | Name of operand leaf area density field | word | no | LAD
\endtable \endtable
The inherited entries are elaborated in: The inherited entries are elaborated in:
@ -121,26 +118,24 @@ class atmPlantCanopyTurbSource
//- Internal flag to determine the working field is epsilon or omega //- Internal flag to determine the working field is epsilon or omega
Switch isEpsilon_; Switch isEpsilon_;
//- Name of density field
const word rhoName_;
//- Required turbulence model coefficients (copied from turb model) //- Required turbulence model coefficients (copied from turb model)
dimensionedScalar Cmu_; dimensionedScalar Cmu_;
dimensionedScalar C1_; dimensionedScalar C1_;
dimensionedScalar C2_; dimensionedScalar C2_;
//- Name of operand canopy drag coefficient field
word CdName_;
// Fields //- Name of operand leaf area density field
word LADname_;
//- Plant canopy drag coefficient field [-]
volScalarField Cd_;
//- Leaf area density field [1/m]
volScalarField LAD_;
// Private Member Functions // Private Member Functions
//- Return requested field from the object registry
//- or read+register the field to the object registry
volScalarField& getOrReadField(const word& fieldName) const;
//- Return the modifier for plant canopy effects //- Return the modifier for plant canopy effects
tmp<volScalarField::Internal> calcPlantCanopyTerm tmp<volScalarField::Internal> calcPlantCanopyTerm
( (
@ -221,11 +216,8 @@ public:
const label fieldi const label fieldi
); );
//- Read source dictionary (effectively no-op) //- Read source dictionary
virtual bool read(const dictionary& dict) virtual bool read(const dictionary& dict);
{
return true;
}
}; };

View File

@ -42,6 +42,36 @@ namespace fv
} }
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
Foam::volScalarField& Foam::fv::atmPlantCanopyUSource::getOrReadField
(
const word& fieldName
) const
{
auto* ptr = mesh_.getObjectPtr<volScalarField>(fieldName);
if (!ptr)
{
ptr = new volScalarField
(
IOobject
(
fieldName,
mesh_.time().timeName(),
mesh_,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh_
);
mesh_.objectRegistry::store(ptr);
}
return *ptr;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fv::atmPlantCanopyUSource::atmPlantCanopyUSource Foam::fv::atmPlantCanopyUSource::atmPlantCanopyUSource
@ -53,32 +83,11 @@ Foam::fv::atmPlantCanopyUSource::atmPlantCanopyUSource
) )
: :
fv::cellSetOption(sourceName, modelType, dict, mesh), fv::cellSetOption(sourceName, modelType, dict, mesh),
rhoName_(coeffs_.getOrDefault<word>("rho", "rho")), CdName_(),
Cd_ LADname_()
(
IOobject
(
"Cd",
mesh.time().timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
),
LAD_
(
IOobject
(
"LAD",
mesh.time().timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
)
{ {
read(dict);
fieldNames_.resize(1, "U"); fieldNames_.resize(1, "U");
fv::option::resetApplied(); fv::option::resetApplied();
@ -95,13 +104,17 @@ void Foam::fv::atmPlantCanopyUSource::addSup
const label fieldi const label fieldi
) )
{ {
const volVectorField& U = eqn.psi(); if (V_ < VSMALL)
if (V_ > VSMALL)
{ {
// (SP:Eq. 42) return;
eqn -= fvm::Sp(Cd_*LAD_*mag(U), U);
} }
const volVectorField& U = eqn.psi();
const volScalarField& Cd = getOrReadField(CdName_);
const volScalarField& LAD = getOrReadField(LADname_);
// (SP:Eq. 42), (BSG:Eq. 7)
eqn -= fvm::Sp(Cd*LAD*mag(U), U);
} }
@ -112,12 +125,16 @@ void Foam::fv::atmPlantCanopyUSource::addSup
const label fieldi const label fieldi
) )
{ {
const volVectorField& U = eqn.psi(); if (V_ < VSMALL)
if (V_ > VSMALL)
{ {
eqn -= fvm::Sp(rho*Cd_*LAD_*mag(U), U); return;
} }
const volVectorField& U = eqn.psi();
const volScalarField& Cd = getOrReadField(CdName_);
const volScalarField& LAD = getOrReadField(LADname_);
eqn -= fvm::Sp(rho*Cd*LAD*mag(U), U);
} }
@ -129,12 +146,33 @@ void Foam::fv::atmPlantCanopyUSource::addSup
const label fieldi const label fieldi
) )
{ {
const volVectorField& U = eqn.psi(); if (V_ < VSMALL)
if (V_ > VSMALL)
{ {
eqn -= fvm::Sp(alpha*rho*Cd_*LAD_*mag(U), U); return;
} }
const volVectorField& U = eqn.psi();
const volScalarField& Cd = getOrReadField(CdName_);
const volScalarField& LAD = getOrReadField(LADname_);
eqn -= fvm::Sp(alpha*rho*Cd*LAD*mag(U), U);
}
bool Foam::fv::atmPlantCanopyUSource::read(const dictionary& dict)
{
if (!fv::cellSetOption::read(dict))
{
return false;
}
CdName_ = dict.getOrDefault<word>("Cd", "Cd");
LADname_ = dict.getOrDefault<word>("LAD", "LAD");
(void) getOrReadField(CdName_);
(void) getOrReadField(LADname_);
return true;
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2020 ENERCON GmbH Copyright (C) 2020 ENERCON GmbH
Copyright (C) 2020 OpenCFD Ltd. Copyright (C) 2020-2022 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -31,7 +31,7 @@ Group
grpFvOptionsSources grpFvOptionsSources
Description Description
Applies sources on velocity, i.e. \c U, to incorporate effects Applies sources on velocity (i.e. \c U) to incorporate effects
of plant canopy for atmospheric boundary layer modelling. of plant canopy for atmospheric boundary layer modelling.
Corrections applied to: Corrections applied to:
@ -53,6 +53,13 @@ Description
Modification of two-equation models to account for plant drag. Modification of two-equation models to account for plant drag.
Boundary-Layer Meteorology, 121(2), 229-266. Boundary-Layer Meteorology, 121(2), 229-266.
DOI:10.1007/s10546-006-9073-5 DOI:10.1007/s10546-006-9073-5
Governing equations (tag:BSG):
Brozovsky, J., Simonsen, A., & Gaitani, N. (2021).
Validation of a CFD model for the evaluation of urban microclimate
at high latitudes: A case study in Trondheim, Norway.
Building and Environment, 205, 108175.
DOI:10.1016/j.buildenv.2021.108175
\endverbatim \endverbatim
Usage Usage
@ -60,28 +67,24 @@ Usage
\verbatim \verbatim
atmPlantCanopyUSource1 atmPlantCanopyUSource1
{ {
// Mandatory entries (unmodifiable) // Mandatory entries
type atmPlantCanopyUSource; type atmPlantCanopyUSource;
atmPlantCanopyUSourceCoeffs // Optional entries
{ Cd <word>;
// Mandatory (inherited) entries (unmodifiable) LAD <word>;
selectionMode all;
// Optional entries (unmodifiable) // Inherited entries
rho rho;
}
// Optional (inherited) entries
... ...
} }
\endverbatim \endverbatim
where the entries mean: where the entries mean:
\table \table
Property | Description | Type | Req'd | Dflt Property | Description | Type | Reqd | Deflt
type | Type name: atmPlantCanopyUSource | word | yes | - type | Type name: atmPlantCanopyUSource | word | yes | -
rho | Name of density field | word | no | rho Cd | Name of operand canopy drag coefficient field | word | no | Cd
LAD | Name of operand leaf area density field | word | no | LAD
\endtable \endtable
The inherited entries are elaborated in: The inherited entries are elaborated in:
@ -117,17 +120,18 @@ class atmPlantCanopyUSource
{ {
// Private Data // Private Data
//- Name of density field //- Name of operand canopy drag coefficient field
const word rhoName_; word CdName_;
//- Name of operand leaf area density field
word LADname_;
// Fields // Private Member Functions
//- Plant canopy drag coefficient field [-] //- Return requested field from the object registry
volScalarField Cd_; //- or read+register the field to the object registry
volScalarField& getOrReadField(const word& fieldName) const;
//- Leaf area density field [1/m]
volScalarField LAD_;
public: public:
@ -180,11 +184,8 @@ public:
const label fieldi const label fieldi
); );
//- Read source dictionary (effectively no-op) //- Read source dictionary
virtual bool read(const dictionary& dict) virtual bool read(const dictionary& dict);
{
return true;
}
}; };