DEShybrid.H
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) 2015 OpenFOAM Foundation
9  Copyright (C) 2015-2021 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 Class
28  Foam::DEShybrid
29 
30 Description
31  Hybrid convection scheme of Travin et al. for hybrid RAS/LES calculations.
32 
33  The scheme provides a blend between two convection schemes, based on local
34  properties including the wall distance, velocity gradient and eddy
35  viscosity. The scheme was originally developed for DES calculations to
36  blend a low-dissipative scheme, e.g. linear, in the vorticity-dominated,
37  finely-resolved regions and a numerically more robust, e.g. upwind-biased,
38  convection scheme in irrotational or coarsely-resolved regions.
39 
40  The routine calculates the blending factor denoted as "sigma" in the
41  literature reference, where 0 <= sigma <= sigmaMax, which is then employed
42  to set the weights:
43  \f[
44  weight = (1-sigma) w_1 + sigma w_2
45  \f]
46 
47  where
48  \vartable
49  sigma | blending factor
50  w_1 | scheme 1 weights
51  w_2 | scheme 2 weights
52  \endvartable
53 
54  First published in:
55  \verbatim
56  A. Travin, M. Shur, M. Strelets, P. Spalart (2000).
57  Physical and numerical upgrades in the detached-eddy simulation of
58  complex turbulent flows.
59  In Proceedings of the 412th Euromech Colloquium on LES and Complex
60  Transition and Turbulent Flows, Munich, Germany
61  \endverbatim
62 
63  Original publication contained a typo for C_H3 constant. Corrected version
64  with minor changes for 2 lower limiters published in:
65  \verbatim
66  P. Spalart, M. Shur, M. Strelets, A. Travin (2012).
67  Sensitivity of Landing-Gear Noise Predictions by Large-Eddy
68  Simulation to Numerics and Resolution.
69  AIAA Paper 2012-1174, 50th AIAA Aerospace Sciences Meeting,
70  Nashville / TN, Jan. 2012
71  \endverbatim
72 
73  Example of the DEShybrid scheme specification using linear within the LES
74  region and linearUpwind within the RAS region:
75  \verbatim
76  divSchemes
77  {
78  .
79  .
80  div(phi,U) Gauss DEShybrid
81  linear // scheme 1
82  linearUpwind grad(U) // scheme 2
83  hmax // LES delta name, e.g. 'delta', 'hmax'
84  0.65 // DES coefficient, typically = 0.65
85  30 // Reference velocity scale
86  2 // Reference length scale
87  0 // Minimum sigma limit (0-1)
88  1 // Maximum sigma limit (0-1)
89  1.0e-03; // Limiter of B function, typically 1e-03
90  .
91  .
92  }
93  \endverbatim
94 
95 Notes
96  - Scheme 1 should be linear (or other low-dissipative schemes) which will
97  be used in the detached/vortex shedding regions.
98  - Scheme 2 should be an upwind/deferred correction/TVD scheme which will
99  be used in the free-stream/Euler/boundary layer regions.
100  - the scheme is compiled into a separate library, and not available to
101  solvers by default. In order to use the scheme, add the library as a
102  run-time loaded library in the \$FOAM\_CASE/system/controlDict
103  dictionary, e.g.:
104  \verbatim
105  libs ("libturbulenceModelSchemes.so");
106  \endverbatim
107 
108 SourceFiles
109  DEShybrid.C
110 
111 \*---------------------------------------------------------------------------*/
112 
113 #ifndef DEShybrid_H
114 #define DEShybrid_H
115 
117 #include "surfaceInterpolate.H"
118 #include "fvcGrad.H"
119 #include "blendedSchemeBase.H"
120 #include "turbulentTransportModel.H"
122 
123 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
124 
125 namespace Foam
126 {
127 
128 /*---------------------------------------------------------------------------*\
129  Class DEShybrid Declaration
130 \*---------------------------------------------------------------------------*/
131 
132 template<class Type>
133 class DEShybrid
134 :
135  public surfaceInterpolationScheme<Type>,
136  public blendedSchemeBase<Type>
137 {
138  // Private Data
139 
140  //- Scheme 1
141  tmp<surfaceInterpolationScheme<Type>> tScheme1_;
142 
143  //- Scheme 2
145 
146  //- Name of the LES delta field
147  word deltaName_;
148 
149  //- DES Coefficient
150  scalar CDES_;
151 
152  //- Reference velocity scale [m/s]
153  dimensionedScalar U0_;
154 
155  //- Reference length scale [m]
156  dimensionedScalar L0_;
157 
158  //- Minimum bound for sigma (0 <= sigmaMin <= 1)
159  scalar sigmaMin_;
160 
161  //- Maximum bound for sigma (0 <= sigmaMax <= 1)
162  scalar sigmaMax_;
163 
164  //- Limiter of B function
165  scalar OmegaLim_;
166 
167  //- Scheme constants
168  scalar CH1_;
169  scalar CH2_;
170  scalar CH3_;
171 
172  //- No copy construct
173  DEShybrid(const DEShybrid&) = delete;
174 
175  //- No copy assignment
176  void operator=(const DEShybrid&) = delete;
177 
178 
179  // Private Member Functions
180 
181  //- Calculate the blending factor
182  tmp<surfaceScalarField> calcBlendingFactor
183  (
185  const volScalarField& nuEff,
186  const volVectorField& U,
187  const volScalarField& delta
188  ) const
189  {
191  const volScalarField S(sqrt(2.0)*mag(symm(gradU())));
192  const volScalarField Omega(sqrt(2.0)*mag(skew(gradU())));
193  const dimensionedScalar tau0_ = L0_/U0_;
194 
195  const volScalarField B
196  (
197  CH3_*Omega*max(S, Omega)
198  /max(0.5*(sqr(S) + sqr(Omega)), sqr(OmegaLim_/tau0_))
199  );
200 
201  const volScalarField K
202  (
203  max(Foam::sqrt(0.5*(sqr(S) + sqr(Omega))), 0.1/tau0_)
204  );
205 
206  const volScalarField lTurb
207  (
208  Foam::sqrt
209  (
210  max
211  (
212  nuEff/(pow(0.09, 1.5)*K),
213  dimensionedScalar("l0", sqr(dimLength), 0)
214  )
215  )
216  );
217 
218  const volScalarField g(tanh(pow4(B)));
219 
220  const volScalarField A
221  (
222  CH2_*max
223  (
224  scalar(0),
225  CDES_*delta/max(lTurb*g, SMALL*L0_) - 0.5
226  )
227  );
228 
229  const volScalarField factor
230  (
231  IOobject
232  (
233  typeName + ":Factor",
234  this->mesh().time().timeName(),
235  this->mesh(),
238  ),
239  max(sigmaMax_*tanh(pow(A, CH1_)), sigmaMin_)
240  );
241 
243  {
244  factor.write();
245  }
246 
248  (
250  (
251  vf.name() + "BlendingFactor",
252  fvc::interpolate(factor)
253  )
254  );
255  }
256 
257 
258 public:
259 
260  //- Runtime type information
261  TypeName("DEShybrid");
262 
263 
264  // Constructors
265 
266  //- Construct from mesh and Istream.
267  // The name of the flux field is read from the Istream and looked-up
268  // from the mesh objectRegistry
269  DEShybrid(const fvMesh& mesh, Istream& is)
270  :
272  tScheme1_
273  (
275  ),
276  tScheme2_
277  (
279  ),
280  deltaName_(is),
281  CDES_(readScalar(is)),
282  U0_("U0", dimLength/dimTime, readScalar(is)),
283  L0_("L0", dimLength, readScalar(is)),
284  sigmaMin_(readScalar(is)),
285  sigmaMax_(readScalar(is)),
286  OmegaLim_(readScalar(is)),
287  CH1_(3.0),
288  CH2_(1.0),
289  CH3_(2.0)
290  {
291  if (U0_.value() <= 0)
292  {
294  << "U0 coefficient must be > 0. "
295  << "Current value: " << U0_ << exit(FatalError);
296  }
297  if (L0_.value() <= 0)
298  {
300  << "L0 coefficient must be > 0. "
301  << "Current value: " << L0_ << exit(FatalError);
302  }
303  if (sigmaMin_ < 0)
304  {
306  << "sigmaMin coefficient must be >= 0. "
307  << "Current value: " << sigmaMin_ << exit(FatalError);
308  }
309  if (sigmaMax_ < 0)
310  {
312  << "sigmaMax coefficient must be >= 0. "
313  << "Current value: " << sigmaMax_ << exit(FatalError);
314  }
315  if (sigmaMin_ > 1)
316  {
318  << "sigmaMin coefficient must be <= 1. "
319  << "Current value: " << sigmaMin_ << exit(FatalError);
320  }
321  if (sigmaMax_ > 1)
322  {
324  << "sigmaMax coefficient must be <= 1. "
325  << "Current value: " << sigmaMax_ << exit(FatalError);
326  }
327  }
328 
329  //- Construct from mesh, faceFlux and Istream
330  DEShybrid
331  (
332  const fvMesh& mesh,
333  const surfaceScalarField& faceFlux,
334  Istream& is
335  )
336  :
338  tScheme1_
339  (
340  surfaceInterpolationScheme<Type>::New(mesh, faceFlux, is)
341  ),
342  tScheme2_
343  (
344  surfaceInterpolationScheme<Type>::New(mesh, faceFlux, is)
345  ),
346  deltaName_(is),
347  CDES_(readScalar(is)),
348  U0_("U0", dimLength/dimTime, readScalar(is)),
349  L0_("L0", dimLength, readScalar(is)),
350  sigmaMin_(readScalar(is)),
351  sigmaMax_(readScalar(is)),
352  OmegaLim_(readScalar(is)),
353  CH1_(3.0),
354  CH2_(1.0),
355  CH3_(2.0)
356  {
357  if (U0_.value() <= 0)
358  {
360  << "U0 coefficient must be > 0. "
361  << "Current value: " << U0_ << exit(FatalError);
362  }
363  if (L0_.value() <= 0)
364  {
366  << "L0 coefficient must be > 0. "
367  << "Current value: " << U0_ << exit(FatalError);
368  }
369  if (sigmaMin_ < 0)
370  {
372  << "sigmaMin coefficient must be >= 0. "
373  << "Current value: " << sigmaMin_ << exit(FatalError);
374  }
375  if (sigmaMax_ < 0)
376  {
378  << "sigmaMax coefficient must be >= 0. "
379  << "Current value: " << sigmaMax_ << exit(FatalError);
380  }
381  if (sigmaMin_ > 1)
382  {
384  << "sigmaMin coefficient must be <= 1. "
385  << "Current value: " << sigmaMin_ << exit(FatalError);
386  }
387  if (sigmaMax_ > 1)
388  {
390  << "sigmaMax coefficient must be <= 1. "
391  << "Current value: " << sigmaMax_ << exit(FatalError);
392  }
393  }
394 
395 
396  // Member Functions
397 
398  //- Return the face-based blending factor
400  (
402  ) const
403  {
404  const fvMesh& mesh = this->mesh();
405 
406  typedef compressible::turbulenceModel cmpModel;
407  typedef incompressible::turbulenceModel icoModel;
408 
409  // Lookup the LES delta from the mesh database
410  const volScalarField& delta = this->mesh().template
411  lookupObject<const volScalarField>(deltaName_);
412 
413  // Could avoid the compressible/incompressible case by looking
414  // up all fields from the database - but retrieving from model
415  // ensures consistent fields are being employed e.g. for multiphase
416  // where group name is used
417 
418  if (mesh.foundObject<icoModel>(icoModel::propertiesName))
419  {
420  const icoModel& model =
421  mesh.lookupObject<icoModel>(icoModel::propertiesName);
422 
423  return calcBlendingFactor(vf, model.nuEff(), model.U(), delta);
424  }
425  else if (mesh.foundObject<cmpModel>(cmpModel::propertiesName))
426  {
427  const cmpModel& model =
428  mesh.lookupObject<cmpModel>(cmpModel::propertiesName);
429 
430  return calcBlendingFactor
431  (
432  vf, model.muEff()/model.rho(), model.U(), delta
433  );
434  }
435 
437  << "Scheme requires a turbulence model to be present. "
438  << "Unable to retrieve turbulence model from the mesh "
439  << "database" << exit(FatalError);
440 
441  return nullptr;
442  }
443 
444 
445  //- Return the interpolation weighting factors
446  tmp<surfaceScalarField> weights
447  (
448  const GeometricField<Type, fvPatchField, volMesh>& vf
449  ) const
450  {
452 
453  return
454  (scalar(1) - bf)*tScheme1_().weights(vf)
455  + bf*tScheme2_().weights(vf);
456  }
457 
458 
459  //- Return the face-interpolate of the given cell field
460  // with explicit correction
463  (
465  ) const
466  {
468 
469  return
470  (scalar(1) - bf)*tScheme1_().interpolate(vf)
471  + bf*tScheme2_().interpolate(vf);
472  }
473 
474 
475  //- Return true if this scheme uses an explicit correction
476  virtual bool corrected() const
477  {
478  return tScheme1_().corrected() || tScheme2_().corrected();
479  }
480 
481 
482  //- Return the explicit correction to the face-interpolate
483  // for the given field
485  correction
486  (
488  ) const
489  {
491 
492  if (tScheme1_().corrected())
493  {
494  if (tScheme2_().corrected())
495  {
496  return
497  (
498  (scalar(1) - bf)
499  * tScheme1_().correction(vf)
500  + bf
501  * tScheme2_().correction(vf)
502  );
503  }
504  else
505  {
506  return
507  (
508  (scalar(1) - bf)
509  * tScheme1_().correction(vf)
510  );
511  }
512  }
513  else if (tScheme2_().corrected())
514  {
515  return (bf*tScheme2_().correction(vf));
516  }
517 
518  return nullptr;
519  }
520 };
521 
522 
523 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
524 
525 } // End namespace Foam
526 
527 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
528 
529 #endif
530 
531 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::IOobject::NO_WRITE
Definition: IOobject.H:195
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
Foam::surfaceInterpolationScheme::New
static tmp< surfaceInterpolationScheme< Type > > New(const fvMesh &mesh, Istream &schemeData)
Return new tmp interpolation scheme.
Definition: surfaceInterpolationScheme.C:40
Foam::symm
dimensionedSymmTensor symm(const dimensionedSymmTensor &dt)
Definition: dimensionedSymmTensor.C:84
Foam::fvc::grad
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh >> grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcGrad.C:54
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
blendedSchemeBase.H
Foam::skew
dimensionedTensor skew(const dimensionedTensor &dt)
Definition: dimensionedTensor.C:138
Foam::dimLength
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:52
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
turbulentTransportModel.H
B
static const Foam::dimensionedScalar B("", Foam::dimless, 18.678)
A
static const Foam::dimensionedScalar A("", Foam::dimPressure, 611.21)
Foam::dimensioned::value
const Type & value() const
Return const reference to value.
Definition: dimensionedType.C:434
Foam::objectRegistry::foundObject
bool foundObject(const word &name, const bool recursive=false) const
Is the named Type found?
Definition: objectRegistryTemplates.C:379
K
CGAL::Exact_predicates_exact_constructions_kernel K
Definition: CGALTriangulation3DKernel.H:58
Foam::dimTime
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
Definition: dimensionSets.H:53
Foam::pow4
dimensionedScalar pow4(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:100
Foam::tanh
dimensionedScalar tanh(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:272
Foam::Istream
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:61
delta
scalar delta
Definition: LISASMDCalcMethod2.H:8
Foam::dimensionedScalar
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Definition: dimensionedScalarFwd.H:42
Foam::objectRegistry::lookupObject
const Type & lookupObject(const word &name, const bool recursive=false) const
Definition: objectRegistryTemplates.C:434
Foam::pow
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
Definition: dimensionedScalar.C:75
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
timeName
word timeName
Definition: getTimeIndex.H:3
Foam::FatalError
error FatalError
Foam::DEShybrid::blendingFactor
virtual tmp< surfaceScalarField > blendingFactor(const GeometricField< Type, fvPatchField, volMesh > &vf) const
Return the face-based blending factor.
Definition: DEShybrid.H:411
Foam::dimensioned< scalar >
Foam::DEShybrid::correction
virtual tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > correction(const GeometricField< Type, fvPatchField, volMesh > &vf) const
Return the explicit correction to the face-interpolate.
Definition: DEShybrid.H:497
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:85
Foam::DEShybrid::corrected
virtual bool corrected() const
Return true if this scheme uses an explicit correction.
Definition: DEShybrid.H:487
g
const uniformDimensionedVectorField & g
Definition: createFluidFields.H:26
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::fvc::interpolate
static tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > interpolate(const GeometricField< Type, fvPatchField, volMesh > &tvf, const surfaceScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
U
U
Definition: pEqn.H:72
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:51
Foam::surfaceScalarField
GeometricField< scalar, fvsPatchField, surfaceMesh > surfaceScalarField
Definition: surfaceFieldsFwd.H:54
Foam::DEShybrid::interpolate
tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > interpolate(const GeometricField< Type, fvPatchField, volMesh > &vf) const
Return the face-interpolate of the given cell field.
Definition: DEShybrid.H:474
Foam::ThermalDiffusivity
Templated wrapper class to provide compressible turbulence models thermal diffusivity based thermal t...
Definition: phaseCompressibleTurbulenceModelFwd.H:47
Foam::sqrt
dimensionedScalar sqrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:144
fvcGrad.H
Calculate the gradient of the given field.
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::surfaceInterpolationScheme
Abstract base class for surface interpolation schemes.
Definition: surfaceInterpolationScheme.H:57
Foam::DEShybrid::weights
tmp< surfaceScalarField > weights(const GeometricField< Type, fvPatchField, volMesh > &vf) const
Return the interpolation weighting factors.
Definition: DEShybrid.H:458
Foam::DEShybrid
Hybrid convection scheme of Travin et al. for hybrid RAS/LES calculations.
Definition: DEShybrid.H:144
Foam::IncompressibleTurbulenceModel
Templated abstract base class for single-phase incompressible turbulence models.
Definition: IncompressibleTurbulenceModel.H:55
Foam::surfaceInterpolationScheme::mesh
const fvMesh & mesh() const
Return mesh reference.
Definition: surfaceInterpolationScheme.H:144
Foam::GeometricField< Type, fvPatchField, volMesh >
Foam::IOobject::NO_READ
Definition: IOobject.H:188
Foam::blendedSchemeBase
Base class for blended schemes to provide access to the blending factor surface field.
Definition: blendedSchemeBase.H:55
turbulentFluidThermoModel.H
surfaceInterpolationScheme.H
Foam::DEShybrid::TypeName
TypeName("DEShybrid")
Runtime type information.