ENH: New atmospheric boundary layer (ABL) model suite (Part 1)

Please refer to the header file documentation for complete set of details.

  ENH: add new fvOptions for ABL modelling

    - atmAmbientTurbSource
    - atmBuoyancyTurbSource
    - atmCoriolisUSource
    - atmLengthScaleTurbSource
    - atmPlantCanopyTurbSource
    - atmPlantCanopyUSource
    - atmPlantCanopyTSource
    - atmNutSource

  ENH: add new boundary conditions for ABL modelling
       with PatchFunction1 and TimeFunction1 support

    - atmAlphatkWallFunction
    - atmEpsilonWallFunction
    - atmNutkWallFunction
    - atmNutUWallFunction
    - atmNutWallFunction
    - atmOmegaWallFunction
    - atmTurbulentHeatFluxTemperature

  STYLE: change names of nutkAtmRoughWallFunction -> atmNutkWallFunction by
         ensuring the bitwise backward compatibility

  ENH: add new variable-scaling force computation method to actuationDiskSource

  ENH: review actuationDiskSource and radialActuationDiskSource

  ENH: add new function object, ObukhovLength

  ENH: add new ABL tutorials/verifications

    - verificationAndValidation/atmosphericModels/atmFlatTerrain
      - verification with the Leipzig field experiment
      - illustration of precursor/successor field mapping
    - verificationAndValidation/atmosphericModels/atmForestStability
      - verification with the Sweden field experiment
    - update incompressible/simpleFoam/turbineSiting
This commit is contained in:
Kutalmis Bercin
2020-05-05 14:20:45 +01:00
committed by Andrew Heather
parent 70cd6c6176
commit 41e264f27d
386 changed files with 53513 additions and 349 deletions

View File

