epsilonWallFunctionFvPatchScalarField.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 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
33 
35 
36 // * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
37 
39 {
40  if (master_ != -1)
41  {
42  return;
43  }
44 
45  const volScalarField& epsilon =
46  static_cast<const volScalarField&>(this->internalField());
47 
48  const volScalarField::Boundary& bf = epsilon.boundaryField();
49 
50  label master = -1;
51  forAll(bf, patchi)
52  {
53  if (isA<epsilonWallFunctionFvPatchScalarField>(bf[patchi]))
54  {
56 
57  if (master == -1)
58  {
59  master = patchi;
60  }
61 
62  epf.master() = master;
63  }
64  }
65 }
66 
67 
69 {
70  const volScalarField& epsilon =
71  static_cast<const volScalarField&>(this->internalField());
72 
73  const volScalarField::Boundary& bf = epsilon.boundaryField();
74 
75  const fvMesh& mesh = epsilon.mesh();
76 
77  if (initialised_ && !mesh.changing())
78  {
79  return;
80  }
81 
82  volScalarField weights
83  (
84  IOobject
85  (
86  "weights",
87  mesh.time().timeName(),
88  mesh,
91  false // do not register
92  ),
93  mesh,
95  );
96 
97  DynamicList<label> epsilonPatches(bf.size());
98  forAll(bf, patchi)
99  {
100  if (isA<epsilonWallFunctionFvPatchScalarField>(bf[patchi]))
101  {
102  epsilonPatches.append(patchi);
103 
104  const labelUList& faceCells = bf[patchi].patch().faceCells();
105  forAll(faceCells, i)
106  {
107  weights[faceCells[i]]++;
108  }
109  }
110  }
111 
112  cornerWeights_.setSize(bf.size());
113  forAll(epsilonPatches, i)
114  {
115  label patchi = epsilonPatches[i];
116  const fvPatchScalarField& wf = weights.boundaryField()[patchi];
118  }
119 
120  G_.setSize(internalField().size(), 0.0);
122 
123  initialised_ = true;
124 }
125 
126 
129 {
130  const volScalarField& epsilon =
131  static_cast<const volScalarField&>(this->internalField());
132 
133  const volScalarField::Boundary& bf = epsilon.boundaryField();
134 
136  refCast<const epsilonWallFunctionFvPatchScalarField>(bf[patchi]);
137 
138  return const_cast<epsilonWallFunctionFvPatchScalarField&>(epf);
139 }
140 
141 
143 (
144  const turbulenceModel& turbulence,
145  scalarField& G0,
146  scalarField& epsilon0
147 )
148 {
149  // Accumulate all of the G and epsilon contributions
151  {
152  if (!cornerWeights_[patchi].empty())
153  {
155 
156  const List<scalar>& w = cornerWeights_[patchi];
157 
158  epf.calculate(turbulence, w, epf.patch(), G0, epsilon0);
159  }
160  }
161 
162  // Apply zero-gradient condition for epsilon
164  {
165  if (!cornerWeights_[patchi].empty())
166  {
168 
169  epf == scalarField(epsilon0, epf.patch().faceCells());
170  }
171  }
172 }
173 
174 
176 (
177  const turbulenceModel& turbModel,
178  const List<scalar>& cornerWeights,
179  const fvPatch& patch,
180  scalarField& G0,
181  scalarField& epsilon0
182 )
183 {
184  const label patchi = patch.index();
185 
187  nutWallFunctionFvPatchScalarField::nutw(turbModel, patchi);
188 
189  const scalarField& y = turbModel.y()[patchi];
190 
191  const tmp<scalarField> tnuw = turbModel.nu(patchi);
192  const scalarField& nuw = tnuw();
193 
194  const tmp<volScalarField> tk = turbModel.k();
195  const volScalarField& k = tk();
196 
197  const fvPatchVectorField& Uw = turbModel.U().boundaryField()[patchi];
198 
199  const scalarField magGradUw(mag(Uw.snGrad()));
200 
201  const scalar Cmu25 = pow025(nutw.Cmu());
202  const scalar Cmu75 = pow(nutw.Cmu(), 0.75);
203 
204  // Set epsilon and G
205  forAll(nutw, facei)
206  {
207  const label celli = patch.faceCells()[facei];
208 
209  const scalar yPlus = Cmu25*y[facei]*sqrt(k[celli])/nuw[facei];
210 
211  const scalar w = cornerWeights[facei];
212 
213  if (yPlus > nutw.yPlusLam())
214  {
215  epsilon0[celli] +=
216  w*Cmu75*pow(k[celli], 1.5)/(nutw.kappa()*y[facei]);
217 
218  G0[celli] +=
219  w
220  *(nutw[facei] + nuw[facei])
221  *magGradUw[facei]
222  *Cmu25*sqrt(k[celli])
223  /(nutw.kappa()*y[facei]);
224  }
225  else
226  {
227  epsilon0[celli] += w*2.0*k[celli]*nuw[facei]/sqr(y[facei]);
228  }
229  }
230 }
231 
232 
233 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
234 
237 (
238  const fvPatch& p,
240 )
241 :
243  G_(),
244  epsilon_(),
245  initialised_(false),
246  master_(-1),
248 {}
249 
250 
253 (
254  const fvPatch& p,
256  const dictionary& dict
257 )
258 :
260  G_(),
261  epsilon_(),
262  initialised_(false),
263  master_(-1),
265 {
266  // Apply zero-gradient condition on start-up
268 }
269 
270 
273 (
275  const fvPatch& p,
277  const fvPatchFieldMapper& mapper
278 )
279 :
280  fixedValueFvPatchField<scalar>(ptf, p, iF, mapper),
281  G_(),
282  epsilon_(),
283  initialised_(false),
284  master_(-1),
286 {}
287 
288 
291 (
293 )
294 :
296  G_(),
297  epsilon_(),
298  initialised_(false),
299  master_(-1),
301 {}
302 
303 
306 (
309 )
310 :
311  fixedValueFvPatchField<scalar>(ewfpsf, iF),
312  G_(),
313  epsilon_(),
314  initialised_(false),
315  master_(-1),
317 {}
318 
319 
320 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
321 
323 {
324  if (patch().index() == master_)
325  {
326  if (init)
327  {
328  G_ = 0.0;
329  }
330 
331  return G_;
332  }
333 
334  return epsilonPatch(master_).G();
335 }
336 
337 
339 (
340  bool init
341 )
342 {
343  if (patch().index() == master_)
344  {
345  if (init)
346  {
347  epsilon_ = 0.0;
348  }
349 
350  return epsilon_;
351  }
352 
353  return epsilonPatch(master_).epsilon(init);
354 }
355 
356 
358 {
359  if (updated())
360  {
361  return;
362  }
363 
364  const turbulenceModel& turbModel = db().lookupObject<turbulenceModel>
365  (
367  (
369  internalField().group()
370  )
371  );
372 
373  setMaster();
374 
375  if (patch().index() == master_)
376  {
378  calculateTurbulenceFields(turbModel, G(true), epsilon(true));
379  }
380 
381  const scalarField& G0 = this->G();
382  const scalarField& epsilon0 = this->epsilon();
383 
384  typedef DimensionedField<scalar, volMesh> FieldType;
385 
386  FieldType& G =
387  const_cast<FieldType&>
388  (
389  db().lookupObject<FieldType>(turbModel.GName())
390  );
391 
392  FieldType& epsilon = const_cast<FieldType&>(internalField());
393 
394  forAll(*this, facei)
395  {
396  label celli = patch().faceCells()[facei];
397 
398  G[celli] = G0[celli];
399  epsilon[celli] = epsilon0[celli];
400  }
401 
403 }
404 
405 
407 (
408  const scalarField& weights
409 )
410 {
411  if (updated())
412  {
413  return;
414  }
415 
416  const turbulenceModel& turbModel = db().lookupObject<turbulenceModel>
417  (
419  (
421  internalField().group()
422  )
423  );
424 
425  setMaster();
426 
427  if (patch().index() == master_)
428  {
430  calculateTurbulenceFields(turbModel, G(true), epsilon(true));
431  }
432 
433  const scalarField& G0 = this->G();
434  const scalarField& epsilon0 = this->epsilon();
435 
436  typedef DimensionedField<scalar, volMesh> FieldType;
437 
438  FieldType& G =
439  const_cast<FieldType&>
440  (
441  db().lookupObject<FieldType>(turbModel.GName())
442  );
443 
444  FieldType& epsilon = const_cast<FieldType&>(internalField());
445 
446  scalarField& epsilonf = *this;
447 
448  // Only set the values if the weights are > tolerance
449  forAll(weights, facei)
450  {
451  scalar w = weights[facei];
452 
453  if (w > tolerance_)
454  {
455  label celli = patch().faceCells()[facei];
456 
457  G[celli] = (1.0 - w)*G[celli] + w*G0[celli];
458  epsilon[celli] = (1.0 - w)*epsilon[celli] + w*epsilon0[celli];
459  epsilonf[facei] = epsilon[celli];
460  }
461  }
462 
464 }
465 
466 
468 (
469  fvMatrix<scalar>& matrix
470 )
471 {
472  if (manipulatedMatrix())
473  {
474  return;
475  }
476 
477  matrix.setValues(patch().faceCells(), patchInternalField());
478 
480 }
481 
482 
484 (
485  fvMatrix<scalar>& matrix,
486  const Field<scalar>& weights
487 )
488 {
489  if (manipulatedMatrix())
490  {
491  return;
492  }
493 
494  DynamicList<label> constraintCells(weights.size());
495  DynamicList<scalar> constraintEpsilon(weights.size());
496  const labelUList& faceCells = patch().faceCells();
497 
499  = internalField();
500 
501  label nConstrainedCells = 0;
502 
503 
504  forAll(weights, facei)
505  {
506  // Only set the values if the weights are > tolerance
507  if (weights[facei] > tolerance_)
508  {
509  nConstrainedCells++;
510 
511  label celli = faceCells[facei];
512 
513  constraintCells.append(celli);
514  constraintEpsilon.append(epsilon[celli]);
515  }
516  }
517 
518  if (debug)
519  {
520  Pout<< "Patch: " << patch().name()
521  << ": number of constrained cells = " << nConstrainedCells
522  << " out of " << patch().size()
523  << endl;
524  }
525 
526  matrix.setValues
527  (
528  constraintCells,
529  scalarField(constraintEpsilon)
530  );
531 
533 }
534 
535 
536 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
537 
538 namespace Foam
539 {
541  (
544  );
545 }
546 
547 
548 // ************************************************************************* //
const char *const group
Group name for atomic constants.
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
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 tmp< Field< Type > > snGrad() const
Return patch-normal gradient.
Definition: fvPatchField.C:186
const dimensionedScalar G0
Conductance quantum: default SI units: [S].
virtual void calculate(const turbulenceModel &turbulence, const List< scalar > &cornerWeights, const fvPatch &patch, scalarField &G, scalarField &epsilon)
Calculate the epsilon and G.
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
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.
scalarField G_
Local copy of turbulence G 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.
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)
virtual void manipulateMatrix(fvMatrix< scalar > &matrix)
Manipulate matrix.
static scalar tolerance_
Tolerance used in weighted calculations.
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Definition: fvPatchField.H:66
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.
const dimensionedScalar epsilon0
Electric constant: default SI units: [F/m].
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
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
volScalarField & e
Elementary charge.
Definition: createFields.H:11
virtual label & master()
Return non-const access to the master patch ID.
static const word propertiesName
Default name of the turbulence properties dictionary.
virtual void calculateTurbulenceFields(const turbulenceModel &turbulence, scalarField &G0, scalarField &epsilon0)
Main driver to calculate the turbulence fields.
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
scalarField epsilon_
Local copy of turbulence epsilon field.
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
This boundary condition provides a turbulence dissipation wall constraint for low- and high-Reynolds ...
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
scalarField & G(bool init=false)
Return non-const access to the master&#39;s G field.
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
virtual label size() const
Return size.
Definition: fvPatch.H:155
virtual epsilonWallFunctionFvPatchScalarField & epsilonPatch(const label patchi)
Helper function to return non-const access to an epsilon patch.
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.
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
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
List< List< scalar > > cornerWeights_
List of averaging corner weights.
virtual void updateWeightedCoeffs(const scalarField &weights)
Update the coefficients associated with the patch field.
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 const word & name() const
Return name.
Definition: fvPatch.H:143
virtual void setMaster()
Set the master patch - master is responsible for updating all.
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 void createAveragingWeights()
Create the averaging weights for cells which are bounded by.
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.
epsilonWallFunctionFvPatchScalarField(const fvPatch &, const DimensionedField< scalar, volMesh > &)
Construct from patch and internal field.
makePatchTypeField(fvPatchScalarField, atmBoundaryLayerInletEpsilonFvPatchScalarField)
label size() const
Return the number of elements in the UList.
Definition: ListI.H:170
Namespace for OpenFOAM.
const DimensionedField< Type, volMesh > & internalField() const
Return dimensioned internal field reference.
Definition: fvPatchField.H:332
scalarField & epsilon(bool init=false)
Return non-const access to the master&#39;s epsilon field.