omegaWallFunctionFvPatchScalarField.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) 2011-2022 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 
28 #include "momentumTransportModel.H"
29 #include "fvMatrix.H"
31 
32 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
33 
34 namespace Foam
35 {
36 
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38 
39 scalar omegaWallFunctionFvPatchScalarField::tolerance_ = 1e-1;
40 
41 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
42 
44 {
45  if (master_ != -1)
46  {
47  return;
48  }
49 
50  const volScalarField& omega =
51  static_cast<const volScalarField&>(this->internalField());
52 
53  const volScalarField::Boundary& bf = omega.boundaryField();
54 
55  label master = -1;
56  forAll(bf, patchi)
57  {
58  if (isA<omegaWallFunctionFvPatchScalarField>(bf[patchi]))
59  {
61 
62  if (master == -1)
63  {
64  master = patchi;
65  }
66 
67  opf.master() = master;
68  }
69  }
70 }
71 
72 
74 {
75  const volScalarField& omega =
76  static_cast<const volScalarField&>(this->internalField());
77 
78  const volScalarField::Boundary& bf = omega.boundaryField();
79 
80  const fvMesh& mesh = omega.mesh();
81 
82  if (initialised_ && !mesh.changing())
83  {
84  return;
85  }
86 
87  volScalarField weights
88  (
89  IOobject
90  (
91  "weights",
92  mesh.time().timeName(),
93  mesh,
96  false // do not register
97  ),
98  mesh,
100  );
101 
102  DynamicList<label> omegaPatches(bf.size());
103  forAll(bf, patchi)
104  {
105  if (isA<omegaWallFunctionFvPatchScalarField>(bf[patchi]))
106  {
107  omegaPatches.append(patchi);
108 
109  const labelUList& faceCells = bf[patchi].patch().faceCells();
110  forAll(faceCells, i)
111  {
112  label celli = faceCells[i];
113  weights[celli]++;
114  }
115  }
116  }
117 
119  forAll(omegaPatches, i)
120  {
121  label patchi = omegaPatches[i];
122  const fvPatchScalarField& wf = weights.boundaryField()[patchi];
124  }
125 
126  G_.setSize(internalField().size(), 0.0);
127  omega_.setSize(internalField().size(), 0.0);
128 
129  initialised_ = true;
130 }
131 
132 
135 {
136  const volScalarField& omega =
137  static_cast<const volScalarField&>(this->internalField());
138 
139  const volScalarField::Boundary& bf = omega.boundaryField();
140 
142  refCast<const omegaWallFunctionFvPatchScalarField>(bf[patchi]);
143 
144  return const_cast<omegaWallFunctionFvPatchScalarField&>(opf);
145 }
146 
147 
149 (
150  const momentumTransportModel& turbModel,
151  scalarField& G0,
152  scalarField& omega0
153 )
154 {
155  // Ask for the wall distance in advance. Some processes may not have any
156  // corner weights, so we cannot allow functions inside the if statements
157  // below to trigger the wall distance calculation.
158  turbModel.y();
159 
160  // accumulate all of the G and omega contributions
162  {
163  if (!cornerWeights_[patchi].empty())
164  {
166 
167  const List<scalar>& w = cornerWeights_[patchi];
168 
169  opf.calculate(turbModel, w, opf.patch(), G0, omega0);
170  }
171  }
172 
173  // apply zero-gradient condition for omega
175  {
176  if (!cornerWeights_[patchi].empty())
177  {
179 
180  opf == scalarField(omega0, opf.patch().faceCells());
181  }
182  }
183 }
184 
185 
187 (
188  const momentumTransportModel& turbModel,
189  const List<scalar>& cornerWeights,
190  const fvPatch& patch,
191  scalarField& G0,
192  scalarField& omega0
193 )
194 {
195  const label patchi = patch.index();
196 
198  nutWallFunctionFvPatchScalarField::nutw(turbModel, patchi);
199 
200  const scalarField& y = turbModel.y()[patchi];
201 
202  const tmp<volScalarField> tk = turbModel.k();
203  const volScalarField& k = tk();
204 
205  const tmp<scalarField> tnuw = turbModel.nu(patchi);
206  const scalarField& nuw = tnuw();
207 
208  const fvPatchVectorField& Uw = turbModel.U().boundaryField()[patchi];
209 
210  const scalarField magGradUw(mag(Uw.snGrad()));
211 
212  const FieldType& G =
213  db().lookupObject<FieldType>(turbModel.GName());
214 
215  const scalar Cmu25 = pow025(nutw.Cmu());
216  const scalar Cmu5 = sqrt(nutw.Cmu());
217 
218  // Set omega and G
219  forAll(nutw, facei)
220  {
221  const label celli = patch.faceCells()[facei];
222  const scalar w = cornerWeights[facei];
223 
224  const scalar Rey = y[facei]*sqrt(k[celli])/nuw[facei];
225  const scalar yPlus = Cmu25*Rey;
226  const scalar uPlus = (1/nutw.kappa())*log(nutw.E()*yPlus);
227 
228  if (blended_)
229  {
230  const scalar lamFrac = exp(-Rey/11);
231  const scalar turbFrac = 1 - lamFrac;
232 
233  const scalar uStar = sqrt
234  (
235  lamFrac*nuw[facei]*magGradUw[facei] + turbFrac*Cmu5*k[celli]
236  );
237 
238  const scalar omegaVis = 6*nuw[facei]/(beta1_*sqr(y[facei]));
239  const scalar omegaLog = uStar/(Cmu5*nutw.kappa()*y[facei]);
240 
241  omega0[celli] += w*(lamFrac*omegaVis + turbFrac*omegaLog);
242 
243  G0[celli] +=
244  w
245  *(
246  lamFrac*G[celli]
247 
248  + turbFrac
249  *sqr(uStar*magGradUw[facei]*y[facei]/uPlus)
250  /(nuw[facei]*nutw.kappa()*yPlus)
251  );
252  }
253  else
254  {
255  if (yPlus < nutw.yPlusLam())
256  {
257  const scalar omegaVis = 6*nuw[facei]/(beta1_*sqr(y[facei]));
258 
259  omega0[celli] += w*omegaVis;
260 
261  G0[celli] += w*G[celli];
262  }
263  else
264  {
265  const scalar uStar = sqrt(Cmu5*k[celli]);
266  const scalar omegaLog = uStar/(Cmu5*nutw.kappa()*y[facei]);
267 
268  omega0[celli] += w*omegaLog;
269 
270  G0[celli] +=
271  w*
272  sqr(uStar*magGradUw[facei]*y[facei]/uPlus)
273  /(nuw[facei]*nutw.kappa()*yPlus);
274  }
275  }
276  }
277 }
278 
279 
280 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
281 
283 (
284  const fvPatch& p,
286 )
287 :
289  beta1_(0.075),
290  blended_(false),
291  G_(),
292  omega_(),
293  initialised_(false),
294  master_(-1),
296 {}
297 
298 
300 (
301  const fvPatch& p,
303  const dictionary& dict
304 )
305 :
307  beta1_(dict.lookupOrDefault<scalar>("beta1", 0.075)),
308  blended_(dict.lookupOrDefault<Switch>("blended", false)),
309  G_(),
310  omega_(),
311  initialised_(false),
312  master_(-1),
314 {
315  // apply zero-gradient condition on start-up
317 }
318 
319 
321 (
323  const fvPatch& p,
325  const fvPatchFieldMapper& mapper
326 )
327 :
328  fixedValueFvPatchField<scalar>(ptf, p, iF, mapper),
329  beta1_(ptf.beta1_),
330  blended_(ptf.blended_),
331  G_(),
332  omega_(),
333  initialised_(false),
334  master_(-1),
336 {}
337 
338 
340 (
343 )
344 :
345  fixedValueFvPatchField<scalar>(owfpsf, iF),
346  beta1_(owfpsf.beta1_),
347  blended_(owfpsf.blended_),
348  G_(),
349  omega_(),
350  initialised_(false),
351  master_(-1),
353 {}
354 
355 
356 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
357 
359 {
360  if (patch().index() == master_)
361  {
362  if (init)
363  {
364  G_ = 0.0;
365  }
366 
367  return G_;
368  }
369 
370  return omegaPatch(master_).G();
371 }
372 
373 
375 {
376  if (patch().index() == master_)
377  {
378  if (init)
379  {
380  omega_ = 0.0;
381  }
382 
383  return omega_;
384  }
385 
386  return omegaPatch(master_).omega(init);
387 }
388 
389 
391 {
392  if (updated())
393  {
394  return;
395  }
396 
397  const momentumTransportModel& turbModel =
399  (
401  (
402  momentumTransportModel::typeName,
403  internalField().group()
404  )
405  );
406 
407  setMaster();
408 
409  if (patch().index() == master_)
410  {
412  calculateTurbulenceFields(turbModel, G(true), omega(true));
413  }
414 
415  const scalarField& G0 = this->G();
416  const scalarField& omega0 = this->omega();
417 
418  FieldType& G =
419  const_cast<FieldType&>
420  (
421  db().lookupObject<FieldType>(turbModel.GName())
422  );
423  FieldType& omega =
424  const_cast<FieldType&>
425  (
426  internalField()
427  );
428 
429  scalarField weights(patch().magSf()/patch().patch().magFaceAreas());
430  forAll(weights, facei)
431  {
432  scalar& w = weights[facei];
433  w = w <= tolerance_ ? 0 : (w - tolerance_)/(1 - tolerance_);
434  }
435 
436  forAll(weights, facei)
437  {
438  const scalar w = weights[facei];
439  const label celli = patch().faceCells()[facei];
440 
441  G[celli] = (1 - w)*G[celli] + w*G0[celli];
442  omega[celli] = (1 - w)*omega[celli] + w*omega0[celli];
443  }
444 
445  this->operator==(scalarField(omega, patch().faceCells()));
446 
448 }
449 
450 
452 (
453  fvMatrix<scalar>& matrix
454 )
455 {
456  if (manipulatedMatrix())
457  {
458  return;
459  }
460 
461  const scalarField& omega0 = this->omega();
462 
463  scalarField weights(patch().magSf()/patch().patch().magFaceAreas());
464  forAll(weights, facei)
465  {
466  scalar& w = weights[facei];
467  w = w <= tolerance_ ? 0 : (w - tolerance_)/(1 - tolerance_);
468  }
469 
470  matrix.setValues
471  (
472  patch().faceCells(),
473  UIndirectList<scalar>(omega0, patch().faceCells()),
474  weights
475  );
476 
478 }
479 
480 
482 {
483  writeEntry(os, "beta1", beta1_);
484  writeEntry(os, "blended", blended_);
486 }
487 
488 
489 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
490 
492 (
495 );
496 
497 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
498 
499 } // End namespace Foam
500 
501 // ************************************************************************* //
const char *const group
Group name for atomic constants.
scalar uPlus
bool changing() const
Is mesh changing (topology changing and/or moving)
Definition: polyMesh.H:537
dictionary dict
virtual tmp< volScalarField > nu() const
Return the laminar viscosity.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
bool empty() const
Return true if the UList is empty (ie, size() is zero)
Definition: UListI.H:325
Switch blended_
Blending switch (defaults to false)
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
virtual void write(Ostream &) const
Write.
virtual tmp< Field< Type > > snGrad() const
Return patch-normal gradient.
Definition: fvPatchField.C:166
scalar Rey
dimensionedScalar log(const dimensionedScalar &ds)
label index() const
Return the index of this patch in the fvBoundaryMesh.
Definition: fvPatch.H:175
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:156
omegaWallFunctionFvPatchScalarField(const fvPatch &, const DimensionedField< scalar, volMesh > &)
Construct from patch and internal field.
bool updated() const
Return true if the boundary condition has already been updated.
Definition: fvPatchField.H:369
const Boundary & boundaryField() const
Return const-reference to the boundary field.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
dimensionedScalar sqrt(const dimensionedScalar &ds)
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:63
dimensionedScalar pow025(const dimensionedScalar &ds)
A simple wrapper around bool so that it can be read as a word: true/false, on/off, yes/no, y/n, t/f, or none/any.
Definition: Switch.H:60
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Definition: fvPatchField.H:66
virtual void createAveragingWeights()
Create the averaging weights for cells which are bounded by.
const dimensionSet dimless
label k
Boltzmann constant.
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:372
bool manipulatedMatrix() const
Return true if the matrix has already been manipulated.
Definition: fvPatchField.H:375
fvMesh & mesh
const Type & lookupObject(const word &name) const
Lookup and return the object of the given Type.
const volScalarField::Boundary & y() const
Return the near wall distance.
Macros for easy insertion into run-time selection tables.
virtual void operator==(const fvPatchField< Type > &)
Definition: fvPatchField.C:424
scalarField & G(bool init=false)
Return non-const access to the master&#39;s G field.
static const nutWallFunctionFvPatchScalarField & nutw(const momentumTransportModel &turbModel, const label patchi)
Return the nut patchField for the given wall patch.
scalar y
This boundary condition provides a turbulent kinematic viscosity condition when using wall functions...
virtual omegaWallFunctionFvPatchScalarField & omegaPatch(const label patchi)
Helper function to return non-const access to an omega patch.
dimensionedScalar exp(const dimensionedScalar &ds)
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:56
static word timeName(const scalar, const int precision=curPrecision_)
Return time name of given scalar time.
Definition: Time.C:666
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
virtual const labelUList & faceCells() const
Return faceCells.
Definition: fvPatch.C:99
static word groupName(Name name, const word &group)
Foam::fvPatchFieldMapper.
static scalar tolerance_
Tolerance used in weighted calculations.
A special matrix type and solver, designed for finite volume solutions of scalar equations. Face addressing is used to make all matrix assembly and solution loops vectorise.
Definition: fvPatchField.H:72
virtual void manipulateMatrix(fvMatrix< Type > &matrix)
Manipulate matrix.
Definition: fvPatchField.C:236
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:60
const fvPatch & patch() const
Return patch.
Definition: fvPatchField.H:351
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:54
virtual void calculate(const momentumTransportModel &turbModel, const List< scalar > &cornerWeights, const fvPatch &patch, scalarField &G, scalarField &omega)
Calculate the omega and G.
virtual tmp< Field< Type > > patchInternalField() const
Return internal field next to patch as patch field.
Definition: fvPatchField.C:174
const Mesh & mesh() const
Return mesh.
List< List< scalar > > cornerWeights_
List of averaging corner weights.
void writeEntry(Ostream &os, const HashTable< T, Key, Hash > &ht)
Definition: HashTableIO.C:96
scalarField G_
Local copy of turbulence G field.
virtual tmp< volScalarField > k() const =0
Return the turbulence kinetic energy.
Abstract base class for turbulence models (RAS, LES and laminar).
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
scalarField & omega(bool init=false)
Return non-const access to the master&#39;s omega field.
void setValues(const labelUList &cells, const ListType< Type > &values)
Set solution in given cells to the specified values.
Definition: fvMatrix.C:502
void setSize(const label)
Reset size of List.
Definition: List.C:281
const volVectorField & U() const
Access function to velocity field.
label patchi
This boundary condition provides a wall constraint on turbulnce specific dissipation, omega for both low and high Reynolds number turbulence models.
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
const dimensionedScalar G0
Conductance quantum: default SI units: [S].
scalar yPlus
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
Definition: fvPatchField.C:216
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:95
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
const objectRegistry & db() const
Return local objectRegistry.
Definition: fvPatchField.C:147
dimensioned< scalar > mag(const dimensioned< Type > &)
virtual void setMaster()
Set the master patch - master is responsible for updating all.
const doubleScalar e
Elementary charge.
Definition: doubleScalar.H:105
word GName() const
Helper function to return the name of the turbulence G field.
static scalar yPlusLam(const scalar kappa, const scalar E)
Calculate the Y+ at the edge of the laminar sublayer.
volScalarField & p
A class for managing temporary objects.
Definition: PtrList.H:53
virtual label & master()
Return non-const access to the master patch ID.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:98
virtual void manipulateMatrix(fvMatrix< scalar > &matrix)
Manipulate matrix.
makePatchTypeField(fvPatchScalarField, atmBoundaryLayerInletEpsilonFvPatchScalarField)
label size() const
Return the number of elements in the UList.
Definition: ListI.H:171
scalarField omega_
Local copy of turbulence omega field.
virtual void calculateTurbulenceFields(const momentumTransportModel &turbModel, scalarField &G0, scalarField &omega0)
Main driver to calculate the turbulence fields.
Namespace for OpenFOAM.
const DimensionedField< Type, volMesh > & internalField() const
Return dimensioned internal field reference.
Definition: fvPatchField.H:357