atmosphericBoundaryLayer.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2014-2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
27 #include "Time.H"
28 
29 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
30 
31 namespace Foam
32 {
34 }
35 
37 (
39 );
40 
41 const Foam::scalar Foam::atmosphericBoundaryLayer::kappaDefault_ = 0.41;
42 const Foam::scalar Foam::atmosphericBoundaryLayer::CmuDefault_ = 0.09;
43 
44 
45 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
46 
48 (
49  const vectorField& C
50 ) const
51 {
52  return z0_->value(flowDir_ & C, yDir_ & C);
53 }
54 
55 
57 (
58  const scalarField& z0
59 ) const
60 {
61  return kappa_*Uref_/(log((Zref_ + z0)/z0));
62 }
63 
64 
65 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
66 
68 (
69  const objectRegistry& db
70 )
71 :
73  (
74  IOobject
75  (
76  dictName,
77  db.time().constant(),
78  db,
79  IOobject::MUST_READ,
80  IOobject::NO_WRITE
81  )
82  ),
83  flowDir_(normalised(lookup<vector>("flowDir", dimless))),
84  zDir_(normalised(lookup<vector>("zDir", dimless))),
85  yDir_(zDir_ ^ flowDir_),
86  kappa_(lookupOrDefault<scalar>("kappa", dimless, kappaDefault_)),
87  Cmu_(lookupOrDefault<scalar>("Cmu", dimless, CmuDefault_)),
88  Uref_(lookup<scalar>("Uref", dimVelocity)),
89  Zref_(lookup<scalar>("Zref", dimLength)),
90  z0_
91  (
92  Function2<scalar>::New
93  (
94  "z0",
95  dimLength,
96  dimLength,
97  dimLength,
98  *this
99  )
100  ),
101  zGround_
102  (
103  Function2<scalar>::New
104  (
105  "zGround",
106  dimLength,
107  dimLength,
108  dimLength,
109  *this
110  )
111  ),
112  offset_(found("Ulower")),
113  Ulower_(lookupOrDefault<scalar>("Ulower", dimVelocity, 0)),
114  kLower_(lookupOrDefault<scalar>("kLower", dimEnergy/dimMass, 0)),
115  epsilonLower_
116  (
117  lookupOrDefault<scalar>
118  (
119  "epsilonLower",
121  0
122  )
123  )
124 {
125  if (mag(flowDir_) < small || mag(zDir_) < small)
126  {
128  << "magnitude of n or z must be greater than zero"
129  << abort(FatalError);
130  }
131 }
132 
133 
134 // * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
135 
137 (
138  const objectRegistry& db
139 )
140 {
141  if (db.foundObject<atmosphericBoundaryLayer>(dictName))
142  {
143  return db.lookupObject<atmosphericBoundaryLayer>(dictName);
144  }
145  else
146  {
148 
149  ptr->store();
150 
151  return *ptr;
152  }
153 }
154 
155 
156 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
157 
159 (
160  const vectorField& C
161 ) const
162 {
163  const scalarField x(flowDir_ & C);
164  const scalarField y(yDir_ & C);
165  const scalarField z(zDir_ & C);
166 
167  const scalarField z0(z0_->value(x, y));
168  const scalarField zGround(zGround_->value(x, y));
169 
170  const scalarField Un
171  (
172  (Ustar(z0)/kappa_)
173  *log(max(z - zGround + z0, z0)/z0)
174  );
175 
176  if (offset_)
177  {
178  return flowDir_*Un + flowDir_*Ulower_;
179  }
180  else
181  {
182  return flowDir_*Un;
183  }
184 }
185 
186 
188 (
189  const vectorField& C
190 ) const
191 {
192  const scalarField x(flowDir_ & C);
193  const scalarField y(yDir_ & C);
194  const scalarField z(zDir_ & C);
195 
196  const scalarField z0(z0_->value(x, y));
197  const scalarField zGround(zGround_->value(x, y));
198 
199  tmp<scalarField> tk(sqr(Ustar(z0))/sqrt(Cmu_));
200 
201  if (offset_)
202  {
203  const scalarField zmg(z - zGround);
204  tk.ref() = pos0(zmg)*tk() + neg(zmg)*kLower_;
205  }
206 
207  return tk;
208 }
209 
210 
212 (
213  const vectorField& C
214 ) const
215 {
216  const scalarField x(flowDir_ & C);
217  const scalarField y(yDir_ & C);
218  const scalarField z(zDir_ & C);
219 
220  const scalarField z0(z0_->value(x, y));
221  const scalarField zGround(zGround_->value(x, y));
222  const scalarField zmg(z - zGround);
223 
224  tmp<scalarField> tepsilon
225  (
226  pow3(Ustar(z0))/(kappa_*(zmg + z0))
227  );
228 
229  if (offset_)
230  {
231  tepsilon.ref() = pos0(zmg)*tepsilon() + neg(zmg)*epsilonLower_;
232  }
233 
234  return tepsilon;
235 }
236 
237 
239 {
240  writeEntry(os, "flowDir", flowDir_);
241  writeEntry(os, "zDir", zDir_);
242  writeEntry(os, "kappa", kappa_);
243  writeEntry(os, "Cmu", Cmu_);
244  writeEntry(os, "Uref", Uref_);
245  writeEntry(os, "Zref", Zref_);
246 
247  if (offset_)
248  {
249  writeEntry(os, "Ulower", Ulower_);
250  writeEntry(os, "kLower", kLower_);
251  writeEntry(os, "epsilonLower", epsilonLower_);
252  }
253 
254  writeEntry
255  (
256  os,
257  dimLength,
258  dimLength,
259  dimLength,
260  z0_()
261  );
262 
263  writeEntry
264  (
265  os,
266  dimLength,
267  dimLength,
268  dimLength,
269  zGround_()
270  );
271 }
272 
273 
274 // ************************************************************************* //
scalar y
bool found
Graphite solid properties.
Definition: C.H:51
Run-time selectable function of two variables.
Definition: Function2.H:62
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:57
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
This class provides functions to evaluate the velocity and turbulence distributions appropriate for a...
tmp< scalarField > z0(const vectorField &C) const
Return surface roughness height.
atmosphericBoundaryLayer(const objectRegistry &obr)
Read construct from objectRegistry.
static const atmosphericBoundaryLayer & New(const objectRegistry &db)
Return a reference to the atmosphericBoundaryLayer.
static const word dictName
The name of the dictionary.
tmp< scalarField > Ustar(const scalarField &z0) const
Return friction velocity.
tmp< vectorField > U(const vectorField &p) const
Return the velocity field.
virtual bool write(const bool write=true) const
Inherit write from regIOobject.
tmp< scalarField > k(const vectorField &p) const
Return the turbulent kinetic energy field.
tmp< scalarField > epsilon(const vectorField &p) const
Return the turbulent dissipation rate field.
Registry of regIOobjects.
const Type & lookupObject(const word &name) const
Lookup and return the object of the given Type and name.
bool foundObject(const word &name) const
Is the named Type in registry.
void store()
Transfer ownership of this object to its registry.
Definition: regIOobjectI.H:40
A class for managing temporary objects.
Definition: tmp.H:55
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:197
A class for handling words, derived from string.
Definition: word.H:63
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
const dimensionSet time
const unitSet & lookup(const word &unitName)
Lookup and return the named unit from the table.
Definition: units.C:346
Namespace for OpenFOAM.
const dimensionSet & dimless
Definition: dimensions.C:138
dimensionedScalar pos0(const dimensionedScalar &ds)
const dimensionSet & dimMass
Definition: dimensions.C:140
const dimensionSet & dimLength
Definition: dimensions.C:141
String typeName(const std::type_info &info)
Return the un-mangled name given the standard type info.
errorManip< error > abort(error &err)
Definition: errorManip.H:131
dimensionedScalar log(const dimensionedScalar &ds)
tmp< DimensionedField< typename outerProduct< Type, Type >::type, GeoMesh, Field >> sqr(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
const dimensionSet & dimVelocity
Definition: dimensions.C:154
const dimensionSet & dimTime
Definition: dimensions.C:142
dimensionSet normalised(const dimensionSet &)
Definition: dimensionSet.C:509
void pow3(LagrangianPatchField< scalar > &f, const LagrangianPatchField< scalar > &f1)
dimensionedScalar neg(const dimensionedScalar &ds)
tmp< DimensionedField< scalar, GeoMesh, Field > > mag(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
const dimensionSet & dimEnergy
Definition: dimensions.C:160
error FatalError
void sqrt(LagrangianPatchField< scalar > &f, const LagrangianPatchField< scalar > &f1)
defineTypeNameAndDebug(atmosphericBoundaryLayer, 0)
tmp< DimensionedField< TypeR, GeoMesh, Field > > New(const tmp< DimensionedField< TypeR, GeoMesh, Field >> &tdf1, const word &name, const dimensionSet &dimensions)
void writeEntry(Ostream &os, const word &key, const DimensionedFieldFunction< DimensionedFieldType > &f)
dimensioned< Type > max(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)