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-2020 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 // * * * * * * * * * * * * * * 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 momentumTransportModel& 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 momentumTransportModel& 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 (
294 )
295 :
296  fixedValueFvPatchField<scalar>(ewfpsf, iF),
297  G_(),
298  epsilon_(),
299  initialised_(false),
300  master_(-1),
302 {}
303 
304 
305 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
306 
308 {
309  if (patch().index() == master_)
310  {
311  if (init)
312  {
313  G_ = 0.0;
314  }
315 
316  return G_;
317  }
318 
319  return epsilonPatch(master_).G();
320 }
321 
322 
324 (
325  bool init
326 )
327 {
328  if (patch().index() == master_)
329  {
330  if (init)
331  {
332  epsilon_ = 0.0;
333  }
334 
335  return epsilon_;
336  }
337 
338  return epsilonPatch(master_).epsilon(init);
339 }
340 
341 
343 {
344  if (updated())
345  {
346  return;
347  }
348 
349  const momentumTransportModel& turbModel =
351  (
353  (
354  momentumTransportModel::typeName,
355  internalField().group()
356  )
357  );
358 
359  setMaster();
360 
361  if (patch().index() == master_)
362  {
364  calculateTurbulenceFields(turbModel, G(true), epsilon(true));
365  }
366 
367  const scalarField& G0 = this->G();
368  const scalarField& epsilon0 = this->epsilon();
369 
370  typedef DimensionedField<scalar, volMesh> FieldType;
371 
372  FieldType& G =
373  const_cast<FieldType&>
374  (
375  db().lookupObject<FieldType>(turbModel.GName())
376  );
377 
378  FieldType& epsilon = const_cast<FieldType&>(internalField());
379 
380  forAll(*this, facei)
381  {
382  label celli = patch().faceCells()[facei];
383 
384  G[celli] = G0[celli];
385  epsilon[celli] = epsilon0[celli];
386  }
387 
389 }
390 
391 
393 (
394  const scalarField& weights
395 )
396 {
397  if (updated())
398  {
399  return;
400  }
401 
402  const momentumTransportModel& turbModel =
404  (
406  (
407  momentumTransportModel::typeName,
408  internalField().group()
409  )
410  );
411 
412  setMaster();
413 
414  if (patch().index() == master_)
415  {
417  calculateTurbulenceFields(turbModel, G(true), epsilon(true));
418  }
419 
420  const scalarField& G0 = this->G();
421  const scalarField& epsilon0 = this->epsilon();
422 
423  typedef DimensionedField<scalar, volMesh> FieldType;
424 
425  FieldType& G =
426  const_cast<FieldType&>
427  (
428  db().lookupObject<FieldType>(turbModel.GName())
429  );
430 
431  FieldType& epsilon = const_cast<FieldType&>(internalField());
432 
433  scalarField& epsilonf = *this;
434 
435  // Only set the values if the weights are > tolerance
436  forAll(weights, facei)
437  {
438  scalar w = weights[facei];
439 
440  if (w > tolerance_)
441  {
442  label celli = patch().faceCells()[facei];
443 
444  G[celli] = (1.0 - w)*G[celli] + w*G0[celli];
445  epsilon[celli] = (1.0 - w)*epsilon[celli] + w*epsilon0[celli];
446  epsilonf[facei] = epsilon[celli];
447  }
448  }
449 
451 }
452 
453 
455 (
456  fvMatrix<scalar>& matrix
457 )
458 {
459  if (manipulatedMatrix())
460  {
461  return;
462  }
463 
464  matrix.setValues(patch().faceCells(), patchInternalField());
465 
467 }
468 
469 
471 (
472  fvMatrix<scalar>& matrix,
473  const Field<scalar>& weights
474 )
475 {
476  if (manipulatedMatrix())
477  {
478  return;
479  }
480 
481  DynamicList<label> constraintCells(weights.size());
482  DynamicList<scalar> constraintEpsilon(weights.size());
483  const labelUList& faceCells = patch().faceCells();
484 
486  = internalField();
487 
488  label nConstrainedCells = 0;
489 
490 
491  forAll(weights, facei)
492  {
493  // Only set the values if the weights are > tolerance
494  if (weights[facei] > tolerance_)
495  {
496  nConstrainedCells++;
497 
498  label celli = faceCells[facei];
499 
500  constraintCells.append(celli);
501  constraintEpsilon.append(epsilon[celli]);
502  }
503  }
504 
505  if (debug)
506  {
507  Pout<< "Patch: " << patch().name()
508  << ": number of constrained cells = " << nConstrainedCells
509  << " out of " << patch().size()
510  << endl;
511  }
512 
513  matrix.setValues
514  (
515  constraintCells,
516  scalarField(constraintEpsilon)
517  );
518 
520 }
521 
522 
523 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
524 
525 namespace Foam
526 {
528  (
531  );
532 }
533 
534 
535 // ************************************************************************* //
virtual tmp< volScalarField > nu() const =0
Return the laminar viscosity.
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:325
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:166
label index() const
Return the index of this patch in the fvBoundaryMesh.
Definition: fvPatch.H:174
virtual void calculate(const momentumTransportModel &turbulence, const List< scalar > &cornerWeights, const fvPatch &patch, scalarField &G, scalarField &epsilon)
Calculate the epsilon and G.
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:156
bool updated() const
Return true if the boundary condition has already been updated.
Definition: fvPatchField.H:355
const Boundary & boundaryField() const
Return const-reference to the boundary field.
virtual void calculateTurbulenceFields(const momentumTransportModel &turbulence, scalarField &G0, scalarField &epsilon0)
Main driver to calculate the turbulence fields.
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:164
dimensionedScalar sqrt(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:62
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
const nearWallDist & y() const
Return the near wall distances.
static word timeName(const scalar, const int precision=precision_)
Return time name of given scalar time.
Definition: Time.C:636
const dimensionSet dimless
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:361
const Type & lookupObject(const word &name) const
Lookup and return the object of the given Type.
Macros for easy insertion into run-time selection tables.
virtual void operator==(const fvPatchField< Type > &)
Definition: fvPatchField.C:441
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...
dynamicFvMesh & mesh
virtual label & master()
Return non-const access to the master patch ID.
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)
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.
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:242
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:337
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:156
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:174
const Mesh & mesh() const
Return mesh.
virtual tmp< volScalarField > k() const =0
Return the turbulence kinetic energy.
Abstract base class for turbulence models (RAS, LES and laminar).
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
void setSize(const label)
Reset size of List.
Definition: List.C:281
const volVectorField & U() const
Access function to velocity field.
label patchi
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.
const dimensionedScalar G0
Conductance quantum: default SI units: [S].
scalar yPlus
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
Definition: fvPatchField.C:209
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:147
dimensioned< scalar > mag(const dimensioned< Type > &)
const dimensionedScalar epsilon0
Electric constant: default SI units: [F/m].
word GName() const
Helper function to return the name of the turbulence G field.
virtual const word & name() const
Return name.
Definition: fvPatch.H:144
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
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:171
const dimensionedScalar e
Elementary charge.
Definition: doubleScalar.H:105
Namespace for OpenFOAM.
const DimensionedField< Type, volMesh > & internalField() const
Return dimensioned internal field reference.
Definition: fvPatchField.H:343
scalarField & epsilon(bool init=false)
Return non-const access to the master&#39;s epsilon field.