@ -0,0 +1,266 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 ENERCON GmbH
Copyright (C) 2020 OpenCFD 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 "ObukhovLength.H"
#include "volFields.H"
#include "dictionary.H"
#include "Time.H"
#include "mapPolyMesh.H"
#include "addToRunTimeSelectionTable.H"
#include "zeroGradientFvPatchField.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
defineTypeNameAndDebug(ObukhovLength, 0);
addToRunTimeSelectionTable(functionObject, ObukhovLength, dictionary);
}
}
// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
bool Foam::functionObjects::ObukhovLength::calcOL()
{
const auto* rhoPtr = mesh_.findObject<volScalarField>("rho");
const volScalarField& nut = mesh_.lookupObject<volScalarField>("nut");
const volVectorField& U = mesh_.lookupObject<volVectorField>(UName_);
const volScalarField& alphat = mesh_.lookupObject<volScalarField>("alphat");
const volScalarField& T = mesh_.lookupObject<volScalarField>("T");
volScalarField* result1 = mesh_.getObjectPtr<volScalarField>(resultName1_);
volScalarField* result2 = mesh_.getObjectPtr<volScalarField>(resultName2_);
const bool isNew = !result1;
if (!result1)
{
result1 = new volScalarField
(
IOobject
(
resultName1_,
mesh_.time().timeName(),
mesh_,
IOobject::NO_READ,
IOobject::NO_WRITE,
true
),
mesh_,
dimLength,
zeroGradientFvPatchField<scalar>::typeName
);
result1->store();
result2 = new volScalarField
(
IOobject
(
resultName2_,
mesh_.time().timeName(),
mesh_,
IOobject::NO_READ,
IOobject::NO_WRITE,
true
),
mesh_,
dimVelocity,
zeroGradientFvPatchField<scalar>::typeName
);
result2->store();
}
volScalarField B(alphat*beta_*(fvc::grad(T) & g_));
if (rhoPtr)
{
const auto& rho = *rhoPtr;
B /= rho;
}
else
{
const dimensionedScalar rho(dimless, rhoRef_);
B /= rho;
}
*result2 = // Ustar
sqrt
(
max
(
nut*sqrt(2*magSqr(symm(fvc::grad(U)))),
dimensionedScalar(sqr(U.dimensions()), VSMALL)
)
);
// (O:Eq. 26)
*result1 = // ObukhovLength
-min
(
dimensionedScalar(dimLength, ROOTVGREAT), // neutral stratification
pow3(*result2)/
(
sign(B)*kappa_
*max(mag(B), dimensionedScalar(B.dimensions(), VSMALL))
)
);
return isNew;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::ObukhovLength::ObukhovLength
(
const word& name,
const Time& runTime,
const dictionary& dict
)
:
fvMeshFunctionObject(name, runTime, dict),
UName_("U"),
resultName1_("ObukhovLength"),
resultName2_("Ustar"),
rhoRef_(1.0),
kappa_(0.40),
beta_
(
dimensionedScalar
(
dimless/dimTemperature,
dict.getCheckOrDefault<scalar>
(
"beta",
3e-3,
[&](const scalar x){ return x > SMALL; }
)
)
),
g_
(
"g",
dimLength/sqr(dimTime),
meshObjects::gravity::New(mesh_.time()).value()
)
{
read(dict);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::functionObjects::ObukhovLength::read(const dictionary& dict)
{
fvMeshFunctionObject::read(dict),
UName_ = dict.getOrDefault<word>("U", "U");
resultName1_ = dict.getOrDefault<word>("ObukhovLength", "ObukhovLength");
resultName2_ = dict.getOrDefault<word>("Ustar", "Ustar");
if (UName_ != "U" && resultName1_ == "ObukhovLength")
{
resultName1_ += '(' + UName_ + ')';
}
if (UName_ != "U" && resultName1_ == "Ustar")
{
resultName2_ += '(' + UName_ + ')';
}
rhoRef_ = dict.getOrDefault<scalar>("rhoRef", 1.0);
kappa_ = dict.getOrDefault<scalar>("kappa", 0.4);
beta_.value() = dict.getOrDefault<scalar>("beta", 3e-3);
return true;
}
bool Foam::functionObjects::ObukhovLength::execute()
{
Log << type() << " " << name() << " execute:" << endl;
bool isNew = false;
isNew = calcOL();
if (isNew) Log << " (new)" << nl << endl;
return true;
}
bool Foam::functionObjects::ObukhovLength::write()
{
const auto* ioptr1 = mesh_.cfindObject<regIOobject>(resultName1_);
const auto* ioptr2 = mesh_.cfindObject<regIOobject>(resultName2_);
if (ioptr1)
{
Log << type() << " " << name() << " write:" << nl
<< " writing field " << ioptr1->name() << nl
<< " writing field " << ioptr2->name() << endl;
ioptr1->write();
ioptr2->write();
}
return true;
}
void Foam::functionObjects::ObukhovLength::removeObukhovLength()
{
mesh_.thisDb().checkOut(resultName1_);
mesh_.thisDb().checkOut(resultName2_);
}
void Foam::functionObjects::ObukhovLength::updateMesh(const mapPolyMesh& mpm)
{
if (&mpm.mesh() == &mesh_)
{
removeObukhovLength();
}
}
void Foam::functionObjects::ObukhovLength::movePoints(const polyMesh& m)
{
if (&m == &mesh_)
{
removeObukhovLength();
}
}
// ************************************************************************* //

View File

@ -0,0 +1,271 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 ENERCON GmbH
Copyright (C) 2020 OpenCFD 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/>.
Class
Foam::functionObjects::ObukhovLength
Group
grpFieldFunctionObjects
Description
Computes the Obukhov length field and associated friction velocity field.
When scaled by the ground-normal height, i.e. z, the Obukhov length becomes
a dimensionless stability parameter, i.e. z/L, for atmospheric boundary
layer modelling, expressing the relative roles of buoyancy and shear in the
production and dissipation of turbulent kinetic energy.
\f[
u^* = \sqrt{\max (\nu_t \sqrt{2 |\symm{\grad{\u}}|^2}, VSMALL)}
\f]
\f[
L_o = - \frac{(u^*)^3}{sign(B) \kappa \max (|B|, VSMALL)}
\f]
with
\f[
B = \alpha_t \beta \frac{\grad{T} \cdot \vec{g}}{\rho}
\f]
where
\vartable
u^* | Friction velocity [m/s]
\nu_t | Turbulent viscosity [m2/s]
\u | Velocity [m/s]
L_o | Obukhov length [m]
B | Buoyancy production term [m2/s3]
\alpha_t | Kinematic turbulent thermal conductivity [m2/s]/[kg/m/s]
\rho | Density of fluid [-]/[kg/m3]
\beta | Thermal expansion coefficient [1/K]
T | Temperature [K]
g | Gravitational acceleration [m/s2]
VSMALL | A very small number to avoid floating point exceptions
\endvartable
References:
\verbatim
Definition of the Obukhov length (tag:O):
Obukhov, A. M. (1946).
Turbulentnost'v temperaturnoj-neodnorodnoj atmosfere.
Trudy Inst. Theor. Geofiz. AN SSSR, 1, 95-115.
Obukhov, A. M. (1971).
Turbulence in an atmosphere with a non-uniform temperature.
Boundary-layer meteorology, 2(1), 7-29.
DOI:10.1007/BF00718085
Obukhov length. (2016).
In American Meteorological Society - Glossary of meteorology.
Retrieved Apr 1, 2020, from glossary.ametsoc.org/wiki/Obukhov_length
\endverbatim
Required fields:
\verbatim
U | Velocity [m/s]
T | Temperature [K]
nut | Turbulent viscosity [m2/s]
alphat | Kinematic turbulent thermal conductivity [m2/s]/[kg/m/s]
g | Gravitational acceleration [m/s2]
\endverbatim
\table
Operand | Type | Location
input | - | -
output file | - | -
output field 1 | volScalarField | $FOAM_CASE/\<time\>/\<ObukhovLength\>
output field 2 | volScalarField | $FOAM_CASE/\<time\>/\<Ustar\>
\endtable
Usage
Minimal example by using \c system/controlDict.functions:
\verbatim
ObukhovLength1
{
// Mandatory entries (unmodifiable)
type ObukhovLength;
libs (fieldFunctionObjects);
// Optional entries (runtime modifiable)
U U;
result1 ObukhovLength;
result2 Ustar;
rhoRef 1.0;
kappa 0.4;
beta 3e-3;
// Optional (inherited) entries
...
}
\endverbatim
where the entries mean:
\table
Property | Description | Type | Req'd | Dflt
type | Type name: ObukhovLength | word | yes | -
libs | Library name: fieldFunctionObjects | word | yes | -
U | Name of the velocity field | word | no | U
result1 | Name of the output field for ObukhovLength | word | no <!--
--> | ObukhovLength
result2 | Name of the output field for Ustar | word | no | Ustar
rhoRef | Reference density (to convert from kinematic to static <!--
--> pressure) | scalar | no | 1.0
kappa | von Kármán constant | scalar | no | 0.40
beta | Thermal expansion coefficient [1/K] | scalar | no | 3e-3
\endtable
The inherited entries are elaborated in:
- \link functionObject.H \endlink
Minimal example by using the \c postProcess utility:
\verbatim
postProcess -func "ObukhovLength(<UField>)"
\endverbatim
See also
- Foam::functionObjects::fvMeshFunctionObject
- ExtendedCodeGuide::atmosphericModels::functionObjects::ObukhovLength
SourceFiles
ObukhovLength.C
\*---------------------------------------------------------------------------*/
#ifndef functionObjects_ObukhovLength_H
#define functionObjects_ObukhovLength_H
#include "fvMeshFunctionObject.H"
#include "turbulentTransportModel.H"
#include "gravityMeshObject.H"
#include "Enum.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
/*---------------------------------------------------------------------------*\
Class ObukhovLength Declaration
\*---------------------------------------------------------------------------*/
class ObukhovLength
:
public fvMeshFunctionObject
{
protected:
// Protected Data
//- Name of velocity field
word UName_;
//- Name of the output field for ObukhovLength
word resultName1_;
//- Name of the output field for Ustar
word resultName2_;
//- Reference density (to convert from kinematic to static pressure)
scalar rhoRef_;
//- von Kármán constant [-]
scalar kappa_;
//- Thermal expansion coefficient [1/K]
dimensionedScalar beta_;
//- Gravitational acceleration vector [m/s2]
const dimensionedVector g_;
// Protected Member Functions
//- Hard-coded Obukhov length field and friction velocity
// \return true if fields did not previously exist
bool calcOL();
public:
//- Run-time type information
TypeName("ObukhovLength");
// Constructors
//- Construct from Time and dictionary
ObukhovLength
(
const word& name,
const Time& runTime,
const dictionary& dict
);
//- No copy construct
ObukhovLength(const ObukhovLength&) = delete;
//- No copy assignment
void operator=(const ObukhovLength&) = delete;
//- Destructor
virtual ~ObukhovLength() = default;
// Member Functions
//- Remove (checkOut) the output fields from the object registry
void removeObukhovLength();
//- Read the data
virtual bool read(const dictionary& dict);
//- Calculate the output fields
virtual bool execute();
//- Write the output fields
virtual bool write();
//- Update for changes of mesh
virtual void updateMesh(const mapPolyMesh& mpm);
//- Update for mesh point-motion
virtual void movePoints(const polyMesh& m);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace functionObjects
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //