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-2023 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 
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().name(),
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 
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  const dictionary& dict
287 )
288 :
289  fixedValueFvPatchField<scalar>(p, iF, dict),
290  beta1_(dict.lookupOrDefault<scalar>("beta1", 0.075)),
291  blended_(dict.lookupOrDefault<Switch>("blended", false)),
292  G_(),
293  omega_(),
294  initialised_(false),
295  master_(-1),
296  cornerWeights_()
297 {
298  // apply zero-gradient condition on start-up
300 }
301 
302 
304 (
306  const fvPatch& p,
308  const fvPatchFieldMapper& mapper
309 )
310 :
311  fixedValueFvPatchField<scalar>(ptf, p, iF, mapper),
312  beta1_(ptf.beta1_),
313  blended_(ptf.blended_),
314  G_(),
315  omega_(),
316  initialised_(false),
317  master_(-1),
318  cornerWeights_()
319 {}
320 
321 
323 (
326 )
327 :
328  fixedValueFvPatchField<scalar>(owfpsf, iF),
329  beta1_(owfpsf.beta1_),
330  blended_(owfpsf.blended_),
331  G_(),
332  omega_(),
333  initialised_(false),
334  master_(-1),
335  cornerWeights_()
336 {}
337 
338 
339 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
340 
342 {
343  if (patch().index() == master_)
344  {
345  if (init)
346  {
347  G_ = 0.0;
348  }
349 
350  return G_;
351  }
352 
353  return omegaPatch(master_).G();
354 }
355 
356 
358 {
359  if (patch().index() == master_)
360  {
361  if (init)
362  {
363  omega_ = 0.0;
364  }
365 
366  return omega_;
367  }
368 
369  return omegaPatch(master_).omega(init);
370 }
371 
372 
374 {
375  if (updated())
376  {
377  return;
378  }
379 
380  const momentumTransportModel& turbModel =
382 
383  setMaster();
384 
385  if (patch().index() == master_)
386  {
388  calculateTurbulenceFields(turbModel, G(true), omega(true));
389  }
390 
391  const scalarField& G0 = this->G();
392  const scalarField& omega0 = this->omega();
393 
394  FieldType& G =
395  const_cast<FieldType&>
396  (
397  db().lookupObject<FieldType>(turbModel.GName())
398  );
399  FieldType& omega =
400  const_cast<FieldType&>
401  (
402  internalField()
403  );
404 
405  scalarField weights(patch().magSf()/patch().patch().magFaceAreas());
406  forAll(weights, facei)
407  {
408  scalar& w = weights[facei];
409  w = w <= tolerance_ ? 0 : (w - tolerance_)/(1 - tolerance_);
410  }
411 
412  forAll(weights, facei)
413  {
414  const scalar w = weights[facei];
415  const label celli = patch().faceCells()[facei];
416 
417  G[celli] = (1 - w)*G[celli] + w*G0[celli];
418  omega[celli] = (1 - w)*omega[celli] + w*omega0[celli];
419  }
420 
421  this->operator==(scalarField(omega, patch().faceCells()));
422 
424 }
425 
426 
428 (
429  fvMatrix<scalar>& matrix
430 )
431 {
432  if (manipulatedMatrix())
433  {
434  return;
435  }
436 
437  const scalarField& omega0 = this->omega();
438 
439  scalarField weights(patch().magSf()/patch().patch().magFaceAreas());
440  forAll(weights, facei)
441  {
442  scalar& w = weights[facei];
443  w = w <= tolerance_ ? 0 : (w - tolerance_)/(1 - tolerance_);
444  }
445 
446  matrix.setValues
447  (
448  patch().faceCells(),
449  UIndirectList<scalar>(omega0, patch().faceCells()),
450  weights
451  );
452 
454 }
455 
456 
458 {
459  writeEntry(os, "beta1", beta1_);
460  writeEntry(os, "blended", blended_);
462 }
463 
464 
465 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
466 
468 (
471 );
472 
473 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
474 
475 } // End namespace Foam
476 
477 // ************************************************************************* //
scalar y
label k
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
Macros for easy insertion into run-time selection tables.
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:296
Generic GeometricBoundaryField class.
Generic GeometricField class.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
label size() const
Return the number of elements in the UList.
Definition: ListI.H:171
void setSize(const label)
Reset size of List.
Definition: List.C:281
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
Definition: Switch.H:61
bool empty() const
Return true if the UList is empty (ie, size() is zero)
Definition: UListI.H:325
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:160
const word & name() const
Return const reference to name.
This boundary condition supplies a fixed value constraint, and is the base class for a number of othe...
virtual void write(Ostream &) const
Write.
A special matrix type and solver, designed for finite volume solutions of scalar equations....
Definition: fvMatrix.H:118
void setValues(const labelUList &cells, const ListType< Type > &values)
Set solution in given cells to the specified values.
Definition: fvMatrix.C:502
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:101
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:406
Foam::fvPatchFieldMapper.
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Definition: fvPatchField.H:87
bool manipulatedMatrix() const
Return true if the matrix has already been manipulated.
Definition: fvPatchField.H:379
const DimensionedField< Type, volMesh > & internalField() const
Return dimensioned internal field reference.
Definition: fvPatchField.H:361
virtual void operator==(const fvPatchField< Type > &)
Definition: fvPatchField.C:417
virtual tmp< Field< Type > > patchInternalField() const
Return internal field next to patch as patch field.
Definition: fvPatchField.C:172
virtual tmp< Field< Type > > snGrad() const
Return patch-normal gradient.
Definition: fvPatchField.C:164
const objectRegistry & db() const
Return local objectRegistry.
Definition: fvPatchField.C:145
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
Definition: fvPatchField.C:204
virtual void manipulateMatrix(fvMatrix< Type > &matrix)
Manipulate matrix.
Definition: fvPatchField.C:224
const fvPatch & patch() const
Return patch.
Definition: fvPatchField.H:355
bool updated() const
Return true if the boundary condition has already been updated.
Definition: fvPatchField.H:373
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:64
label index() const
Return the index of this patch in the fvBoundaryMesh.
Definition: fvPatch.H:175
virtual const labelUList & faceCells() const
Return faceCells.
Definition: fvPatch.C:99
Abstract base class for turbulence models (RAS, LES and laminar).
virtual tmp< volScalarField > k() const =0
Return the turbulence kinetic energy.
word GName() const
Helper function to return the name of the turbulence G field.
const volVectorField & U() const
Access function to velocity field.
const volScalarField::Boundary & y() const
Return the near wall distance.
virtual tmp< volScalarField > nu() const
Return the laminar viscosity.
This boundary condition provides a turbulent kinematic viscosity condition when using wall functions,...
static scalar yPlusLam(const scalar kappa, const scalar E)
Calculate the Y+ at the edge of the laminar sublayer.
static const nutWallFunctionFvPatchScalarField & nutw(const momentumTransportModel &turbModel, const label patchi)
Return the nut patchField for the given wall patch.
const Type & lookupObject(const word &name) const
Lookup and return the object of the given Type and name.
const Type & lookupType(const word &group=word::null) const
Lookup and return the object of the given Type.
This boundary condition provides a wall constraint on turbulnce specific dissipation,...
scalarField & omega(bool init=false)
Return non-const access to the master's omega field.
virtual void calculate(const momentumTransportModel &turbModel, const List< scalar > &cornerWeights, const fvPatch &patch, scalarField &G, scalarField &omega)
Calculate the omega and G.
scalarField G_
Local copy of turbulence G field.
List< List< scalar > > cornerWeights_
List of averaging corner weights.
Switch blended_
Blending switch (defaults to false)
virtual label & master()
Return non-const access to the master patch ID.
virtual void calculateTurbulenceFields(const momentumTransportModel &turbModel, scalarField &G0, scalarField &omega0)
Main driver to calculate the turbulence fields.
static scalar tolerance_
Tolerance used in weighted calculations.
virtual void manipulateMatrix(fvMatrix< scalar > &matrix)
Manipulate matrix.
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
virtual void createAveragingWeights()
Create the averaging weights for cells which are bounded by.
scalarField & G(bool init=false)
Return non-const access to the master's G field.
omegaWallFunctionFvPatchScalarField(const fvPatch &, const DimensionedField< scalar, volMesh > &, const dictionary &)
Construct from patch, internal field and dictionary.
virtual omegaWallFunctionFvPatchScalarField & omegaPatch(const label patchi)
Helper function to return non-const access to an omega patch.
scalarField omega_
Local copy of turbulence omega field.
virtual void setMaster()
Set the master patch - master is responsible for updating all.
bool changing() const
Is mesh changing.
Definition: polyMesh.H:488
A class for managing temporary objects.
Definition: tmp.H:55
const scalar yPlus
const scalar uPlus
const scalar Rey
label patchi
const dimensionedScalar G0
Conductance quantum: default SI units: [S].
Namespace for OpenFOAM.
const doubleScalar e
Definition: doubleScalar.H:105
dimensionedScalar exp(const dimensionedScalar &ds)
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
dimensionedSymmTensor sqr(const dimensionedVector &dv)
const dimensionSet dimless
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
dimensionedScalar log(const dimensionedScalar &ds)
void writeEntry(Ostream &os, const HashTable< T, Key, Hash > &ht)
Definition: HashTableIO.C:96
dimensionedScalar sqrt(const dimensionedScalar &ds)
dimensioned< scalar > mag(const dimensioned< Type > &)
makePatchTypeField(fvPatchScalarField, atmBoundaryLayerInletEpsilonFvPatchScalarField)
dimensionedScalar pow025(const dimensionedScalar &ds)
dictionary dict
volScalarField & p