1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
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.
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
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/>.
24 \*---------------------------------------------------------------------------*/
26 #include "LaunderGibsonRSTM.H"
27 #include "addToRunTimeSelectionTable.H"
28 #include "wallFvPatch.H"
30 #include "backwardsCompatibilityWallFunctions.H"
32 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
36 namespace incompressible
41 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
43 defineTypeNameAndDebug(LaunderGibsonRSTM, 0);
44 addToRunTimeSelectionTable(RASModel, LaunderGibsonRSTM, dictionary);
46 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
48 LaunderGibsonRSTM::LaunderGibsonRSTM
50 const volVectorField& U,
51 const surfaceScalarField& phi,
52 transportModel& transport,
53 const word& turbulenceModelName,
57 RASModel(modelName, U, phi, transport, turbulenceModelName),
61 dimensioned<scalar>::lookupOrAddToDict
70 dimensioned<scalar>::lookupOrAddToDict
79 dimensioned<scalar>::lookupOrAddToDict
88 dimensioned<scalar>::lookupOrAddToDict
97 dimensioned<scalar>::lookupOrAddToDict
106 dimensioned<scalar>::lookupOrAddToDict
115 dimensioned<scalar>::lookupOrAddToDict
124 dimensioned<scalar>::lookupOrAddToDict
133 dimensioned<scalar>::lookupOrAddToDict
142 dimensioned<scalar>::lookupOrAddToDict
151 dimensioned<scalar>::lookupOrAddToDict
160 dimensioned<scalar>::lookupOrAddToDict
169 dimensioned<scalar>::lookupOrAddToDict
189 autoCreateR("R", mesh_)
201 autoCreateK("k", mesh_)
213 autoCreateEpsilon("epsilon", mesh_)
225 autoCreateNut("nut", mesh_)
229 bound(epsilon_, epsilonMin_);
231 nut_ = Cmu_*sqr(k_)/epsilon_;
232 nut_.correctBoundaryConditions();
234 if (couplingFactor_.value() < 0.0 || couplingFactor_.value() > 1.0)
238 "LaunderGibsonRSTM::LaunderGibsonRSTM"
239 "(const volVectorField& U, const surfaceScalarField& phi,"
240 "transportModel& transport)"
241 ) << "couplingFactor = " << couplingFactor_
242 << " is not in range 0 - 1" << nl
250 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
252 tmp<volSymmTensorField> LaunderGibsonRSTM::devReff() const
254 return tmp<volSymmTensorField>
256 new volSymmTensorField
266 R_ - nu()*dev(twoSymm(fvc::grad(U_)))
272 tmp<fvVectorMatrix> LaunderGibsonRSTM::divDevReff(volVectorField& U) const
274 if (couplingFactor_.value() > 0.0)
278 fvc::div(R_ + couplingFactor_*nut_*fvc::grad(U), "div(R)")
279 + fvc::laplacian((1.0-couplingFactor_)*nut_, U, "laplacian(nuEff,U)")
280 - fvm::laplacian(nuEff(), U)
288 + fvc::laplacian(nut_, U, "laplacian(nuEff,U)")
289 - fvm::laplacian(nuEff(), U)
295 bool LaunderGibsonRSTM::read()
297 if (RASModel::read())
299 Cmu_.readIfPresent(coeffDict());
300 kappa_.readIfPresent(coeffDict());
301 Clg1_.readIfPresent(coeffDict());
302 Clg2_.readIfPresent(coeffDict());
303 C1_.readIfPresent(coeffDict());
304 C2_.readIfPresent(coeffDict());
305 Cs_.readIfPresent(coeffDict());
306 Ceps_.readIfPresent(coeffDict());
307 sigmaR_.readIfPresent(coeffDict());
308 sigmaEps_.readIfPresent(coeffDict());
309 C1Ref_.readIfPresent(coeffDict());
310 C2Ref_.readIfPresent(coeffDict());
312 couplingFactor_.readIfPresent(coeffDict());
314 if (couplingFactor_.value() < 0.0 || couplingFactor_.value() > 1.0)
316 FatalErrorIn("LaunderGibsonRSTM::read()")
317 << "couplingFactor = " << couplingFactor_
318 << " is not in range 0 - 1"
331 void LaunderGibsonRSTM::correct()
340 if (mesh_.changing())
345 volSymmTensorField P(-twoSymm(R_ & fvc::grad(U_)));
346 volScalarField G("RASModel::G", 0.5*mag(tr(P)));
348 // Update epsilon and G at the wall
349 epsilon_.boundaryField().updateCoeffs();
351 // Dissipation equation
352 tmp<fvScalarMatrix> epsEqn
355 + fvm::div(phi_, epsilon_)
356 - fvm::Sp(fvc::div(phi_), epsilon_)
357 //- fvm::laplacian(Ceps*(k_/epsilon_)*R_, epsilon_)
358 - fvm::laplacian(DepsilonEff(), epsilon_)
361 - fvm::Sp(C2_*epsilon_/k_, epsilon_)
366 epsEqn().boundaryManipulate(epsilon_.boundaryField());
369 bound(epsilon_, epsilonMin_);
372 // Reynolds stress equation
374 const fvPatchList& patches = mesh_.boundary();
376 forAll(patches, patchi)
378 const fvPatch& curPatch = patches[patchi];
380 if (isA<wallFvPatch>(curPatch))
382 forAll(curPatch, facei)
384 label faceCelli = curPatch.faceCells()[facei];
386 min(G[faceCelli]/(0.5*mag(tr(P[faceCelli])) + SMALL), 1.0);
391 const volSymmTensorField reflect
393 C1Ref_*epsilon_/k_*R_ - C2Ref_*Clg2_*dev(P)
396 tmp<fvSymmTensorMatrix> REqn
400 - fvm::Sp(fvc::div(phi_), R_)
401 //- fvm::laplacian(Cs*(k_/epsilon_)*R_, R_)
402 - fvm::laplacian(DREff(), R_)
403 + fvm::Sp(Clg1_*epsilon_/k_, R_)
406 + (2.0/3.0*(Clg1_ - 1)*I)*epsilon_
409 // wall reflection terms
412 I*((yr_.n() & reflect) & yr_.n())
413 - 1.5*(yr_.n()*(reflect & yr_.n())
414 + (yr_.n() & reflect)*yr_.n())
415 )*pow(Cmu_, 0.75)*pow(k_, 1.5)/(kappa_*yr_*epsilon_)
423 dimensionedSymmTensor
429 kMin_.value(), -GREAT, -GREAT,
430 kMin_.value(), -GREAT,
440 // Re-calculate turbulent viscosity
441 nut_ = Cmu_*sqr(k_)/epsilon_;
442 nut_.correctBoundaryConditions();
445 // Correct wall shear stresses
447 forAll(patches, patchi)
449 const fvPatch& curPatch = patches[patchi];
451 if (isA<wallFvPatch>(curPatch))
453 symmTensorField& Rw = R_.boundaryField()[patchi];
455 const scalarField& nutw = nut_.boundaryField()[patchi];
457 const vectorField snGradU(U_.boundaryField()[patchi].snGrad());
459 const vectorField& faceAreas
460 = mesh_.Sf().boundaryField()[patchi];
462 const scalarField& magFaceAreas
463 = mesh_.magSf().boundaryField()[patchi];
465 forAll(curPatch, facei)
467 // Calculate near-wall velocity gradient
469 = (faceAreas[facei]/magFaceAreas[facei])*snGradU[facei];
471 // Calculate near-wall shear-stress tensor
472 tensor tauw = -nutw[facei]*2*symm(gradUw);
474 // Reset the shear components of the stress tensor
475 Rw[facei].xy() = tauw.xy();
476 Rw[facei].xz() = tauw.xz();
477 Rw[facei].yz() = tauw.yz();
484 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
486 } // End namespace RASModels
487 } // End namespace incompressible
488 } // End namespace Foam
490 // ************************************************************************* //