Loading...
Searching...
No Matches
EBRSM.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2022-2023 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26\*---------------------------------------------------------------------------*/
27
28#include "EBRSM.H"
29#include "fvOptions.H"
30#include "bound.H"
31
32// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
33
34namespace Foam
35{
36namespace RASModels
37{
38
39// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
40
41template<class BasicTurbulenceModel>
42tmp<volScalarField> EBRSM<BasicTurbulenceModel>::calcL() const
43{
44 // (M:Eq. C.13)
45 return
46 Cl_*max
47 (
48 pow(k_, 1.5)/epsilon_,
49 Ceta_*pow025
50 (
51 pow3
52 (
53 max
54 (
55 this->nu(),
56 dimensionedScalar(this->nu()().dimensions(), Zero)
57 )
58 )/epsilon_
59 )
60 );
61}
62
63
64template<class BasicTurbulenceModel>
65tmp<volVectorField> EBRSM<BasicTurbulenceModel>::calcN() const
66{
67 const volVectorField gradf(fvc::grad(f_));
68
69 // (M:Eq. C.9)
70 return gradf/max(mag(gradf), dimensionedScalar(dimless/dimLength, SMALL));
71}
72
73
74template<class BasicTurbulenceModel>
75tmp<volScalarField> EBRSM<BasicTurbulenceModel>::calcTau() const
76{
77 // (M:Eq. C.12)
78 return
79 max
80 (
81 k_/epsilon_,
82 Ct_*sqrt
83 (
84 max
85 (
86 this->nu(),
87 dimensionedScalar(this->nu()().dimensions(), Zero)
88 )/epsilon_
89 )
90 );
91}
92
93
94template<class BasicTurbulenceModel>
95tmp<volSymmTensorField> EBRSM<BasicTurbulenceModel>::D
96(
97 const volScalarField& tau,
99) const
100{
101 // (M:Eq. C.10, C.14)
102 return (Cmu_/sigma*tau)*this->R_ + this->nu()*I;
103}
104
105
106template<class BasicTurbulenceModel>
107tmp<volScalarField> EBRSM<BasicTurbulenceModel>::D
108(
110) const
111{
112 // (LM:p. 2)
113 return this->nut_/sigma + this->nu();
114}
115
116
117template<class BasicTurbulenceModel>
118tmp<volScalarField> EBRSM<BasicTurbulenceModel>::Ceps1Prime
119(
120 const volScalarField& G
121) const
122{
123 // (M:Eq. C.15)
124 return Ceps1_*(scalar(1) + A1_*(scalar(1) - pow3(f_))*G/this->epsilon_);
125}
126
127
128template<class BasicTurbulenceModel>
130{
131 this->nut_ = Cmu_*k_*calcTau();
132 this->nut_.correctBoundaryConditions();
133 fv::options::New(this->mesh_).correct(this->nut_);
134
135 BasicTurbulenceModel::correctNut();
136}
137
138
139// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
140
141template<class BasicTurbulenceModel>
142EBRSM<BasicTurbulenceModel>::EBRSM
143(
144 const alphaField& alpha,
145 const rhoField& rho,
146 const volVectorField& U,
147 const surfaceScalarField& alphaRhoPhi,
148 const surfaceScalarField& phi,
149 const transportModel& transport,
150 const word& propertiesName,
151 const word& type
152)
153:
154 ReynoldsStress<RASModel<BasicTurbulenceModel>>
155 (
156 type,
157 alpha,
158 rho,
159 U,
160 alphaRhoPhi,
161 phi,
162 transport,
163 propertiesName
164 ),
165
166 simpleGradientDiffusion_
167 (
168 Switch::getOrAddToDict
169 (
170 "simpleGradientDiffusion",
171 this->coeffDict_,
172 false
173 )
174 ),
175 g1_
176 (
177 dimensioned<scalar>::getOrAddToDict
178 (
179 "g1",
180 this->coeffDict_,
181 3.4
182 )
183 ),
184 g1star_
185 (
186 dimensioned<scalar>::getOrAddToDict
187 (
188 "g1star",
189 this->coeffDict_,
190 1.8
191 )
192 ),
193 g3_
194 (
195 dimensioned<scalar>::getOrAddToDict
196 (
197 "g3",
198 this->coeffDict_,
199 0.8
200 )
201 ),
202 g3star_
203 (
204 dimensioned<scalar>::getOrAddToDict
205 (
206 "g3star",
207 this->coeffDict_,
208 1.3
209 )
210 ),
211 g4_
212 (
213 dimensioned<scalar>::getOrAddToDict
214 (
215 "g4",
216 this->coeffDict_,
217 1.25
218 )
219 ),
220 g5_
221 (
222 dimensioned<scalar>::getOrAddToDict
223 (
224 "g5",
225 this->coeffDict_,
226 0.2
227 )
228 ),
229 Cmu_
230 (
231 dimensioned<scalar>::getOrAddToDict
232 (
233 "Cmu",
234 this->coeffDict_,
235 0.21
236 )
237 ),
238 Ceps1_
239 (
240 dimensioned<scalar>::getOrAddToDict
241 (
242 "Ceps1",
243 this->coeffDict_,
244 1.44
245 )
246 ),
247 Ceps2_
248 (
249 dimensioned<scalar>::getOrAddToDict
250 (
251 "Ceps2",
252 this->coeffDict_,
253 1.83
254 )
255 ),
256 sigmaK_
257 (
258 dimensioned<scalar>::getOrAddToDict
259 (
260 "sigmaK",
261 this->coeffDict_,
262 1.0
263 )
264 ),
265 sigmaEps_
266 (
267 dimensioned<scalar>::getOrAddToDict
268 (
269 "sigmaEps",
270 this->coeffDict_,
271 1.15
272 )
273 ),
274 A1_
275 (
276 dimensioned<scalar>::getOrAddToDict
277 (
278 "A1",
279 this->coeffDict_,
280 0.065
281 )
282 ),
283 Ct_
284 (
285 dimensioned<scalar>::getOrAddToDict
286 (
287 "Ct",
288 this->coeffDict_,
289 6.0
290 )
291 ),
292 Cl_
293 (
294 dimensioned<scalar>::getOrAddToDict
295 (
296 "Cl",
297 this->coeffDict_,
298 0.133
299 )
300 ),
301 Ceta_
302 (
303 dimensioned<scalar>::getOrAddToDict
304 (
305 "Ceta",
306 this->coeffDict_,
307 80.0
308 )
309 ),
310 Cstability_
311 (
312 dimensioned<scalar>::getOrAddToDict
313 (
314 "Cstability",
315 this->coeffDict_,
317 10.0
318 )
319 ),
320
321 f_
322 (
324 (
325 IOobject::groupName("f", alphaRhoPhi.group()),
326 this->runTime_.timeName(),
327 this->mesh_,
328 IOobject::MUST_READ,
329 IOobject::AUTO_WRITE
330 ),
331 this->mesh_
332 ),
333 k_
334 (
336 (
337 IOobject::groupName("k", alphaRhoPhi.group()),
338 this->runTime_.timeName(),
339 this->mesh_,
340 IOobject::NO_READ,
341 IOobject::AUTO_WRITE
342 ),
343 0.5*tr(this->R_)
344 ),
345 epsilon_
346 (
348 (
349 IOobject::groupName("epsilon", alphaRhoPhi.group()),
350 this->runTime_.timeName(),
351 this->mesh_,
352 IOobject::MUST_READ,
353 IOobject::AUTO_WRITE
354 ),
355 this->mesh_
356 )
357{
358 this->boundNormalStress(this->R_);
359 bound(epsilon_, this->epsilonMin_);
360 bound(k_, this->kMin_);
361
362 if (type == typeName)
363 {
364 this->printCoeffs(type);
366}
367
368
369// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
370
371template<class BasicTurbulenceModel>
373{
375 {
376 simpleGradientDiffusion_.readIfPresent
377 (
378 "simpleGradientDiffusion",
379 this->coeffDict()
380 );
381 g1_.readIfPresent(this->coeffDict());
382 g1star_.readIfPresent(this->coeffDict());
383 g3_.readIfPresent(this->coeffDict());
384 g3star_.readIfPresent(this->coeffDict());
385 g4_.readIfPresent(this->coeffDict());
386 g5_.readIfPresent(this->coeffDict());
387 Cmu_.readIfPresent(this->coeffDict());
388 Ceps1_.readIfPresent(this->coeffDict());
389 Ceps2_.readIfPresent(this->coeffDict());
390 sigmaK_.readIfPresent(this->coeffDict());
391 sigmaEps_.readIfPresent(this->coeffDict());
392 A1_.readIfPresent(this->coeffDict());
393 Ct_.readIfPresent(this->coeffDict());
394 Cl_.readIfPresent(this->coeffDict());
395 Ceta_.readIfPresent(this->coeffDict());
396 Cstability_.readIfPresent(this->coeffDict());
397
398 return true;
400
401 return false;
402}
403
404
405template<class BasicTurbulenceModel>
407{
408 if (!this->turbulence_)
409 {
410 return;
411 }
412
413 // Construct local convenience references
414 const alphaField& alpha = this->alpha_;
415 const rhoField& rho = this->rho_;
416 const surfaceScalarField& alphaRhoPhi = this->alphaRhoPhi_;
417 const volVectorField& U = this->U_;
418 volSymmTensorField& R = this->R_;
419 fv::options& fvOptions(fv::options::New(this->mesh_));
420
421 ReynoldsStress<RASModel<BasicTurbulenceModel>>::correct();
422
423
424 // Calculate the velocity gradient tensor in Hessian form (delta_i u_j)
425 // Tranpose of the classical Jacobian form (delta_j u_i)
426 tmp<volTensorField> tgradU = fvc::grad(U);
427 const volTensorField& gradU = tgradU.cref();
428
429 // Calculate the production tensor
430 tmp<volSymmTensorField> tP = -twoSymm(R & gradU);
431 const volSymmTensorField& P = tP.cref();
432
433 // Calculate turbulent kinetic energy production rate
434 const volScalarField G(this->GName(), 0.5*mag(tr(P)));
435
436
437 // Calculate elliptic blending function
438 // between near-wall and weakly-inhomogeneous regions
439 {
440 // (M:Eq. C.13)
441 tmp<volScalarField> tinvLsqr = scalar(1)/sqr(calcL());
442 const volScalarField& invLsqr = tinvLsqr.cref();
443
444 // (M:Eq. C.8)
445 tmp<fvScalarMatrix> fEqn
446 (
447 fvm::Sp(invLsqr, f_)
448 - fvm::laplacian(f_)
449 ==
450 invLsqr
451 );
452
453 tinvLsqr.clear();
454
455 fEqn.ref().relax();
456 solve(fEqn);
457 }
458
459
460 // Calculate approximate wall-normal vector field (M:Eq. C.9)
461 tmp<volVectorField> tn = calcN();
462 const volVectorField& n = tn.cref();
463
464 // Calculate turbulent time scale (M:Eq. C.12)
465 tmp<volScalarField> ttau = calcTau();
466 const volScalarField& tau = ttau.cref();
467
468
469 // Calculate turbulent dissipation rate field
470 {
471 // Dissipation-production stimulator in the buffer layer (M:Eq. C.15)
472 tmp<volScalarField> tCeps1Prime = Ceps1Prime(G);
473 const volScalarField& Ceps1Prime = tCeps1Prime.cref();
474
475 // Update epsilon and G at the wall
476 epsilon_.boundaryFieldRef().updateCoeffs();
477 // Push any changed cell values to coupled neighbours
478 epsilon_.boundaryFieldRef().template evaluateCoupled<coupledFvPatch>();
479
480 // (M:Eq. C.14)
481 tmp<fvScalarMatrix> epsEqn
482 (
483 fvm::ddt(alpha, rho, epsilon_)
484 + fvm::div(alphaRhoPhi, epsilon_)
485 - (
486 simpleGradientDiffusion_
487 ? fvm::laplacian(alpha*rho*D(sigmaEps_), epsilon_)
488 : fvm::laplacian(alpha*rho*D(tau, sigmaEps_), epsilon_)
489 )
490 + fvm::Sp(Cstability_/k_, epsilon_)
491 ==
492 alpha()*rho()*Ceps1Prime()*G()/tau()
493 - fvm::Sp(alpha*rho*Ceps2_/tau, epsilon_)
494 + Cstability_*epsilon_()/k_()
495 + fvOptions(alpha, rho, epsilon_)
496 );
497
498 tCeps1Prime.clear();
499
500 epsEqn.ref().relax();
501 fvOptions.constrain(epsEqn.ref());
502 epsEqn.ref().boundaryManipulate(epsilon_.boundaryFieldRef());
503 solve(epsEqn);
504 fvOptions.correct(epsilon_);
505
506 bound(epsilon_, this->epsilonMin_);
507 }
508
509
510 // Calculate Reynolds-stress field
511 {
512 // Homogeneous form of the redistribution term (M:Eq. C.3)
513 tmp<volSymmTensorField> tPhiH;
514 {
515 // Reynolds stress anisotropy tensor (M:Eq. C.4)
516 const volSymmTensorField B(R/(scalar(2)*k_) - oneThirdI);
517
518 // Rate-of-strain tensor (M:Eq. C.5)
519 const volSymmTensorField S(symm(gradU));
520
521 // Rate-of-rotation tensor (M:Eq. C.6)
522 // Note the Hessian form of gradient
523 const volTensorField W(gradU.T() - gradU);
524
525 tPhiH =
526 k_
527 *(
528 (g3_ - g3star_*mag(B))*S
529 + g4_*devTwoSymm(B & S)
530 + g5_*twoSymm(B & W.T())
531 );
532 }
533
534
535 // Near-wall form of the redistribution model (M:Eq. C.7)
536 tmp<volSymmTensorField> tPhiW;
537 {
538 tmp<volSymmTensorField> tnn = symm(n*n);
539 const volSymmTensorField& nn = tnn.cref();
540
541 tn.clear();
542
543 tPhiW =
544 - scalar(5)*epsilon_/k_*
545 (
546 twoSymm(R & nn)
547 - 0.5*(R && nn)*(nn + I)
548 );
549 }
550
551
552 tmp<fvSymmTensorMatrix> REqn;
553 {
554 const volScalarField fCube(pow3(f_));
555
556 // Velocity-pressure gradient correlation (M:Eq. C.2)
557 const volSymmTensorField Phi
558 (
559 (scalar(1) - fCube)*tPhiW + fCube*tPhiH
560 );
561
562 // Near-wall part of the dissipation tensor (M:Eq. C.11)
563 const volScalarField epsilonW
564 (
565 (scalar(1) - fCube)*epsilon_/k_
566 );
567
568 // Homogeneous part of the dissipation tensor (M:Eq. C.11)
569 const volSphericalTensorField epsilonH
570 (
571 fCube*epsilon_*twoThirdsI
572 );
573
574 // Implicit part of the g1-term (M:Eq. C.3)
575 const volScalarField Phi1Implicit
576 (
577 fCube*(g1_*epsilon_ + g1star_*G)/(scalar(2)*k_)
578 );
579
580 // Explicit part of the g1-term (M:Eq. C.3)
581 const volSphericalTensorField Phi1Explicit
582 (
583 fCube*(g1_*epsilon_ + g1star_*G)*oneThirdI
584 );
585
586
587 // (M:Eq. C.1)
588 REqn =
589 (
591 + fvm::div(alphaRhoPhi, R)
592 - (
593 simpleGradientDiffusion_
594 ? fvm::laplacian(alpha*rho*D(sigmaK_), R)
595 : fvm::laplacian(alpha*rho*D(tau, sigmaK_), R)
596 )
597 + fvm::Sp(alpha*rho*Phi1Implicit, R)
598 + fvm::Sp(alpha*rho*epsilonW, R)
599 ==
600 alpha()*rho()*
601 (
602 P()
603 + Phi()
604 + Phi1Explicit()
605 - epsilonH()
606 )
607 + fvOptions(alpha, rho, R)
608 );
609
610 ttau.clear();
611 tP.clear();
612 }
613
614
615 REqn.ref().relax();
616 fvOptions.constrain(REqn.ref());
617 solve(REqn);
618 fvOptions.correct(R);
619
620 this->boundNormalStress(R);
621
622 #ifdef FULLDEBUG
623 this->checkRealizabilityConditions(R);
624 #endif
625
626 k_ == 0.5*tr(R);
627 bound(k_, this->kMin_);
628 }
629
630 correctNut();
631}
632
633
634// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
635
636} // End namespace RASModels
637} // End namespace Foam
638
639// ************************************************************************* //
static const Foam::dimensionedScalar B("", Foam::dimless, 18.678)
#define R(A, B, C, D, E, F, K, M)
label n
Bound the given scalar field if it has gone unbounded.
fv::options & fvOptions
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
void updateCoeffs()
Update the boundary condition coefficients.
tmp< GeometricField< Type, PatchField, GeoMesh > > T() const
Return transpose (only if it is a tensor field).
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
Templated abstract base class for RAS turbulence models.
Definition RASModel.H:81
BasicTurbulenceModel::alphaField alphaField
Definition EBRSM.H:208
BasicTurbulenceModel::rhoField rhoField
Definition EBRSM.H:209
virtual void correct()
Solve the transport equations and correct the turbulent viscosity.
Definition EBRSM.C:399
BasicTurbulenceModel::transportModel transportModel
Definition EBRSM.H:210
virtual bool read()
Re-read model coefficients if they have changed.
Definition EBRSM.C:365
Reynolds-stress turbulence model base class.
virtual tmp< volSymmTensorField > R() const
ReynoldsStress(const word &modelName, const alphaField &alpha, const rhoField &rho, const volVectorField &U, const surfaceScalarField &alphaRhoPhi, const surfaceScalarField &phi, const transportModel &transport, const word &propertiesName)
void checkRealizabilityConditions(const volSymmTensorField &R) const
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
Definition Switch.H:81
Generic dimensioned Type class.
dimensioned< Type > T() const
Return transpose.
void correct(GeometricField< Type, PatchField, GeoMesh > &field)
Apply correction to field.
Finite-volume options, which is an IOdictionary of values and a fv::optionList.
Definition fvOptions.H:69
static options & New(const fvMesh &mesh)
Construct fvOptions and register to database if not present otherwise lookup and return.
Definition fvOptions.C:116
A class for managing temporary objects.
Definition tmp.H:75
const T & cref() const
Return const reference to the object or to the contents of a (non-null) managed pointer.
Definition tmpI.H:221
void clear() const noexcept
If object pointer points to valid object: delete object and set pointer to nullptr.
Definition tmpI.H:289
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
Definition tmpI.H:235
Base-class for all transport models used by the incompressible turbulence models.
A class for handling words, derived from Foam::string.
Definition word.H:66
U
Definition pEqn.H:72
thermo correct()
zeroField Sp
Definition alphaSuSp.H:2
word timeName
Definition getTimeIndex.H:3
const dimensionedScalar G
Newtonian constant of gravitation.
tmp< GeometricField< Type, faPatchField, areaMesh > > laplacian(const GeometricField< Type, faPatchField, areaMesh > &vf, const word &name)
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh > > grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition fvcGrad.C:47
tmp< fvMatrix< Type > > laplacian(const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
tmp< fvMatrix< Type > > div(const surfaceScalarField &flux, const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition fvmDiv.C:41
tmp< fvMatrix< Type > > ddt(const GeometricField< Type, fvPatchField, volMesh > &vf)
Definition fvmDdt.C:41
zeroField Sp(const Foam::zero, const GeometricField< Type, fvPatchField, volMesh > &)
A no-op source.
Namespace for OpenFOAM.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
dimensionedSymmTensor symm(const dimensionedSymmTensor &dt)
GeometricField< vector, fvPatchField, volMesh > volVectorField
const dimensionSet dimless
Dimensionless.
dimensionedScalar tr(const dimensionedSphericalTensor &dt)
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition int32.H:127
dimensionedSymmTensor sqr(const dimensionedVector &dv)
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
dimensionedScalar pow3(const dimensionedScalar &ds)
volScalarField & bound(volScalarField &, const dimensionedScalar &lowerBound)
Bound the given scalar field if it has gone unbounded.
Definition bound.C:29
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
GeometricField< scalar, fvPatchField, volMesh > volScalarField
SymmTensor< Cmpt > devTwoSymm(const SymmTensor< Cmpt > &st)
Return the deviatoric part of twice the symmetric part of a SymmTensor.
dimensionedSymmTensor twoSymm(const dimensionedSymmTensor &dt)
static const Identity< scalar > I
Definition Identity.H:100
GeometricField< scalar, fvsPatchField, surfaceMesh > surfaceScalarField
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
const word GlobalIOList< Tuple2< scalar, vector > >::typeName("scalarVectorTable")
GeometricField< tensor, fvPatchField, volMesh > volTensorField
dimensionedScalar sqrt(const dimensionedScalar &ds)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
GeometricField< sphericalTensor, fvPatchField, volMesh > volSphericalTensorField
GeometricField< symmTensor, fvPatchField, volMesh > volSymmTensorField
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
static const sphericalTensor twoThirdsI(2.0/3.0)
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
static const sphericalTensor oneThirdI(1.0/3.0)
dimensionedScalar pow025(const dimensionedScalar &ds)
volScalarField & nu
volScalarField & alpha
const dimensionedScalar & D
CEqn solve()
dimensionedScalar sigma("sigma", dimMass/sqr(dimTime), transportProperties)