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:
committed by
Andrew Heather
parent
70cd6c6176
commit
41e264f27d
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -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
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user