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 \*---------------------------------------------------------------------------*/
27 #include "addToRunTimeSelectionTable.H"
28 #include "wallFvPatch.H"
30 #include "backwardsCompatibilityWallFunctions.H"
32 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
36 namespace incompressible
41 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
43 defineTypeNameAndDebug(LRR, 0);
44 addToRunTimeSelectionTable(RASModel, LRR, dictionary);
46 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
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
151 autoCreateR("R", mesh_)
163 autoCreateK("k", mesh_)
175 autoCreateEpsilon("epsilon", mesh_)
187 autoCreateNut("nut", mesh_)
190 if (couplingFactor_.value() < 0.0 || couplingFactor_.value() > 1.0)
195 "(const volVectorField& U, const surfaceScalarField& phi,"
196 "transportModel& transport)"
197 ) << "couplingFactor = " << couplingFactor_
198 << " is not in range 0 - 1" << nl
203 bound(epsilon_, epsilonMin_);
205 nut_ = Cmu_*sqr(k_)/epsilon_;
206 nut_.correctBoundaryConditions();
212 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
214 tmp<volSymmTensorField> LRR::devReff() const
216 return tmp<volSymmTensorField>
218 new volSymmTensorField
228 R_ - nu()*dev(twoSymm(fvc::grad(U_)))
234 tmp<fvVectorMatrix> LRR::divDevReff(volVectorField& U) const
236 if (couplingFactor_.value() > 0.0)
240 fvc::div(R_ + couplingFactor_*nut_*fvc::grad(U), "div(R)")
243 (1.0 - couplingFactor_)*nut_,
247 - fvm::laplacian(nuEff(), U)
255 + fvc::laplacian(nut_, U, "laplacian(nuEff,U)")
256 - fvm::laplacian(nuEff(), U)
264 if (RASModel::read())
266 Cmu_.readIfPresent(coeffDict());
267 Clrr1_.readIfPresent(coeffDict());
268 Clrr2_.readIfPresent(coeffDict());
269 C1_.readIfPresent(coeffDict());
270 C2_.readIfPresent(coeffDict());
271 Cs_.readIfPresent(coeffDict());
272 Ceps_.readIfPresent(coeffDict());
273 sigmaEps_.readIfPresent(coeffDict());
275 couplingFactor_.readIfPresent(coeffDict());
277 if (couplingFactor_.value() < 0.0 || couplingFactor_.value() > 1.0)
279 FatalErrorIn("LRR::read()")
280 << "couplingFactor = " << couplingFactor_
281 << " is not in range 0 - 1"
303 volSymmTensorField P(-twoSymm(R_ & fvc::grad(U_)));
304 volScalarField G("RASModel::G", 0.5*mag(tr(P)));
306 // Update epsilon and G at the wall
307 epsilon_.boundaryField().updateCoeffs();
309 // Dissipation equation
310 tmp<fvScalarMatrix> epsEqn
313 + fvm::div(phi_, epsilon_)
314 - fvm::Sp(fvc::div(phi_), epsilon_)
315 //- fvm::laplacian(Ceps*(K/epsilon_)*R, epsilon_)
316 - fvm::laplacian(DepsilonEff(), epsilon_)
319 - fvm::Sp(C2_*epsilon_/k_, epsilon_)
324 epsEqn().boundaryManipulate(epsilon_.boundaryField());
327 bound(epsilon_, epsilonMin_);
330 // Reynolds stress equation
332 const fvPatchList& patches = mesh_.boundary();
334 forAll(patches, patchi)
336 const fvPatch& curPatch = patches[patchi];
338 if (isA<wallFvPatch>(curPatch))
340 forAll(curPatch, facei)
342 label faceCelli = curPatch.faceCells()[facei];
345 G[faceCelli]/(0.5*mag(tr(P[faceCelli])) + SMALL),
353 tmp<fvSymmTensorMatrix> REqn
357 - fvm::Sp(fvc::div(phi_), R_)
358 //- fvm::laplacian(Cs*(k_/epsilon_)*R_, R_)
359 - fvm::laplacian(DREff(), R_)
360 + fvm::Sp(Clrr1_*epsilon_/k_, R_)
363 - (2.0/3.0*(1 - Clrr1_)*I)*epsilon_
372 dimensionedSymmTensor
378 kMin_.value(), -GREAT, -GREAT,
379 kMin_.value(), -GREAT,
389 // Re-calculate viscosity
390 nut_ = Cmu_*sqr(k_)/epsilon_;
391 nut_.correctBoundaryConditions();
394 // Correct wall shear stresses
396 forAll(patches, patchi)
398 const fvPatch& curPatch = patches[patchi];
400 if (isA<wallFvPatch>(curPatch))
402 symmTensorField& Rw = R_.boundaryField()[patchi];
404 const scalarField& nutw = nut_.boundaryField()[patchi];
406 const vectorField snGradU(U_.boundaryField()[patchi].snGrad());
408 const vectorField& faceAreas
409 = mesh_.Sf().boundaryField()[patchi];
411 const scalarField& magFaceAreas
412 = mesh_.magSf().boundaryField()[patchi];
414 forAll(curPatch, facei)
416 // Calculate near-wall velocity gradient
418 = (faceAreas[facei]/magFaceAreas[facei])*snGradU[facei];
420 // Calculate near-wall shear-stress tensor
421 tensor tauw = -nutw[facei]*2*symm(gradUw);
423 // Reset the shear components of the stress tensor
424 Rw[facei].xy() = tauw.xy();
425 Rw[facei].xz() = tauw.xz();
426 Rw[facei].yz() = tauw.yz();
433 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
435 } // End namespace RASModels
436 } // End namespace incompressible
437 } // End namespace Foam
439 // ************************************************************************* //