00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "LaunderGibsonRSTM.H"
00027 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00028 #include <finiteVolume/wallFvPatch.H>
00029
00030 #include <incompressibleRASModels/backwardsCompatibilityWallFunctions.H>
00031
00032
00033
00034 namespace Foam
00035 {
00036 namespace incompressible
00037 {
00038 namespace RASModels
00039 {
00040
00041
00042
00043 defineTypeNameAndDebug(LaunderGibsonRSTM, 0);
00044 addToRunTimeSelectionTable(RASModel, LaunderGibsonRSTM, dictionary);
00045
00046
00047
00048 LaunderGibsonRSTM::LaunderGibsonRSTM
00049 (
00050 const volVectorField& U,
00051 const surfaceScalarField& phi,
00052 transportModel& lamTransportModel
00053 )
00054 :
00055 RASModel(typeName, U, phi, lamTransportModel),
00056
00057 Cmu_
00058 (
00059 dimensioned<scalar>::lookupOrAddToDict
00060 (
00061 "Cmu",
00062 coeffDict_,
00063 0.09
00064 )
00065 ),
00066 kappa_
00067 (
00068 dimensioned<scalar>::lookupOrAddToDict
00069 (
00070 "kappa",
00071 coeffDict_,
00072 0.41
00073 )
00074 ),
00075 Clg1_
00076 (
00077 dimensioned<scalar>::lookupOrAddToDict
00078 (
00079 "Clg1",
00080 coeffDict_,
00081 1.8
00082 )
00083 ),
00084 Clg2_
00085 (
00086 dimensioned<scalar>::lookupOrAddToDict
00087 (
00088 "Clg2",
00089 coeffDict_,
00090 0.6
00091 )
00092 ),
00093 C1_
00094 (
00095 dimensioned<scalar>::lookupOrAddToDict
00096 (
00097 "C1",
00098 coeffDict_,
00099 1.44
00100 )
00101 ),
00102 C2_
00103 (
00104 dimensioned<scalar>::lookupOrAddToDict
00105 (
00106 "C2",
00107 coeffDict_,
00108 1.92
00109 )
00110 ),
00111 Cs_
00112 (
00113 dimensioned<scalar>::lookupOrAddToDict
00114 (
00115 "Cs",
00116 coeffDict_,
00117 0.25
00118 )
00119 ),
00120 Ceps_
00121 (
00122 dimensioned<scalar>::lookupOrAddToDict
00123 (
00124 "Ceps",
00125 coeffDict_,
00126 0.15
00127 )
00128 ),
00129 sigmaR_
00130 (
00131 dimensioned<scalar>::lookupOrAddToDict
00132 (
00133 "sigmaR",
00134 coeffDict_,
00135 0.81967
00136 )
00137 ),
00138 sigmaEps_
00139 (
00140 dimensioned<scalar>::lookupOrAddToDict
00141 (
00142 "sigmaEps",
00143 coeffDict_,
00144 1.3
00145 )
00146 ),
00147 C1Ref_
00148 (
00149 dimensioned<scalar>::lookupOrAddToDict
00150 (
00151 "C1Ref",
00152 coeffDict_,
00153 0.5
00154 )
00155 ),
00156 C2Ref_
00157 (
00158 dimensioned<scalar>::lookupOrAddToDict
00159 (
00160 "C2Ref",
00161 coeffDict_,
00162 0.3
00163 )
00164 ),
00165 couplingFactor_
00166 (
00167 dimensioned<scalar>::lookupOrAddToDict
00168 (
00169 "couplingFactor",
00170 coeffDict_,
00171 0.0
00172 )
00173 ),
00174
00175 yr_(mesh_),
00176
00177 R_
00178 (
00179 IOobject
00180 (
00181 "R",
00182 runTime_.timeName(),
00183 mesh_,
00184 IOobject::NO_READ,
00185 IOobject::AUTO_WRITE
00186 ),
00187 autoCreateR("R", mesh_)
00188 ),
00189 k_
00190 (
00191 IOobject
00192 (
00193 "k",
00194 runTime_.timeName(),
00195 mesh_,
00196 IOobject::NO_READ,
00197 IOobject::AUTO_WRITE
00198 ),
00199 autoCreateK("k", mesh_)
00200 ),
00201 epsilon_
00202 (
00203 IOobject
00204 (
00205 "epsilon",
00206 runTime_.timeName(),
00207 mesh_,
00208 IOobject::NO_READ,
00209 IOobject::AUTO_WRITE
00210 ),
00211 autoCreateEpsilon("epsilon", mesh_)
00212 ),
00213 nut_
00214 (
00215 IOobject
00216 (
00217 "nut",
00218 runTime_.timeName(),
00219 mesh_,
00220 IOobject::NO_READ,
00221 IOobject::AUTO_WRITE
00222 ),
00223 autoCreateNut("nut", mesh_)
00224 )
00225 {
00226 nut_ = Cmu_*sqr(k_)/(epsilon_ + epsilonSmall_);
00227 nut_.correctBoundaryConditions();
00228
00229 if (couplingFactor_.value() < 0.0 || couplingFactor_.value() > 1.0)
00230 {
00231 FatalErrorIn
00232 (
00233 "LaunderGibsonRSTM::LaunderGibsonRSTM"
00234 "(const volVectorField& U, const surfaceScalarField& phi,"
00235 "transportModel& lamTransportModel)"
00236 ) << "couplingFactor = " << couplingFactor_
00237 << " is not in range 0 - 1" << nl
00238 << exit(FatalError);
00239 }
00240
00241 printCoeffs();
00242 }
00243
00244
00245
00246
00247 tmp<volSymmTensorField> LaunderGibsonRSTM::devReff() const
00248 {
00249 return tmp<volSymmTensorField>
00250 (
00251 new volSymmTensorField
00252 (
00253 IOobject
00254 (
00255 "devRhoReff",
00256 runTime_.timeName(),
00257 mesh_,
00258 IOobject::NO_READ,
00259 IOobject::NO_WRITE
00260 ),
00261 R_ - nu()*dev(twoSymm(fvc::grad(U_)))
00262 )
00263 );
00264 }
00265
00266
00267 tmp<fvVectorMatrix> LaunderGibsonRSTM::divDevReff(volVectorField& U) const
00268 {
00269 if (couplingFactor_.value() > 0.0)
00270 {
00271 return
00272 (
00273 fvc::div(R_ + couplingFactor_*nut_*fvc::grad(U), "div(R)")
00274 + fvc::laplacian((1.0-couplingFactor_)*nut_, U, "laplacian(nuEff,U)")
00275 - fvm::laplacian(nuEff(), U)
00276 );
00277 }
00278 else
00279 {
00280 return
00281 (
00282 fvc::div(R_)
00283 + fvc::laplacian(nut_, U, "laplacian(nuEff,U)")
00284 - fvm::laplacian(nuEff(), U)
00285 );
00286 }
00287 }
00288
00289
00290 bool LaunderGibsonRSTM::read()
00291 {
00292 if (RASModel::read())
00293 {
00294 Cmu_.readIfPresent(coeffDict());
00295 Clg1_.readIfPresent(coeffDict());
00296 Clg2_.readIfPresent(coeffDict());
00297 C1_.readIfPresent(coeffDict());
00298 C2_.readIfPresent(coeffDict());
00299 Cs_.readIfPresent(coeffDict());
00300 Ceps_.readIfPresent(coeffDict());
00301 sigmaR_.readIfPresent(coeffDict());
00302 sigmaEps_.readIfPresent(coeffDict());
00303 C1Ref_.readIfPresent(coeffDict());
00304 C2Ref_.readIfPresent(coeffDict());
00305
00306 couplingFactor_.readIfPresent(coeffDict());
00307
00308 if (couplingFactor_.value() < 0.0 || couplingFactor_.value() > 1.0)
00309 {
00310 FatalErrorIn("LaunderGibsonRSTM::read()")
00311 << "couplingFactor = " << couplingFactor_
00312 << " is not in range 0 - 1"
00313 << exit(FatalError);
00314 }
00315
00316 return true;
00317 }
00318 else
00319 {
00320 return false;
00321 }
00322 }
00323
00324
00325 void LaunderGibsonRSTM::correct()
00326 {
00327 RASModel::correct();
00328
00329 if (!turbulence_)
00330 {
00331 return;
00332 }
00333
00334 if (mesh_.changing())
00335 {
00336 yr_.correct();
00337 }
00338
00339 volSymmTensorField P = -twoSymm(R_ & fvc::grad(U_));
00340 volScalarField G("RASModel::G", 0.5*mag(tr(P)));
00341
00342
00343 epsilon_.boundaryField().updateCoeffs();
00344
00345
00346 tmp<fvScalarMatrix> epsEqn
00347 (
00348 fvm::ddt(epsilon_)
00349 + fvm::div(phi_, epsilon_)
00350 - fvm::Sp(fvc::div(phi_), epsilon_)
00351
00352 - fvm::laplacian(DepsilonEff(), epsilon_)
00353 ==
00354 C1_*G*epsilon_/k_
00355 - fvm::Sp(C2_*epsilon_/k_, epsilon_)
00356 );
00357
00358 epsEqn().relax();
00359
00360 epsEqn().boundaryManipulate(epsilon_.boundaryField());
00361
00362 solve(epsEqn);
00363 bound(epsilon_, epsilon0_);
00364
00365
00366
00367
00368 const fvPatchList& patches = mesh_.boundary();
00369
00370 forAll(patches, patchi)
00371 {
00372 const fvPatch& curPatch = patches[patchi];
00373
00374 if (isA<wallFvPatch>(curPatch))
00375 {
00376 forAll(curPatch, facei)
00377 {
00378 label faceCelli = curPatch.faceCells()[facei];
00379 P[faceCelli] *=
00380 min(G[faceCelli]/(0.5*mag(tr(P[faceCelli])) + SMALL), 1.0);
00381 }
00382 }
00383 }
00384
00385 volSymmTensorField reflect = C1Ref_*epsilon_/k_*R_ - C2Ref_*Clg2_*dev(P);
00386
00387 tmp<fvSymmTensorMatrix> REqn
00388 (
00389 fvm::ddt(R_)
00390 + fvm::div(phi_, R_)
00391 - fvm::Sp(fvc::div(phi_), R_)
00392
00393 - fvm::laplacian(DREff(), R_)
00394 + fvm::Sp(Clg1_*epsilon_/k_, R_)
00395 ==
00396 P
00397 + (2.0/3.0*(Clg1_ - 1)*I)*epsilon_
00398 - Clg2_*dev(P)
00399
00400
00401 + symm
00402 (
00403 I*((yr_.n() & reflect) & yr_.n())
00404 - 1.5*(yr_.n()*(reflect & yr_.n())
00405 + (yr_.n() & reflect)*yr_.n())
00406 )*pow(Cmu_, 0.75)*pow(k_, 1.5)/(kappa_*yr_*epsilon_)
00407 );
00408
00409 REqn().relax();
00410 solve(REqn);
00411
00412 R_.max
00413 (
00414 dimensionedSymmTensor
00415 (
00416 "zero",
00417 R_.dimensions(),
00418 symmTensor
00419 (
00420 k0_.value(), -GREAT, -GREAT,
00421 k0_.value(), -GREAT,
00422 k0_.value()
00423 )
00424 )
00425 );
00426
00427 k_ == 0.5*tr(R_);
00428 bound(k_, k0_);
00429
00430
00431
00432 nut_ = Cmu_*sqr(k_)/epsilon_;
00433 nut_.correctBoundaryConditions();
00434
00435
00436
00437
00438 forAll(patches, patchi)
00439 {
00440 const fvPatch& curPatch = patches[patchi];
00441
00442 if (isA<wallFvPatch>(curPatch))
00443 {
00444 symmTensorField& Rw = R_.boundaryField()[patchi];
00445
00446 const scalarField& nutw = nut_.boundaryField()[patchi];
00447
00448 vectorField snGradU = U_.boundaryField()[patchi].snGrad();
00449
00450 const vectorField& faceAreas
00451 = mesh_.Sf().boundaryField()[patchi];
00452
00453 const scalarField& magFaceAreas
00454 = mesh_.magSf().boundaryField()[patchi];
00455
00456 forAll(curPatch, facei)
00457 {
00458
00459 tensor gradUw
00460 = (faceAreas[facei]/magFaceAreas[facei])*snGradU[facei];
00461
00462
00463 tensor tauw = -nutw[facei]*2*symm(gradUw);
00464
00465
00466 Rw[facei].xy() = tauw.xy();
00467 Rw[facei].xz() = tauw.xz();
00468 Rw[facei].yz() = tauw.yz();
00469 }
00470 }
00471 }
00472 }
00473
00474
00475
00476
00477 }
00478 }
00479 }
00480
00481