FSD.C
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) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2019 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 \*---------------------------------------------------------------------------*/
28 
29 #include "FSD.H"
31 #include "LESModel.H"
32 #include "fvcGrad.H"
33 #include "fvcDiv.H"
34 
35 namespace Foam
36 {
37 namespace combustionModels
38 {
39 
40 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
41 
42 template<class ReactionThermo, class ThermoType>
44 (
45  const word& modelType,
46  ReactionThermo& thermo,
48  const word& combustionProperties
49 )
50 :
52  (
53  modelType,
54  thermo,
55  turb,
56  combustionProperties
57  ),
58  reactionRateFlameArea_
59  (
61  (
62  this->coeffs(),
63  this->mesh(),
64  *this
65  )
66  ),
67  ft_
68  (
69  IOobject
70  (
71  this->thermo().phasePropertyName("ft"),
72  this->mesh().time().timeName(),
73  this->mesh(),
77  ),
78  this->mesh(),
80  ),
81  YFuelFuelStream_(dimensionedScalar("YFuelStream", dimless, 1.0)),
82  YO2OxiStream_(dimensionedScalar("YOxiStream", dimless, 0.23)),
83  Cv_(this->coeffs().getScalar("Cv")),
84  C_(5.0),
85  ftMin_(0.0),
86  ftMax_(1.0),
87  ftDim_(300),
88  ftVarMin_(this->coeffs().getScalar("ftVarMin"))
89 {}
90 
91 
92 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
93 
94 template<class ReactionThermo, class ThermoType>
96 {}
97 
98 
99 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
100 
101 template<class ReactionThermo, class ThermoType>
102 void FSD<ReactionThermo, ThermoType>::calculateSourceNorm()
103 {
104  this->singleMixturePtr_->fresCorrect();
105 
106  const label fuelI = this->singleMixturePtr_->fuelIndex();
107 
108  const volScalarField& YFuel = this->thermo().composition().Y()[fuelI];
109 
110  const volScalarField& YO2 = this->thermo().composition().Y("O2");
111 
112  const dimensionedScalar s = this->singleMixturePtr_->s();
113 
114  ft_ =
115  (s*YFuel - (YO2 - YO2OxiStream_))/(s*YFuelFuelStream_ + YO2OxiStream_);
116 
117 
118  volVectorField nft(fvc::grad(ft_));
119 
120  volScalarField mgft(mag(nft));
121 
122  surfaceVectorField SfHat(this->mesh().Sf()/this->mesh().magSf());
123 
124  volScalarField cAux(scalar(1) - ft_);
125 
126  dimensionedScalar dMgft = 1.0e-3*
127  (ft_*cAux*mgft)().weightedAverage(this->mesh().V())
128  /((ft_*cAux)().weightedAverage(this->mesh().V()) + SMALL)
129  + dimensionedScalar("ddMgft", mgft.dimensions(), SMALL);
130 
131  mgft += dMgft;
132 
133  nft /= mgft;
134 
135  const volVectorField& U = YO2.db().lookupObject<volVectorField>("U");
136 
137  const volScalarField sigma
138  (
139  (nft & nft)*fvc::div(U) - (nft & fvc::grad(U) & nft)
140  );
141 
142  reactionRateFlameArea_->correct(sigma);
143 
144  const volScalarField& omegaFuel = reactionRateFlameArea_->omega();
145 
146 
147  const scalar ftStoich =
148  YO2OxiStream_.value()
149  /(
150  s.value()*YFuelFuelStream_.value() + YO2OxiStream_.value()
151  );
152 
153  auto tPc = volScalarField::New
154  (
155  this->thermo().phasePropertyName("Pc"),
157  U.mesh(),
159  );
160  auto& pc = tPc.ref();
161 
162  auto tomegaFuel = volScalarField::New
163  (
164  this->thermo().phasePropertyName("omegaFuelBar"),
166  U.mesh(),
167  dimensionedScalar(omegaFuel.dimensions(), Zero)
168  );
169  auto& omegaFuelBar = tomegaFuel.ref();
170 
171  // Calculation of the mixture fraction variance (ftVar)
172  const compressible::LESModel& lesModel =
174  (
176  );
177 
178  const volScalarField& delta = lesModel.delta();
179  const volScalarField ftVar(Cv_*sqr(delta)*sqr(mgft));
180 
181  // Thickened flame (average flame thickness for counterflow configuration
182  // is 1.5 mm)
183 
184  volScalarField deltaF
185  (
186  delta/dimensionedScalar("flame", dimLength, 1.5e-3)
187  );
188 
189  // Linear correlation between delta and flame thickness
190  volScalarField omegaF(max(deltaF*(4.0/3.0) + (2.0/3.0), scalar(1)));
191 
192  scalar deltaFt = 1.0/ftDim_;
193 
194  forAll(ft_, celli)
195  {
196  if (ft_[celli] > ftMin_ && ft_[celli] < ftMax_)
197  {
198  scalar ftCell = ft_[celli];
199 
200  if (ftVar[celli] > ftVarMin_) //sub-grid beta pdf of ft_
201  {
202  scalar ftVarc = ftVar[celli];
203  scalar a =
204  max(ftCell*(ftCell*(1.0 - ftCell)/ftVarc - 1.0), 0.0);
205  scalar b = max(a/ftCell - a, 0.0);
206 
207  for (int i=1; i<ftDim_; i++)
208  {
209  scalar ft = i*deltaFt;
210  pc[celli] += pow(ft, a-1.0)*pow(1.0 - ft, b - 1.0)*deltaFt;
211  }
212 
213  for (int i=1; i<ftDim_; i++)
214  {
215  scalar ft = i*deltaFt;
216  omegaFuelBar[celli] +=
217  omegaFuel[celli]/omegaF[celli]
218  *exp
219  (
220  -sqr(ft - ftStoich)
221  /(2.0*sqr(0.01*omegaF[celli]))
222  )
223  *pow(ft, a - 1.0)
224  *pow(1.0 - ft, b - 1.0)
225  *deltaFt;
226  }
227  omegaFuelBar[celli] /= max(pc[celli], 1e-4);
228  }
229  else
230  {
231  omegaFuelBar[celli] =
232  omegaFuel[celli]/omegaF[celli]
233  *exp(-sqr(ftCell - ftStoich)/(2.0*sqr(0.01*omegaF[celli])));
234  }
235  }
236  else
237  {
238  omegaFuelBar[celli] = 0.0;
239  }
240  }
241 
242 
243  // Combustion progress variable, c
244 
245  List<label> productsIndex(2, label(-1));
246  {
247  label i = 0;
248  forAll(this->singleMixturePtr_->specieProd(), specieI)
249  {
250  if (this->singleMixturePtr_->specieProd()[specieI] < 0)
251  {
252  productsIndex[i] = specieI;
253  i++;
254  }
255  }
256  }
257 
258 
259  // Flamelet probability of the progress c based on IFC (reuse pc)
260  scalar YprodTotal = 0;
261  forAll(productsIndex, j)
262  {
263  YprodTotal += this->singleMixturePtr_->Yprod0()[productsIndex[j]];
264  }
265 
266  forAll(ft_, celli)
267  {
268  if (ft_[celli] < ftStoich)
269  {
270  pc[celli] = ft_[celli]*(YprodTotal/ftStoich);
271  }
272  else
273  {
274  pc[celli] = (1.0 - ft_[celli])*(YprodTotal/(1.0 - ftStoich));
275  }
276  }
277 
278  auto tproducts = volScalarField::New
279  (
280  this->thermo().phasePropertyName("products"),
282  U.mesh(),
284  );
285  auto& products = tproducts.ref();
286 
287  forAll(productsIndex, j)
288  {
289  label specieI = productsIndex[j];
290  const volScalarField& Yp = this->thermo().composition().Y()[specieI];
291  products += Yp;
292  }
293 
295  (
296  max(scalar(1) - products/max(pc, scalar(1e-5)), scalar(0))
297  );
298 
299  pc = min(C_*c, scalar(1));
300 
301  const volScalarField fres(this->singleMixturePtr_->fres(fuelI));
302 
303  this->wFuel_ == mgft*pc*omegaFuelBar;
304 }
305 
306 
307 template<class ReactionThermo, class ThermoType>
309 {
310  this->wFuel_ == dimensionedScalar(dimMass/dimTime/dimVolume, Zero);
311 
312  if (this->active())
313  {
314  calculateSourceNorm();
315  }
316 }
317 
318 
319 template<class ReactionThermo, class ThermoType>
321 {
323  {
324  this->coeffs().readEntry("Cv", Cv_);
325  this->coeffs().readEntry("ftVarMin", ftVarMin_);
326  reactionRateFlameArea_->read(this->coeffs());
327  return true;
328  }
329 
330  return false;
331 }
332 
333 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
334 
335 } // End namespace combustionModels
336 } // End namespace Foam
337 
338 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
scalar delta
Flame Surface Dennsity (FDS) combustion model.
Definition: FSD.H:81
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh >> grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcGrad.C:47
const Type & lookupObject(const word &name, const bool recursive=false) const
Lookup and return const reference to the object of the given Type. Fatal if not found or the wrong ty...
virtual bool read()
Update properties.
Definition: FSD.C:313
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
dimensionedSymmTensor sqr(const dimensionedVector &dv)
tmp< GeometricField< Type, fvPatchField, volMesh > > div(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcDiv.C:42
compressible::turbulenceModel & turb
const dimensionSet dimless
Dimensionless.
dimensionedScalar sigma("sigma", dimMass/sqr(dimTime), transportProperties)
Macros for easy insertion into run-time selection tables.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:72
psiReactionThermo & thermo
Definition: createFields.H:28
word timeName
Definition: getTimeIndex.H:3
const dimensionSet dimVolume(pow3(dimLength))
Definition: dimensionSets.H:58
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
dynamicFvMesh & mesh
dimensionedScalar exp(const dimensionedScalar &ds)
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:27
Calculate the gradient of the given field.
static const word propertiesName
Default name of the turbulence properties dictionary.
A class for handling words, derived from Foam::string.
Definition: word.H:63
LESModel< EddyDiffusivity< turbulenceModel > > LESModel
Typedefs for turbulence, RAS and LES models for compressible flow based on the standard laminar trans...
const objectRegistry & db() const noexcept
Return the local objectRegistry.
Definition: IOobject.C:450
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
Basic thermodynamics type based on the use of fitting functions for cp, h, s obtained from the templa...
static tmp< GeometricField< scalar, fvPatchField, volMesh > > New(const word &name, IOobjectOption::registerOption regOpt, const Mesh &mesh, const dimensionSet &dims, const word &patchFieldType=fvPatchField< scalar >::calculatedType())
Return tmp field (NO_READ, NO_WRITE) from name, mesh, dimensions and patch type. [Takes current timeN...
Calculate the divergence of the given field.
Abstract base class for turbulence models (RAS, LES and laminar).
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
virtual bool read()
Update properties from given dictionary.
U
Definition: pEqn.H:72
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:50
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
const dimensionedScalar c
Speed of light in a vacuum.
Nothing to be read.
Automatically write from objectRegistry::writeObject()
virtual void correct()
Correct combustion rate.
Definition: FSD.C:301
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
Definition: dimensionSets.H:51
Base class for combustion models using singleStepReactingMixture.
const dimensionSet dimMass(1, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:49
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:180
Request registration (bool: true)
Do not request registration (bool: false)
static autoPtr< reactionRateFlameArea > New(const dictionary &dict, const fvMesh &mesh, const combustionModel &combModel)
virtual ~FSD()
Destructor.
Definition: FSD.C:88
Namespace for OpenFOAM.
const dimensionSet & dimensions() const noexcept
Return dimensions.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127