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-2019 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 "turbulenceModel.H"
29 #include "fvMatrix.H"
31 
32 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
33 
34 namespace Foam
35 {
36 
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38 
39 scalar omegaWallFunctionFvPatchScalarField::tolerance_ = 1e-5;
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 
118  cornerWeights_.setSize(bf.size());
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 turbulenceModel& turbModel,
151  scalarField& G0,
152  scalarField& omega0
153 )
154 {
155  // accumulate all of the G and omega contributions
157  {
158  if (!cornerWeights_[patchi].empty())
159  {
161 
162  const List<scalar>& w = cornerWeights_[patchi];
163 
164  opf.calculate(turbModel, w, opf.patch(), G0, omega0);
165  }
166  }
167 
168  // apply zero-gradient condition for omega
170  {
171  if (!cornerWeights_[patchi].empty())
172  {
174 
175  opf == scalarField(omega0, opf.patch().faceCells());
176  }
177  }
178 }
179 
180 
182 (
183  const turbulenceModel& turbModel,
184  const List<scalar>& cornerWeights,
185  const fvPatch& patch,
186  scalarField& G0,
187  scalarField& omega0
188 )
189 {
190  const label patchi = patch.index();
191 
193  nutWallFunctionFvPatchScalarField::nutw(turbModel, patchi);
194 
195  const scalarField& y = turbModel.y()[patchi];
196 
197  const tmp<volScalarField> tk = turbModel.k();
198  const volScalarField& k = tk();
199 
200  const tmp<scalarField> tnuw = turbModel.nu(patchi);
201  const scalarField& nuw = tnuw();
202 
203  const fvPatchVectorField& Uw = turbModel.U().boundaryField()[patchi];
204 
205  const scalarField magGradUw(mag(Uw.snGrad()));
206 
207  const FieldType& G =
208  db().lookupObject<FieldType>(turbModel.GName());
209 
210  const scalar Cmu25 = pow025(nutw.Cmu());
211  const scalar Cmu5 = sqrt(nutw.Cmu());
212 
213  // Set omega and G
214  forAll(nutw, facei)
215  {
216  const label celli = patch.faceCells()[facei];
217  const scalar w = cornerWeights[facei];
218 
219  const scalar Rey = y[facei]*sqrt(k[celli])/nuw[facei];
220  const scalar yPlus = Cmu25*Rey;
221  const scalar uPlus = (1/nutw.kappa())*log(nutw.E()*yPlus);
222 
223  if (blended_)
224  {
225  const scalar lamFrac = exp(-Rey/11);
226  const scalar turbFrac = 1 - lamFrac;
227 
228  const scalar uStar = sqrt
229  (
230  lamFrac*nuw[facei]*magGradUw[facei] + turbFrac*Cmu5*k[celli]
231  );
232 
233  const scalar omegaVis = 6*nuw[facei]/(beta1_*sqr(y[facei]));
234  const scalar omegaLog = uStar/(Cmu5*nutw.kappa()*y[facei]);
235 
236  omega0[celli] += w*(lamFrac*omegaVis + turbFrac*omegaLog);
237 
238  G0[celli] +=
239  w
240  *(
241  lamFrac*G[celli]
242 
243  + turbFrac
244  *sqr(uStar*magGradUw[facei]*y[facei]/uPlus)
245  /(nuw[facei]*nutw.kappa()*yPlus)
246  );
247  }
248  else
249  {
250  if (yPlus < nutw.yPlusLam())
251  {
252  const scalar omegaVis = 6*nuw[facei]/(beta1_*sqr(y[facei]));
253 
254  omega0[celli] += w*omegaVis;
255 
256  G0[celli] += w*G[celli];
257  }
258  else
259  {
260  const scalar uStar = sqrt(Cmu5*k[celli]);
261  const scalar omegaLog = uStar/(Cmu5*nutw.kappa()*y[facei]);
262 
263  omega0[celli] += w*omegaLog;
264 
265  G0[celli] +=
266  w*
267  sqr(uStar*magGradUw[facei]*y[facei]/uPlus)
268  /(nuw[facei]*nutw.kappa()*yPlus);
269  }
270  }
271  }
272 }
273 
274 
275 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
276 
278 (
279  const fvPatch& p,
281 )
282 :
284  beta1_(0.075),
285  blended_(false),
286  G_(),
287  omega_(),
288  initialised_(false),
289  master_(-1),
291 {}
292 
293 
295 (
296  const fvPatch& p,
298  const dictionary& dict
299 )
300 :
302  beta1_(dict.lookupOrDefault<scalar>("beta1", 0.075)),
303  blended_(dict.lookupOrDefault<Switch>("blended", false)),
304  G_(),
305  omega_(),
306  initialised_(false),
307  master_(-1),
309 {
310  // apply zero-gradient condition on start-up
312 }
313 
314 
316 (
318  const fvPatch& p,
320  const fvPatchFieldMapper& mapper
321 )
322 :
323  fixedValueFvPatchField<scalar>(ptf, p, iF, mapper),
324  beta1_(ptf.beta1_),
325  blended_(ptf.blended_),
326  G_(),
327  omega_(),
328  initialised_(false),
329  master_(-1),
331 {}
332 
333 
335 (
337 )
338 :
340  beta1_(owfpsf.beta1_),
341  blended_(owfpsf.blended_),
342  G_(),
343  omega_(),
344  initialised_(false),
345  master_(-1),
347 {}
348 
349 
351 (
354 )
355 :
356  fixedValueFvPatchField<scalar>(owfpsf, iF),
357  beta1_(owfpsf.beta1_),
358  blended_(owfpsf.blended_),
359  G_(),
360  omega_(),
361  initialised_(false),
362  master_(-1),
364 {}
365 
366 
367 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
368 
370 {
371  if (patch().index() == master_)
372  {
373  if (init)
374  {
375  G_ = 0.0;
376  }
377 
378  return G_;
379  }
380 
381  return omegaPatch(master_).G();
382 }
383 
384 
386 {
387  if (patch().index() == master_)
388  {
389  if (init)
390  {
391  omega_ = 0.0;
392  }
393 
394  return omega_;
395  }
396 
397  return omegaPatch(master_).omega(init);
398 }
399 
400 
402 {
403  if (updated())
404  {
405  return;
406  }
407 
408  const turbulenceModel& turbModel = db().lookupObject<turbulenceModel>
409  (
411  (
413  internalField().group()
414  )
415  );
416 
417  setMaster();
418 
419  if (patch().index() == master_)
420  {
422  calculateTurbulenceFields(turbModel, G(true), omega(true));
423  }
424 
425  const scalarField& G0 = this->G();
426  const scalarField& omega0 = this->omega();
427 
428  FieldType& G =
429  const_cast<FieldType&>
430  (
431  db().lookupObject<FieldType>(turbModel.GName())
432  );
433 
434  FieldType& omega = const_cast<FieldType&>(internalField());
435 
436  forAll(*this, facei)
437  {
438  label celli = patch().faceCells()[facei];
439 
440  G[celli] = G0[celli];
441  omega[celli] = omega0[celli];
442  }
443 
445 }
446 
447 
449 (
450  const scalarField& weights
451 )
452 {
453  if (updated())
454  {
455  return;
456  }
457 
458  const turbulenceModel& turbModel = db().lookupObject<turbulenceModel>
459  (
461  (
463  internalField().group()
464  )
465  );
466 
467  setMaster();
468 
469  if (patch().index() == master_)
470  {
472  calculateTurbulenceFields(turbModel, G(true), omega(true));
473  }
474 
475  const scalarField& G0 = this->G();
476  const scalarField& omega0 = this->omega();
477 
478  FieldType& G =
479  const_cast<FieldType&>
480  (
481  db().lookupObject<FieldType>(turbModel.GName())
482  );
483 
484  FieldType& omega = const_cast<FieldType&>(internalField());
485 
486  scalarField& omegaf = *this;
487 
488  // only set the values if the weights are > tolerance
489  forAll(weights, facei)
490  {
491  scalar w = weights[facei];
492 
493  if (w > tolerance_)
494  {
495  label celli = patch().faceCells()[facei];
496 
497  G[celli] = (1.0 - w)*G[celli] + w*G0[celli];
498  omega[celli] = (1.0 - w)*omega[celli] + w*omega0[celli];
499  omegaf[facei] = omega[celli];
500  }
501  }
502 
504 }
505 
506 
508 (
509  fvMatrix<scalar>& matrix
510 )
511 {
512  if (manipulatedMatrix())
513  {
514  return;
515  }
516 
517  matrix.setValues(patch().faceCells(), patchInternalField());
518 
520 }
521 
522 
524 (
525  fvMatrix<scalar>& matrix,
526  const Field<scalar>& weights
527 )
528 {
529  if (manipulatedMatrix())
530  {
531  return;
532  }
533 
534  DynamicList<label> constraintCells(weights.size());
535  DynamicList<scalar> constraintomega(weights.size());
536  const labelUList& faceCells = patch().faceCells();
537 
539  = internalField();
540 
541  label nConstrainedCells = 0;
542 
543 
544  forAll(weights, facei)
545  {
546  // only set the values if the weights are > tolerance
547  if (weights[facei] > tolerance_)
548  {
549  nConstrainedCells++;
550 
551  label celli = faceCells[facei];
552 
553  constraintCells.append(celli);
554  constraintomega.append(omega[celli]);
555  }
556  }
557 
558  if (debug)
559  {
560  Pout<< "Patch: " << patch().name()
561  << ": number of constrained cells = " << nConstrainedCells
562  << " out of " << patch().size()
563  << endl;
564  }
565 
566  matrix.setValues
567  (
568  constraintCells,
569  scalarField(constraintomega)
570  );
571 
573 }
574 
575 
577 {
578  writeEntry(os, "beta1", beta1_);
579  writeEntry(os, "blended", blended_);
581 }
582 
583 
584 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
585 
587 (
590 );
591 
592 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
593 
594 } // End namespace Foam
595 
596 // ************************************************************************* //
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:540
dictionary dict
#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:313
Switch blended_
Blending switch (defaults to false)
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
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:186
scalar Rey
const dimensionedScalar G0
Conductance quantum: default SI units: [S].
dimensionedScalar log(const dimensionedScalar &ds)
const volVectorField & U() const
Access function to velocity field.
label index() const
Return the index of this patch in the fvBoundaryMesh.
Definition: fvPatch.H:173
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:158
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:356
const Boundary & boundaryField() const
Return const-reference to the boundary field.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:163
virtual tmp< volScalarField > nu() const =0
Return the laminar viscosity.
virtual void updateWeightedCoeffs(const scalarField &weights)
Update the coefficients associated with the patch field.
dimensionedScalar sqrt(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:256
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:61
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.
static word timeName(const scalar, const int precision=precision_)
Return time name of given scalar time.
Definition: Time.C:626
label k
Boltzmann constant.
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:239
bool manipulatedMatrix() const
Return true if the matrix has already been manipulated.
Definition: fvPatchField.H:362
const Type & lookupObject(const word &name) const
Lookup and return the object of the given Type.
word GName() const
Helper function to return the name of the turbulence G field.
Abstract base class for turbulence models (RAS, LES and laminar).
Macros for easy insertion into run-time selection tables.
virtual void operator==(const fvPatchField< Type > &)
Definition: fvPatchField.C:461
scalarField & G(bool init=false)
Return non-const access to the master&#39;s G field.
virtual tmp< volScalarField > k() const =0
Return the turbulence kinetic energy.
scalar y
This boundary condition provides a turbulent kinematic viscosity condition when using wall functions...
dynamicFvMesh & mesh
virtual omegaWallFunctionFvPatchScalarField & omegaPatch(const label patchi)
Helper function to return non-const access to an omega patch.
dimensionedScalar exp(const dimensionedScalar &ds)
static const word propertiesName
Default name of the turbulence properties dictionary.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
virtual const labelUList & faceCells() const
Return faceCells.
Definition: fvPatch.C:93
static word groupName(Name name, const word &group)
void setValues(const labelUList &cells, const UList< Type > &values)
Set solution in given cells to the specified values.
Definition: fvMatrix.C:484
Foam::fvPatchFieldMapper.
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:296
static scalar tolerance_
Tolerance used in weighted calculations.
virtual void calculateTurbulenceFields(const turbulenceModel &turbulence, scalarField &G0, scalarField &omega0)
Main driver to calculate the turbulence fields.
const nearWallDist & y() const
Return the near wall distances.
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:262
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:325
virtual label size() const
Return size.
Definition: fvPatch.H:155
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:53
virtual tmp< Field< Type > > patchInternalField() const
Return internal field next to patch as patch field.
Definition: fvPatchField.C:194
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.
scalarField & omega(bool init=false)
Return non-const access to the master&#39;s omega field.
void setSize(const label)
Reset size of List.
Definition: List.C:281
label patchi
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:47
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.
scalar yPlus
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
Definition: fvPatchField.C:229
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
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:167
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:98
virtual const word & name() const
Return name.
Definition: fvPatch.H:143
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:92
static const nutWallFunctionFvPatchScalarField & nutw(const turbulenceModel &turbModel, const label patchi)
Return the nut patchField for the given wall patch.
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:170
scalarField omega_
Local copy of turbulence omega field.
Namespace for OpenFOAM.
virtual void calculate(const turbulenceModel &turbulence, const List< scalar > &cornerWeights, const fvPatch &patch, scalarField &G, scalarField &omega)
Calculate the omega and G.
const DimensionedField< Type, volMesh > & internalField() const
Return dimensioned internal field reference.
Definition: fvPatchField.H:332