From 5fb0cd77f105be8b35cc70a7f57f742a87843cd5 Mon Sep 17 00:00:00 2001 From: Kutalmis Bercin Date: Fri, 21 Oct 2022 09:12:39 +0100 Subject: [PATCH] ENH: atmopshericModels: avoid storing common fields in fvOptions --- .../atmPlantCanopyTurbSource.C | 86 ++++++++----- .../atmPlantCanopyTurbSource.H | 62 +++++----- .../atmPlantCanopyUSource.C | 114 ++++++++++++------ .../atmPlantCanopyUSource.H | 61 +++++----- 4 files changed, 190 insertions(+), 133 deletions(-) diff --git a/src/atmosphericModels/fvOptions/atmPlantCanopyTurbSource/atmPlantCanopyTurbSource.C b/src/atmosphericModels/fvOptions/atmPlantCanopyTurbSource/atmPlantCanopyTurbSource.C index 26ecedfb0a..c7df352eb9 100644 --- a/src/atmosphericModels/fvOptions/atmPlantCanopyTurbSource/atmPlantCanopyTurbSource.C +++ b/src/atmosphericModels/fvOptions/atmPlantCanopyTurbSource/atmPlantCanopyTurbSource.C @@ -43,14 +43,45 @@ namespace fv // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // +Foam::volScalarField& Foam::fv::atmPlantCanopyTurbSource::getOrReadField +( + const word& fieldName +) const +{ + auto* ptr = mesh_.getObjectPtr(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::fv::atmPlantCanopyTurbSource::calcPlantCanopyTerm ( const volVectorField::Internal& U ) const { + const volScalarField& Cd = getOrReadField(CdName_); + const volScalarField& LAD = getOrReadField(LADname_); + // (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), - isEpsilon_(false), - rhoName_(coeffs_.getOrDefault("rho", "rho")), + isEpsilon_(true), Cmu_(Zero), C1_(Zero), C2_(Zero), - Cd_ - ( - 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 - ) + CdName_(), + LADname_() { + read(dict); + const auto* turbPtr = mesh_.findObject ( @@ -113,9 +123,8 @@ Foam::fv::atmPlantCanopyTurbSource::atmPlantCanopyTurbSource tmp tepsilon = turbPtr->epsilon(); tmp tomega = turbPtr->omega(); - if (tepsilon.is_reference()) + if (!tepsilon.isTmp()) { - isEpsilon_ = true; fieldNames_[0] = tepsilon().name(); const dictionary& turbDict = turbPtr->coeffDict(); @@ -123,7 +132,7 @@ Foam::fv::atmPlantCanopyTurbSource::atmPlantCanopyTurbSource C1_.read("C1", turbDict); C2_.read("C2", turbDict); } - else if (tomega.is_reference()) + else if (!tomega.isTmp()) { isEpsilon_ = false; 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("Cd", "Cd"); + LADname_ = dict.getOrDefault("LAD", "LAD"); + + (void) getOrReadField(CdName_); + (void) getOrReadField(LADname_); + + return true; +} + + // ************************************************************************* // diff --git a/src/atmosphericModels/fvOptions/atmPlantCanopyTurbSource/atmPlantCanopyTurbSource.H b/src/atmosphericModels/fvOptions/atmPlantCanopyTurbSource/atmPlantCanopyTurbSource.H index a0bb3e2f76..5d255efe32 100644 --- a/src/atmosphericModels/fvOptions/atmPlantCanopyTurbSource/atmPlantCanopyTurbSource.H +++ b/src/atmosphericModels/fvOptions/atmPlantCanopyTurbSource/atmPlantCanopyTurbSource.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2020 ENERCON GmbH - Copyright (C) 2020 OpenCFD Ltd. + Copyright (C) 2020-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -36,15 +36,16 @@ Description Corrections applied to either of the below, if exist: \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] \endverbatim Required fields: \verbatim - epsilon/omega | Dissipation rate OR Spec. dissipation rate [m2/s3]/[1/s] - Cd | Plant canopy drag coefficient [-] - LAD | Leaf area density [1/m] + Cd | Canopy drag coefficient [-] + LAD | Leaf area density [m^2/m^3] + epsilon | Turbulent kinetic energy dissipation rate [m^2/s^3] + omega | Specific dissipation rate [1/s] \endverbatim References: @@ -61,28 +62,24 @@ Usage \verbatim atmPlantCanopyTurbSource1 { - // Mandatory entries (unmodifiable) - type atmPlantCanopyTurbSource; + // Mandatory entries + type atmPlantCanopyTurbSource; - atmPlantCanopyTurbSourceCoeffs - { - // Mandatory (inherited) entries (unmodifiable) - selectionMode all; + // Optional entries + Cd ; + LAD ; - // Optional entries (unmodifiable) - rho rho; - } - - // Optional (inherited) entries + // Inherited entries ... } \endverbatim where the entries mean: \table - Property | Description | Type | Req'd | Dflt - type | Type name: atmPlantCanopyTurbSource | word | yes | - - rho | Name of density field | word | no | rho + Property | Description | Type | Reqd | Deflt + type | Type name: atmPlantCanopyTurbSource | word | yes | - + Cd | Name of operand canopy drag coefficient field | word | no | Cd + LAD | Name of operand leaf area density field | word | no | LAD \endtable The inherited entries are elaborated in: @@ -109,7 +106,7 @@ namespace fv { /*---------------------------------------------------------------------------*\ - Class atmPlantCanopyTurbSource Declaration + Class atmPlantCanopyTurbSource Declaration \*---------------------------------------------------------------------------*/ class atmPlantCanopyTurbSource @@ -121,26 +118,24 @@ class atmPlantCanopyTurbSource //- Internal flag to determine the working field is epsilon or omega Switch isEpsilon_; - //- Name of density field - const word rhoName_; - //- Required turbulence model coefficients (copied from turb model) dimensionedScalar Cmu_; dimensionedScalar C1_; dimensionedScalar C2_; + //- Name of operand canopy drag coefficient field + word CdName_; - // Fields - - //- Plant canopy drag coefficient field [-] - volScalarField Cd_; - - //- Leaf area density field [1/m] - volScalarField LAD_; + //- Name of operand leaf area density field + word LADname_; // 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 tmp calcPlantCanopyTerm ( @@ -221,11 +216,8 @@ public: const label fieldi ); - //- Read source dictionary (effectively no-op) - virtual bool read(const dictionary& dict) - { - return true; - } + //- Read source dictionary + virtual bool read(const dictionary& dict); }; diff --git a/src/atmosphericModels/fvOptions/atmPlantCanopyUSource/atmPlantCanopyUSource.C b/src/atmosphericModels/fvOptions/atmPlantCanopyUSource/atmPlantCanopyUSource.C index b8697d1fa3..158ac96647 100644 --- a/src/atmosphericModels/fvOptions/atmPlantCanopyUSource/atmPlantCanopyUSource.C +++ b/src/atmosphericModels/fvOptions/atmPlantCanopyUSource/atmPlantCanopyUSource.C @@ -42,6 +42,36 @@ namespace fv } +// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // + +Foam::volScalarField& Foam::fv::atmPlantCanopyUSource::getOrReadField +( + const word& fieldName +) const +{ + auto* ptr = mesh_.getObjectPtr(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 * * * * * * * * * * * * * * // Foam::fv::atmPlantCanopyUSource::atmPlantCanopyUSource @@ -53,32 +83,11 @@ Foam::fv::atmPlantCanopyUSource::atmPlantCanopyUSource ) : fv::cellSetOption(sourceName, modelType, dict, mesh), - rhoName_(coeffs_.getOrDefault("rho", "rho")), - Cd_ - ( - 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 - ) + CdName_(), + LADname_() { + read(dict); + fieldNames_.resize(1, "U"); fv::option::resetApplied(); @@ -95,13 +104,17 @@ void Foam::fv::atmPlantCanopyUSource::addSup const label fieldi ) { - const volVectorField& U = eqn.psi(); - - if (V_ > VSMALL) + if (V_ < VSMALL) { - // (SP:Eq. 42) - eqn -= fvm::Sp(Cd_*LAD_*mag(U), U); + return; } + + 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 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 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("Cd", "Cd"); + LADname_ = dict.getOrDefault("LAD", "LAD"); + + (void) getOrReadField(CdName_); + (void) getOrReadField(LADname_); + + return true; } diff --git a/src/atmosphericModels/fvOptions/atmPlantCanopyUSource/atmPlantCanopyUSource.H b/src/atmosphericModels/fvOptions/atmPlantCanopyUSource/atmPlantCanopyUSource.H index 9d0723904c..842e80e6e7 100644 --- a/src/atmosphericModels/fvOptions/atmPlantCanopyUSource/atmPlantCanopyUSource.H +++ b/src/atmosphericModels/fvOptions/atmPlantCanopyUSource/atmPlantCanopyUSource.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2020 ENERCON GmbH - Copyright (C) 2020 OpenCFD Ltd. + Copyright (C) 2020-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -31,7 +31,7 @@ Group grpFvOptionsSources 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. Corrections applied to: @@ -53,6 +53,13 @@ Description Modification of two-equation models to account for plant drag. Boundary-Layer Meteorology, 121(2), 229-266. 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 Usage @@ -60,28 +67,24 @@ Usage \verbatim atmPlantCanopyUSource1 { - // Mandatory entries (unmodifiable) - type atmPlantCanopyUSource; + // Mandatory entries + type atmPlantCanopyUSource; - atmPlantCanopyUSourceCoeffs - { - // Mandatory (inherited) entries (unmodifiable) - selectionMode all; + // Optional entries + Cd ; + LAD ; - // Optional entries (unmodifiable) - rho rho; - } - - // Optional (inherited) entries + // Inherited entries ... } \endverbatim where the entries mean: \table - Property | Description | Type | Req'd | Dflt - type | Type name: atmPlantCanopyUSource | word | yes | - - rho | Name of density field | word | no | rho + Property | Description | Type | Reqd | Deflt + type | Type name: atmPlantCanopyUSource | word | yes | - + Cd | Name of operand canopy drag coefficient field | word | no | Cd + LAD | Name of operand leaf area density field | word | no | LAD \endtable The inherited entries are elaborated in: @@ -108,7 +111,7 @@ namespace fv { /*---------------------------------------------------------------------------*\ - Class atmPlantCanopyUSource Declaration + Class atmPlantCanopyUSource Declaration \*---------------------------------------------------------------------------*/ class atmPlantCanopyUSource @@ -117,17 +120,18 @@ class atmPlantCanopyUSource { // Private Data - //- Name of density field - const word rhoName_; + //- Name of operand canopy drag coefficient field + word CdName_; + + //- Name of operand leaf area density field + word LADname_; - // Fields + // Private Member Functions - //- Plant canopy drag coefficient field [-] - volScalarField Cd_; - - //- Leaf area density field [1/m] - volScalarField LAD_; + //- Return requested field from the object registry + //- or read+register the field to the object registry + volScalarField& getOrReadField(const word& fieldName) const; public: @@ -180,11 +184,8 @@ public: const label fieldi ); - //- Read source dictionary (effectively no-op) - virtual bool read(const dictionary& dict) - { - return true; - } + //- Read source dictionary + virtual bool read(const dictionary& dict); };