kOmegaSSTLM.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) 2016-2024 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 
26 #include "kOmegaSSTLM.H"
27 
28 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
29 
30 namespace Foam
31 {
32 namespace RASModels
33 {
34 
35 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
36 
37 template<class BasicMomentumTransportModel>
39 (
40  const volScalarField& CDkOmega
41 ) const
42 {
43  const volScalarField Ry(this->y()*sqrt(this->k_)/this->nu());
44  const volScalarField F3(exp(-pow(Ry/120.0, 8)));
45 
47 }
48 
49 
50 template<class BasicMomentumTransportModel>
52 (
54 ) const
55 {
56  return gammaIntEff_*kOmegaSST<BasicMomentumTransportModel>::Pk(G);
57 }
58 
59 
60 template<class BasicMomentumTransportModel>
63 (
66 ) const
67 {
68  return
69  min(max(gammaIntEff_, scalar(0.1)), scalar(1))
71 }
72 
73 
74 template<class BasicMomentumTransportModel>
76 (
77  const volScalarField::Internal& Us,
78  const volScalarField::Internal& Omega,
79  const volScalarField::Internal& nu
80 ) const
81 {
82  const volScalarField::Internal& omega = this->omega_();
83  const volScalarField::Internal& y = this->y()();
84 
85  const volScalarField::Internal delta(375*Omega*nu*ReThetat_()*y/sqr(Us));
86  const volScalarField::Internal ReOmega(sqr(y)*omega/nu);
87  const volScalarField::Internal Fwake(exp(-sqr(ReOmega/1e5)));
88 
90  (
91  this->groupName("Fthetat"),
92  min
93  (
94  max
95  (
96  Fwake*exp(-pow4((y/delta))),
97  (1 - sqr((gammaInt_() - 1.0/ce2_)/(1 - 1.0/ce2_)))
98  ),
99  scalar(1)
100  )
101  );
102 }
103 
104 
105 template<class BasicMomentumTransportModel>
108 {
110  (
112  (
113  this->groupName("ReThetac"),
114  this->mesh_,
115  dimless
116  )
117  );
118  volScalarField::Internal& ReThetac = tReThetac.ref();
119 
120  forAll(ReThetac, celli)
121  {
122  const scalar ReThetat = ReThetat_[celli];
123 
124  ReThetac[celli] =
125  ReThetat <= 1870
126  ?
127  ReThetat
128  - 396.035e-2
129  + 120.656e-4*ReThetat
130  - 868.230e-6*sqr(ReThetat)
131  + 696.506e-9*pow3(ReThetat)
132  - 174.105e-12*pow4(ReThetat)
133  :
134  ReThetat - 593.11 - 0.482*(ReThetat - 1870);
135  }
136 
137  return tReThetac;
138 }
139 
140 
141 template<class BasicMomentumTransportModel>
143 (
144  const volScalarField::Internal& nu
145 ) const
146 {
148  (
150  (
151  this->groupName("Flength"),
152  this->mesh_,
153  dimless
154  )
155  );
156  volScalarField::Internal& Flength = tFlength.ref();
157 
158  const volScalarField::Internal& omega = this->omega_();
159  const volScalarField::Internal& y = this->y()();
160 
161  forAll(ReThetat_, celli)
162  {
163  const scalar ReThetat = ReThetat_[celli];
164 
165  if (ReThetat < 400)
166  {
167  Flength[celli] =
168  398.189e-1
169  - 119.270e-4*ReThetat
170  - 132.567e-6*sqr(ReThetat);
171  }
172  else if (ReThetat < 596)
173  {
174  Flength[celli] =
175  263.404
176  - 123.939e-2*ReThetat
177  + 194.548e-5*sqr(ReThetat)
178  - 101.695e-8*pow3(ReThetat);
179  }
180  else if (ReThetat < 1200)
181  {
182  Flength[celli] = 0.5 - 3e-4*(ReThetat - 596);
183  }
184  else
185  {
186  Flength[celli] = 0.3188;
187  }
188 
189  const scalar Fsublayer =
190  exp(-sqr(sqr(y[celli])*omega[celli]/(200*nu[celli])));
191 
192  Flength[celli] = Flength[celli]*(1 - Fsublayer) + 40*Fsublayer;
193  }
194 
195  return tFlength;
196 }
197 
198 
199 template<class BasicMomentumTransportModel>
202 (
203  const volScalarField::Internal& Us,
204  const volScalarField::Internal& dUsds,
205  const volScalarField::Internal& nu
206 ) const
207 {
209  (
211  (
212  this->groupName("ReThetat0"),
213  this->mesh_,
214  dimless
215  )
216  );
217  volScalarField::Internal& ReThetat0 = tReThetat0.ref();
218 
219  const volScalarField& k = this->k_;
220 
221  label maxIter = 0;
222 
223  forAll(ReThetat0, celli)
224  {
225  const scalar Tu
226  (
227  max(100*sqrt((2.0/3.0)*k[celli])/Us[celli], scalar(0.027))
228  );
229 
230  // Initialise lambda to zero.
231  // If lambda were cached between time-steps convergence would be faster
232  // starting from the previous time-step value.
233  scalar lambda = 0;
234 
235  scalar lambdaErr;
236  scalar thetat;
237  label iter = 0;
238 
239  do
240  {
241  // Previous iteration lambda for convergence test
242  const scalar lambda0 = lambda;
243 
244  if (Tu <= 1.3)
245  {
246  const scalar Flambda =
247  dUsds[celli] <= 0
248  ?
249  1
250  - (
251  - 12.986*lambda
252  - 123.66*sqr(lambda)
253  - 405.689*pow3(lambda)
254  )*exp(-pow(Tu/1.5, 1.5))
255  :
256  1
257  + 0.275*(1 - exp(-35*lambda))
258  *exp(-Tu/0.5);
259 
260  thetat =
261  (1173.51 - 589.428*Tu + 0.2196/sqr(Tu))
262  *Flambda*nu[celli]
263  /Us[celli];
264  }
265  else
266  {
267  const scalar Flambda =
268  dUsds[celli] <= 0
269  ?
270  1
271  - (
272  -12.986*lambda
273  -123.66*sqr(lambda)
274  -405.689*pow3(lambda)
275  )*exp(-pow(Tu/1.5, 1.5))
276  :
277  1
278  + 0.275*(1 - exp(-35*lambda))
279  *exp(-2*Tu);
280 
281  thetat =
282  331.50*pow((Tu - 0.5658), -0.671)
283  *Flambda*nu[celli]/Us[celli];
284  }
285 
286  lambda = sqr(thetat)/nu[celli]*dUsds[celli];
287  lambda = max(min(lambda, 0.1), -0.1);
288 
289  lambdaErr = mag(lambda - lambda0);
290 
291  maxIter = max(maxIter, ++iter);
292 
293  } while (lambdaErr > lambdaErr_);
294 
295  ReThetat0[celli] = max(thetat*Us[celli]/nu[celli], scalar(20));
296  }
297 
298  if (maxIter > maxLambdaIter_)
299  {
301  << "Number of lambda iterations exceeds maxLambdaIter("
302  << maxLambdaIter_ << ')'<< endl;
303  }
304 
305  return tReThetat0;
306 }
307 
308 
309 template<class BasicMomentumTransportModel>
311 (
312  const volScalarField::Internal& Rev,
313  const volScalarField::Internal& ReThetac,
314  const volScalarField::Internal& RT
315 ) const
316 {
317  const volScalarField::Internal Fonset1(Rev/(2.193*ReThetac));
318 
319  const volScalarField::Internal Fonset2
320  (
321  min(max(Fonset1, pow4(Fonset1)), scalar(2))
322  );
323 
324  const volScalarField::Internal Fonset3(max(1 - pow3(RT/2.5), scalar(0)));
325 
327  (
328  this->groupName("Fonset"),
329  max(Fonset2 - Fonset3, scalar(0))
330  );
331 }
332 
333 
334 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
335 
336 template<class BasicMomentumTransportModel>
338 (
339  const alphaField& alpha,
340  const rhoField& rho,
341  const volVectorField& U,
342  const surfaceScalarField& alphaRhoPhi,
343  const surfaceScalarField& phi,
344  const viscosity& viscosity,
345  const word& type
346 )
347 :
348  kOmegaSST<BasicMomentumTransportModel>
349  (
350  alpha,
351  rho,
352  U,
353  alphaRhoPhi,
354  phi,
355  viscosity
356  ),
357 
358  ca1_("ca1", this->coeffDict(), 2),
359  ca2_("ca2", this->coeffDict(), 0.06),
360  ce1_("ce1", this->coeffDict(), 1),
361  ce2_("ce2", this->coeffDict(), 50),
362  cThetat_("cThetat", this->coeffDict(), 0.03),
363  sigmaThetat_("sigmaThetat", this->coeffDict(), 2),
364  lambdaErr_(this->coeffDict().lookupOrDefault("lambdaErr", 1e-6)),
365  maxLambdaIter_(this->coeffDict().lookupOrDefault("maxLambdaIter", 10)),
366  deltaU_("deltaU", dimVelocity, small),
367 
368  ReThetat_
369  (
370  IOobject
371  (
372  this->groupName("ReThetat"),
373  this->runTime_.name(),
374  this->mesh_,
375  IOobject::MUST_READ,
376  IOobject::AUTO_WRITE
377  ),
378  this->mesh_
379  ),
380 
381  gammaInt_
382  (
383  IOobject
384  (
385  this->groupName("gammaInt"),
386  this->runTime_.name(),
387  this->mesh_,
388  IOobject::MUST_READ,
389  IOobject::AUTO_WRITE
390  ),
391  this->mesh_
392  ),
393 
394  gammaIntEff_
395  (
396  IOobject
397  (
398  this->groupName("gammaIntEff"),
399  this->runTime_.name(),
400  this->mesh_
401  ),
402  this->mesh_,
404  )
405 {}
406 
407 
408 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
409 
410 template<class BasicMomentumTransportModel>
412 {
414  {
415  ca1_.readIfPresent(this->coeffDict());
416  ca2_.readIfPresent(this->coeffDict());
417  ce1_.readIfPresent(this->coeffDict());
418  ce2_.readIfPresent(this->coeffDict());
419  sigmaThetat_.readIfPresent(this->coeffDict());
420  cThetat_.readIfPresent(this->coeffDict());
421  this->coeffDict().readIfPresent("lambdaErr", lambdaErr_);
422  this->coeffDict().readIfPresent("maxLambdaIter", maxLambdaIter_);
423 
424  return true;
425  }
426  else
427  {
428  return false;
429  }
430 }
431 
432 
433 template<class BasicMomentumTransportModel>
435 {
436  // Local references
437  const alphaField& alpha = this->alpha_;
438  const rhoField& rho = this->rho_;
439  const surfaceScalarField& alphaRhoPhi = this->alphaRhoPhi_;
440  const volVectorField& U = this->U_;
441  const volScalarField& k = this->k_;
442  const volScalarField& omega = this->omega_;
443  const tmp<volScalarField> tnu = this->nu();
444  const volScalarField::Internal& nu = tnu()();
445  const volScalarField::Internal& y = this->y()();
446  const Foam::fvModels& fvModels(Foam::fvModels::New(this->mesh_));
448  (
449  Foam::fvConstraints::New(this->mesh_)
450  );
451 
452  // Fields derived from the velocity gradient
453  tmp<volTensorField> tgradU = fvc::grad(U);
454  const volScalarField::Internal Omega(sqrt(2*magSqr(skew(tgradU()()))));
455  const volScalarField::Internal S(sqrt(2*magSqr(symm(tgradU()()))));
456  const volScalarField::Internal Us(max(mag(U()), deltaU_));
457  const volScalarField::Internal dUsds((U() & (U() & tgradU()()))/sqr(Us));
458  tgradU.clear();
459 
460  const volScalarField::Internal Fthetat(this->Fthetat(Us, Omega, nu));
461 
462  {
463  const volScalarField::Internal t(500*nu/sqr(Us));
464  const volScalarField::Internal Pthetat
465  (
466  alpha()*rho()*(cThetat_/t)*(1 - Fthetat)
467  );
468 
469  // Transition onset momentum-thickness Reynolds number equation
470  tmp<fvScalarMatrix> ReThetatEqn
471  (
472  fvm::ddt(alpha, rho, ReThetat_)
473  + fvm::div(alphaRhoPhi, ReThetat_)
474  - fvm::laplacian(alpha*rho*DReThetatEff(), ReThetat_)
475  ==
476  Pthetat*ReThetat0(Us, dUsds, nu) - fvm::Sp(Pthetat, ReThetat_)
477  + fvModels.source(alpha, rho, ReThetat_)
478  );
479 
480  ReThetatEqn.ref().relax();
481  fvConstraints.constrain(ReThetatEqn.ref());
482  solve(ReThetatEqn);
483  fvConstraints.constrain(ReThetat_);
484  bound(ReThetat_, 0);
485  }
486 
487  const volScalarField::Internal ReThetac(this->ReThetac());
488  const volScalarField::Internal Rev(sqr(y)*S/nu);
489  const volScalarField::Internal RT(k()/(nu*omega()));
490 
491  {
492  const volScalarField::Internal Pgamma
493  (
494  alpha()*rho()
495  *ca1_*Flength(nu)*S*sqrt(gammaInt_()*Fonset(Rev, ReThetac, RT))
496  );
497 
498  const volScalarField::Internal Fturb(exp(-pow4(0.25*RT)));
499 
500  const volScalarField::Internal Egamma
501  (
502  alpha()*rho()*ca2_*Omega*Fturb*gammaInt_()
503  );
504 
505  // Intermittency equation
506  tmp<fvScalarMatrix> gammaIntEqn
507  (
508  fvm::ddt(alpha, rho, gammaInt_)
509  + fvm::div(alphaRhoPhi, gammaInt_)
510  - fvm::laplacian(alpha*rho*DgammaIntEff(), gammaInt_)
511  ==
512  Pgamma - fvm::Sp(ce1_*Pgamma, gammaInt_)
513  + Egamma - fvm::Sp(ce2_*Egamma, gammaInt_)
514  + fvModels.source(alpha, rho, gammaInt_)
515  );
516 
517  gammaIntEqn.ref().relax();
518  fvConstraints.constrain(gammaIntEqn.ref());
519  solve(gammaIntEqn);
520  fvConstraints.constrain(gammaInt_);
521  bound(gammaInt_, 0);
522  }
523 
524  const volScalarField::Internal Freattach(exp(-pow4(RT/20.0)));
525  const volScalarField::Internal gammaSep
526  (
527  min(2*max(Rev/(3.235*ReThetac) - 1, scalar(0))*Freattach, scalar(2))
528  *Fthetat
529  );
530 
531  gammaIntEff_ = max(gammaInt_(), gammaSep);
532 }
533 
534 
535 template<class BasicMomentumTransportModel>
537 {
538  if (!this->turbulence_)
539  {
540  return;
541  }
542 
543  // Correct ReThetat and gammaInt
544  correctReThetatGammaInt();
545 
546  // Correct k and omega
548 }
549 
550 
551 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
552 
553 } // End namespace RASModels
554 } // End namespace Foam
555 
556 // ************************************************************************* //
scalar y
label k
scalar delta
#define F2(B, C, D)
Definition: SHA1.C:174
#define F1(B, C, D)
Definition: SHA1.C:173
#define F3(B, C, D)
Definition: SHA1.C:175
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:433
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
static tmp< DimensionedField< Type, GeoMesh, PrimitiveField > > New(const word &name, const Mesh &mesh, const dimensionSet &, const PrimitiveField< Type > &)
Return a temporary field constructed from name, mesh,.
Generic GeometricField class.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
tmp< volScalarField::Internal > Flength(const volScalarField::Internal &nu) const
Empirical correlation that controls the length of the.
Definition: kOmegaSSTLM.C:143
virtual tmp< volScalarField > F1(const volScalarField &CDkOmega) const
Modified form of the k-omega SST F1 function.
Definition: kOmegaSSTLM.C:39
virtual void correct()
Solve the turbulence equations and correct the turbulence viscosity.
Definition: kOmegaSSTLM.C:536
virtual tmp< volScalarField::Internal > epsilonByk(const volScalarField::Internal &F1, const volScalarField::Internal &F2) const
Modified form of the k-omega SST epsilon/k.
Definition: kOmegaSSTLM.C:63
tmp< volScalarField::Internal > Fthetat(const volScalarField::Internal &Us, const volScalarField::Internal &Omega, const volScalarField::Internal &nu) const
Freestream blending-function.
Definition: kOmegaSSTLM.C:76
kOmegaSSTLM(const alphaField &alpha, const rhoField &rho, const volVectorField &U, const surfaceScalarField &alphaRhoPhi, const surfaceScalarField &phi, const viscosity &viscosity, const word &type=typeName)
Construct from components.
Definition: kOmegaSSTLM.C:338
void correctReThetatGammaInt()
Solve the turbulence equations and correct the turbulence viscosity.
Definition: kOmegaSSTLM.C:434
tmp< volScalarField::Internal > ReThetac() const
Empirical correlation for critical Reynolds number where the.
Definition: kOmegaSSTLM.C:107
virtual tmp< volScalarField::Internal > Pk(const volScalarField::Internal &G) const
Modified form of the k-omega SST k production rate.
Definition: kOmegaSSTLM.C:52
tmp< volScalarField::Internal > Fonset(const volScalarField::Internal &Rev, const volScalarField::Internal &ReThetac, const volScalarField::Internal &RT) const
Transition onset location control function.
Definition: kOmegaSSTLM.C:311
tmp< volScalarField::Internal > ReThetat0(const volScalarField::Internal &Us, const volScalarField::Internal &dUsds, const volScalarField::Internal &nu) const
Return the transition onset momentum-thickness Reynolds number.
Definition: kOmegaSSTLM.C:202
virtual bool read()
Re-read model coefficients if they have changed.
Definition: kOmegaSSTLM.C:411
Specialisation for RAS of the generic kOmegaSSTBase base class. For more information,...
Definition: kOmegaSST.H:64
static autoPtr< dictionary > New(Istream &)
Construct top-level dictionary on freestore from Istream.
Definition: dictionaryIO.C:103
Finite volume constraints.
Definition: fvConstraints.H:67
bool constrain(fvMatrix< Type > &eqn) const
Apply constraints to an equation.
Finite volume models.
Definition: fvModels.H:65
tmp< fvMatrix< Type > > source(const VolField< Type > &field) const
Return source for an equation.
virtual void correct()
Solve the turbulence equations and correct the turbulence viscosity.
virtual tmp< volScalarField::Internal > epsilonByk(const volScalarField::Internal &F1, const volScalarField::Internal &F2) const
Return epsilon/k which for standard RAS is betaStar*omega.
virtual tmp< volScalarField::Internal > Pk(const volScalarField::Internal &G) const
Return k production rate.
BasicMomentumTransportModel::alphaField alphaField
BasicMomentumTransportModel::rhoField rhoField
Convenience class to handle the input of constant rotational speed. Reads an omega entry with default...
Definition: omega.H:54
A class for managing temporary objects.
Definition: tmp.H:55
void clear() const
If object pointer points to valid object:
Definition: tmpI.H:253
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:197
Abstract base class for all fluid physical properties.
Definition: viscosity.H:50
A class for handling words, derived from string.
Definition: word.H:62
Foam::fvConstraints & fvConstraints(Foam::fvConstraints::New(mesh))
Foam::fvModels & fvModels(Foam::fvModels::New(mesh))
const scalar omega
U
Definition: pEqn.H:72
dimensionedScalar lambda(viscosity->lookup("lambda"))
volScalarField alpha(IOobject("alpha", runTime.name(), mesh, IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE), lambda *max(Ua &U, zeroSensitivity))
#define WarningInFunction
Report a warning using Foam::Warning.
const dimensionedScalar G
Newtonian constant of gravitation.
tmp< VolField< typename outerProduct< vector, Type >::type > > grad(const SurfaceField< Type > &ssf)
Definition: fvcGrad.C:46
tmp< fvMatrix< Type > > S(const Pair< tmp< volScalarField::Internal >> &, const VolField< Type > &)
tmp< fvMatrix< Type > > laplacian(const VolField< Type > &vf, const word &name)
Definition: fvmLaplacian.C:47
tmp< fvMatrix< Type > > div(const surfaceScalarField &flux, const VolField< Type > &vf, const word &name)
Definition: fvmDiv.C:48
tmp< fvMatrix< Type > > Sp(const volScalarField::Internal &, const VolField< Type > &)
tmp< fvMatrix< Type > > ddt(const VolField< Type > &vf)
Definition: fvmDdt.C:46
Namespace for OpenFOAM.
void skew(LagrangianPatchField< tensor > &f, const LagrangianPatchField< tensor > &f1)
const doubleScalar e
Definition: doubleScalar.H:106
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
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:258
const dimensionSet dimless
void pow4(LagrangianPatchField< scalar > &f, const LagrangianPatchField< scalar > &f1)
void mag(LagrangianPatchField< scalar > &f, const LagrangianPatchField< Type > &f1)
tensor Ry(const scalar &omega)
Rotational transformation tensor about the y-axis by omega radians.
Definition: transform.H:106
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
void symm(LagrangianPatchField< tensor > &f, const LagrangianPatchField< tensor > &f1)
void pow(LagrangianPatchField< typename powProduct< Type, r >::type > &f, const LagrangianPatchField< Type > &f1)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
bool bound(volScalarField &, const dimensionedScalar &min)
Bound the given scalar field where it is below the specified min value.
Definition: bound.C:31
void pow3(LagrangianPatchField< scalar > &f, const LagrangianPatchField< scalar > &f1)
void sqr(LagrangianPatchField< typename outerProduct< Type, Type >::type > &f, const LagrangianPatchField< Type > &f1)
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
const dimensionSet dimVelocity
void magSqr(LagrangianPatchField< scalar > &f, const LagrangianPatchField< Type > &f1)
void sqrt(LagrangianPatchField< scalar > &f, const LagrangianPatchField< scalar > &f1)
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488
SolverPerformance< Type > solve(fvMatrix< Type > &, const word &)
Solve returning the solution statistics given convergence tolerance.