1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "immersedBoundaryOmegaWallFunctionFvPatchScalarField.H"
27 #include "immersedBoundaryVelocityWallFunctionFvPatchVectorField.H"
29 #include "fvPatchFieldMapper.H"
30 #include "volFields.H"
31 #include "addToRunTimeSelectionTable.H"
33 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
37 namespace incompressible
42 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
44 immersedBoundaryOmegaWallFunctionFvPatchScalarField::
45 immersedBoundaryOmegaWallFunctionFvPatchScalarField
48 const DimensionedField<scalar, volMesh>& iF
51 immersedBoundaryWallFunctionFvPatchScalarField(p, iF),
54 GName_("RASModel::G"),
64 immersedBoundaryOmegaWallFunctionFvPatchScalarField::
65 immersedBoundaryOmegaWallFunctionFvPatchScalarField
68 const DimensionedField<scalar, volMesh>& iF,
69 const dictionary& dict
72 immersedBoundaryWallFunctionFvPatchScalarField(p, iF, dict),
73 UName_(dict.lookupOrDefault<word>("U", "U")),
74 kName_(dict.lookupOrDefault<word>("k", "k")),
75 GName_(dict.lookupOrDefault<word>("G", "RASModel::G")),
76 nuName_(dict.lookupOrDefault<word>("nu", "nu")),
77 nutName_(dict.lookupOrDefault<word>("nut", "nut")),
78 Cmu_(dict.lookupOrDefault<scalar>("Cmu", 0.09)),
79 kappa_(dict.lookupOrDefault<scalar>("kappa", 0.41)),
80 E_(dict.lookupOrDefault<scalar>("E", 9.8)),
81 beta1_(dict.lookupOrDefault<scalar>("beta1", 0.075))
85 immersedBoundaryOmegaWallFunctionFvPatchScalarField::
86 immersedBoundaryOmegaWallFunctionFvPatchScalarField
88 const immersedBoundaryOmegaWallFunctionFvPatchScalarField& ptf,
90 const DimensionedField<scalar, volMesh>& iF,
91 const fvPatchFieldMapper& mapper
94 immersedBoundaryWallFunctionFvPatchScalarField(ptf, p, iF, mapper),
99 nutName_(ptf.nutName_),
107 immersedBoundaryOmegaWallFunctionFvPatchScalarField::
108 immersedBoundaryOmegaWallFunctionFvPatchScalarField
110 const immersedBoundaryOmegaWallFunctionFvPatchScalarField& owfpsf
113 immersedBoundaryWallFunctionFvPatchScalarField(owfpsf),
114 UName_(owfpsf.UName_),
115 kName_(owfpsf.kName_),
116 GName_(owfpsf.GName_),
117 nuName_(owfpsf.nuName_),
118 nutName_(owfpsf.nutName_),
120 kappa_(owfpsf.kappa_),
125 immersedBoundaryOmegaWallFunctionFvPatchScalarField::
126 immersedBoundaryOmegaWallFunctionFvPatchScalarField
128 const immersedBoundaryOmegaWallFunctionFvPatchScalarField& owfpsf,
129 const DimensionedField<scalar, volMesh>& iF
132 immersedBoundaryWallFunctionFvPatchScalarField(owfpsf, iF),
133 UName_(owfpsf.UName_),
134 kName_(owfpsf.kName_),
135 GName_(owfpsf.GName_),
136 nuName_(owfpsf.nuName_),
137 nutName_(owfpsf.nutName_),
139 kappa_(owfpsf.kappa_),
144 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
146 void immersedBoundaryOmegaWallFunctionFvPatchScalarField::updateCoeffs()
153 // If G field is not present, execute zero gradient evaluation
155 if (!db().foundObject<volScalarField>(GName_))
159 "void immersedBoundaryOmegaWallFunctionFvPatchScalarField::"
161 ) << "Cannot access " << GName_ << " field. for patch "
162 << patch().name() << ". Evaluating as regular immersed boundary"
165 immersedBoundaryWallFunctionFvPatchScalarField::evaluate();
170 const vectorField& n = ibPatch().ibNormals();
172 const RASModel& rasModel = db().lookupObject<RASModel>("RASProperties");
173 const scalar yPlusLam = rasModel.yPlusLam(kappa_, E_);
175 const scalar Cmu25 = pow(Cmu_, 0.25);
176 const scalar Cmu50 = sqrt(Cmu_);
178 volScalarField& G = const_cast<volScalarField&>
179 (db().lookupObject<volScalarField>(GName_));
181 // Grab values of other fields required for wall functions
184 const fvPatchVectorField& Uwg =
185 patch().lookupPatchField<volVectorField, vector>(UName_);
186 const immersedBoundaryVelocityWallFunctionFvPatchVectorField& Uw =
187 refCast<const immersedBoundaryVelocityWallFunctionFvPatchVectorField>
192 // Calculate tangential component, taking into account wall velocity
193 const scalarField UtanOld =
194 mag((I - sqr(n)) & (Uw.ibSamplingPointValue() - Uw.ibValue()));
196 scalarField& UTangentialNew = Uw.wallTangentialValue();
198 // Turbulence kinetic energy
199 const fvPatchScalarField& kg =
200 patch().lookupPatchField<volScalarField, scalar>(kName_);
201 const immersedBoundaryWallFunctionFvPatchScalarField& kw =
202 refCast<const immersedBoundaryWallFunctionFvPatchScalarField>(kg);
204 // Current and new values of k at sampling point
205 scalarField k = kw.ibSamplingPointValue();
206 scalarField& kNew = kw.wallValue();
209 const fvPatchScalarField& nuwg =
210 patch().lookupPatchField<volScalarField, scalar>(nuName_);
211 const immersedBoundaryFvPatchScalarField& nuw =
212 refCast<const immersedBoundaryFvPatchScalarField>(nuwg);
213 scalarField nu = nuw.ibCellValue();
215 // Turbulent viscosity
216 const fvPatchScalarField& nutwg =
217 patch().lookupPatchField<volScalarField, scalar>(nutName_);
218 const immersedBoundaryWallFunctionFvPatchScalarField& nutw =
219 refCast<const immersedBoundaryWallFunctionFvPatchScalarField>(nutwg);
222 scalarField nutOld = nutw.ibCellValue();
223 scalarField& nutNew = nutw.wallValue();
225 const scalarField magGradUw = mag(Uw.ibGrad());
227 // Get the IB addressing and distance
228 const labelList& ibc = ibPatch().ibCells();
230 // Distance to sampling point
231 const scalarField& ySample = ibPatch().ibSamplingPointDelta();
233 // Distance from wall to IB point
234 const scalarField& y = ibPatch().ibDelta();
236 // Omega: store IB cell values for direct insertion
237 scalarField omegaSample = this->ibSamplingPointValue();
239 scalarField& omegaNew = this->wallValue();
241 // Mark values to be fixed
242 boolList wf(ibc.size(), false);
244 // Calculate yPlus for sample points
245 scalarField ypd = Cmu25*ySample*sqrt(k)/nu;
247 // Calculate wall function conditions
248 forAll (ibc, ibCellI)
250 const scalar nuLam = nu[ibCellI];
252 // Calculate yPlus from k and laminar viscosity for the IB point
253 const scalar yPlusSample = ypd[ibCellI];
255 scalar tauW, uTau; // wall-shear and friction velocity from LOW
257 if (yPlusSample > yPlusLam)
259 // Calculate tauW from log-law using k and U at sampling point
261 tauW = UtanOld[ibCellI]*Cmu25*sqrt(k[ibCellI])*kappa_
262 /log(E_*yPlusSample);
266 // Sampling point is in laminar sublayer
267 tauW = UtanOld[ibCellI]*Cmu25*sqrt(k[ibCellI])/yPlusSample;
270 // friction velocity computed from k and U at sampling point
273 // Calculate yPlus for IB point
275 scalar yPlusIB = yPlusSample*y[ibCellI]/ySample[ibCellI];
277 // Calculate wall function data in the immersed boundary point
278 if (yPlusIB > yPlusLam)
280 // Logarithmic region
283 // turbulent viscosity at IB cell and at wall
284 scalar nutw = nuLam*(yPlusIB*kappa_/log(E_*yPlusIB) - 1);
286 // Fix generation even though it if is not used
288 sqr((nutw + nuLam)*magGradUw[ibCellI])/
289 (Cmu25*sqrt(k[ibCellI])*kappa_*y[ibCellI]);
291 // Compute k at the IB cell
292 kNew[ibCellI] = tauW/Cmu50; // equilibrium boundary layer
293 // kNew[ibCellI] = k[ibCellI]; // zero-Gradient (less stable)
295 // Compute omega at the IB cell
296 omegaNew[ibCellI] = sqrt(kNew[ibCellI])/(Cmu25*kappa_*y[ibCellI]);
298 // Log-Law for tangential velocity - uTau = Cmu25*sqrt(kNew)
299 UTangentialNew[ibCellI] = uTau/kappa_*log(E_*yPlusIB);
301 // Calculate turbulent viscosity
302 nutNew[ibCellI] = nutw;
309 // G is zero - immaterial!
310 // G[ibc[ibCellI]] = 0;
313 kNew[ibCellI] = k[ibCellI]*sqr(yPlusIB/yPlusLam);
315 // Compute omega at the IB cell
316 omegaNew[ibCellI] = 6.0*nu[ibCellI]/(beta1_*sqr(y[ibCellI]));
318 // Laminar sub-layer for tangential velocity: uPlus = yPlus
319 UTangentialNew[ibCellI] = uTau*yPlusIB;
321 // Turbulent viscosity is zero
322 nutNew[ibCellI] = SMALL;
327 // Info<< "UTangentialNew " << min(UTangentialNew) << " " << max(UTangentialNew) << endl;
328 // Info<< "nutNew " << min(nutNew) << " " << max(nutNew) << endl;
329 // Info<< "kNew " << min(kNew) << " " << max(kNew) << endl;
330 // Info<< "epsilonNew " << min(epsilonNew) << " " << max(epsilonNew) << endl;
332 // Set the fields to calculated wall function values
333 Uw.wallMask() = true;
335 nutw.wallMask() = true;
336 this->wallMask() = true;
338 // Insert epsilon values into the internal field
339 immersedBoundaryWallFunctionFvPatchScalarField::updateCoeffs();
343 void immersedBoundaryOmegaWallFunctionFvPatchScalarField::evaluate
345 const Pstream::commsTypes commsType
348 // Insert epsilon values into the internal field
349 this->setIbCellValues(this->wallValue());
351 fvPatchScalarField::evaluate(commsType);
355 void immersedBoundaryOmegaWallFunctionFvPatchScalarField::
356 write(Ostream& os) const
358 immersedBoundaryWallFunctionFvPatchScalarField::write(os);
359 writeEntryIfDifferent<word>(os, "U", "U", UName_);
360 writeEntryIfDifferent<word>(os, "k", "k", kName_);
361 writeEntryIfDifferent<word>(os, "G", "RASModel::G", GName_);
362 writeEntryIfDifferent<word>(os, "nu", "nu", nuName_);
363 writeEntryIfDifferent<word>(os, "nut", "nut", nutName_);
364 os.writeKeyword("Cmu") << Cmu_ << token::END_STATEMENT << nl;
365 os.writeKeyword("kappa") << kappa_ << token::END_STATEMENT << nl;
366 os.writeKeyword("E") << E_ << token::END_STATEMENT << nl;
367 os.writeKeyword("beta1") << beta1_ << token::END_STATEMENT << nl;
371 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
376 immersedBoundaryOmegaWallFunctionFvPatchScalarField
379 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
381 } // End namespace RASModels
382 } // End namespace incompressible
383 } // End namespace Foam
385 // ************************************************************************* //