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 | Copyright (C) 2011-2015 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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
19  for more details.
20 
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/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "FSD.H"
28 #include "LESModel.H"
29 #include "fvcGrad.H"
30 #include "fvcDiv.H"
31 
32 namespace Foam
33 {
34 namespace combustionModels
35 {
36 
37 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
38 
39 template<class CombThermoType, class ThermoType>
41 (
42  const word& modelType,
43  const fvMesh& mesh,
44  const word& phaseName
45 )
46 :
48  (
49  modelType,
50  mesh,
51  phaseName
52  ),
53  reactionRateFlameArea_
54  (
56  (
57  this->coeffs(),
58  this->mesh(),
59  *this
60  )
61  ),
62  ft_
63  (
64  IOobject
65  (
66  IOobject::groupName("ft", phaseName),
67  this->mesh().time().timeName(),
68  this->mesh(),
71  ),
72  this->mesh(),
73  dimensionedScalar("zero", dimless, 0.0)
74  ),
75  YFuelFuelStream_(dimensionedScalar("YFuelStream", dimless, 1.0)),
76  YO2OxiStream_(dimensionedScalar("YOxiStream", dimless, 0.23)),
77  Cv_(readScalar(this->coeffs().lookup("Cv"))),
78  C_(5.0),
79  ftMin_(0.0),
80  ftMax_(1.0),
81  ftDim_(300),
82  ftVarMin_(readScalar(this->coeffs().lookup("ftVarMin")))
83 {}
84 
85 
86 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
87 
88 template<class CombThermoType, class ThermoType>
90 {}
91 
92 
93 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
94 
95 template<class CombThermoType, class ThermoType>
97 {
98  this->singleMixturePtr_->fresCorrect();
99 
100  const label fuelI = this->singleMixturePtr_->fuelIndex();
101 
102  const volScalarField& YFuel = this->thermoPtr_->composition().Y()[fuelI];
103 
104  const volScalarField& YO2 = this->thermoPtr_->composition().Y("O2");
105 
106  const dimensionedScalar s = this->singleMixturePtr_->s();
107 
108  ft_ =
109  (s*YFuel - (YO2 - YO2OxiStream_))/(s*YFuelFuelStream_ + YO2OxiStream_);
110 
111 
112  volVectorField nft(fvc::grad(ft_));
113 
114  volScalarField mgft(mag(nft));
115 
116  surfaceVectorField SfHat(this->mesh().Sf()/this->mesh().magSf());
117 
118  volScalarField cAux(scalar(1) - ft_);
119 
120  dimensionedScalar dMgft = 1.0e-3*
121  (ft_*cAux*mgft)().weightedAverage(this->mesh().V())
122  /((ft_*cAux)().weightedAverage(this->mesh().V()) + SMALL)
123  + dimensionedScalar("ddMgft", mgft.dimensions(), SMALL);
124 
125  mgft += dMgft;
126 
127  nft /= mgft;
128 
129  const volVectorField& U = YO2.db().lookupObject<volVectorField>("U");
130 
131  const volScalarField sigma
132  (
133  (nft & nft)*fvc::div(U) - (nft & fvc::grad(U) & nft)
134  );
135 
136  reactionRateFlameArea_->correct(sigma);
137 
138  const volScalarField& omegaFuel = reactionRateFlameArea_->omega();
139 
140 
141  const scalar ftStoich =
142  YO2OxiStream_.value()
143  /(
144  s.value()*YFuelFuelStream_.value() + YO2OxiStream_.value()
145  );
146 
148  (
149  new volScalarField
150  (
151  IOobject
152  (
153  IOobject::groupName("Pc", this->phaseName_),
154  U.time().timeName(),
155  U.db(),
158  ),
159  U.mesh(),
160  dimensionedScalar("Pc", dimless, 0)
161  )
162  );
163 
164  volScalarField& pc = tPc();
165 
166  tmp<volScalarField> tomegaFuel
167  (
168  new volScalarField
169  (
170  IOobject
171  (
172  IOobject::groupName("omegaFuelBar", this->phaseName_),
173  U.time().timeName(),
174  U.db(),
177  ),
178  U.mesh(),
180  (
181  "omegaFuelBar",
182  omegaFuel.dimensions(),
183  0
184  )
185  )
186  );
187 
188  volScalarField& omegaFuelBar = tomegaFuel();
189 
190  // Calculation of the mixture fraction variance (ftVar)
191  // TODO: generalize delta for RAS and LES.
192  const volScalarField& delta =
193  refCast<const compressible::LESModel>(this->turbulence()).delta();
194 
195  const volScalarField ftVar(Cv_*sqr(delta)*sqr(mgft));
196 
197  // Thickened flame (average flame thickness for counterflow configuration
198  // is 1.5 mm)
199  volScalarField deltaF
200  (
201  delta/dimensionedScalar("flame", dimLength, 1.5e-3)
202  );
203 
204  // Linear correlation between delta and flame thickness
205  volScalarField omegaF(max(deltaF*(4.0/3.0) + (2.0/3.0), scalar(1)));
206 
207  scalar deltaFt = 1.0/ftDim_;
208 
209  forAll(ft_, cellI)
210  {
211  if (ft_[cellI] > ftMin_ && ft_[cellI] < ftMax_)
212  {
213  scalar ftCell = ft_[cellI];
214 
215  if (ftVar[cellI] > ftVarMin_) //sub-grid beta pdf of ft_
216  {
217  scalar ftVarc = ftVar[cellI];
218  scalar a =
219  max(ftCell*(ftCell*(1.0 - ftCell)/ftVarc - 1.0), 0.0);
220  scalar b = max(a/ftCell - a, 0.0);
221 
222  for (int i=1; i<ftDim_; i++)
223  {
224  scalar ft = i*deltaFt;
225  pc[cellI] += pow(ft, a-1.0)*pow(1.0 - ft, b - 1.0)*deltaFt;
226  }
227 
228  for (int i=1; i<ftDim_; i++)
229  {
230  scalar ft = i*deltaFt;
231  omegaFuelBar[cellI] +=
232  omegaFuel[cellI]/omegaF[cellI]
233  *exp
234  (
235  -sqr(ft - ftStoich)
236  /(2.0*sqr(0.01*omegaF[cellI]))
237  )
238  *pow(ft, a - 1.0)
239  *pow(1.0 - ft, b - 1.0)
240  *deltaFt;
241  }
242  omegaFuelBar[cellI] /= max(pc[cellI], 1e-4);
243  }
244  else
245  {
246  omegaFuelBar[cellI] =
247  omegaFuel[cellI]/omegaF[cellI]
248  *exp(-sqr(ftCell - ftStoich)/(2.0*sqr(0.01*omegaF[cellI])));
249  }
250  }
251  else
252  {
253  omegaFuelBar[cellI] = 0.0;
254  }
255  }
256 
257 
258  // Combustion progress variable, c
259 
260  List<label> productsIndex(2, label(-1));
261  {
262  label i = 0;
263  forAll(this->singleMixturePtr_->specieProd(), specieI)
264  {
265  if (this->singleMixturePtr_->specieProd()[specieI] < 0)
266  {
267  productsIndex[i] = specieI;
268  i++;
269  }
270  }
271  }
272 
273 
274  // Flamelet probability of the progress c based on IFC (reuse pc)
275  scalar YprodTotal = 0;
276  forAll(productsIndex, j)
277  {
278  YprodTotal += this->singleMixturePtr_->Yprod0()[productsIndex[j]];
279  }
280 
281  forAll(ft_, cellI)
282  {
283  if (ft_[cellI] < ftStoich)
284  {
285  pc[cellI] = ft_[cellI]*(YprodTotal/ftStoich);
286  }
287  else
288  {
289  pc[cellI] = (1.0 - ft_[cellI])*(YprodTotal/(1.0 - ftStoich));
290  }
291  }
292 
293  tmp<volScalarField> tproducts
294  (
295  new volScalarField
296  (
297  IOobject
298  (
299  IOobject::groupName("products", this->phaseName_),
300  U.time().timeName(),
301  U.db(),
304  ),
305  U.mesh(),
306  dimensionedScalar("products", dimless, 0)
307  )
308  );
309 
310  volScalarField& products = tproducts();
311 
312  forAll(productsIndex, j)
313  {
314  label specieI = productsIndex[j];
315  const volScalarField& Yp = this->thermoPtr_->composition().Y()[specieI];
316  products += Yp;
317  }
318 
320  (
321  max(scalar(1) - products/max(pc, scalar(1e-5)), scalar(0))
322  );
323 
324  pc = min(C_*c, scalar(1));
325 
326  const volScalarField fres(this->singleMixturePtr_->fres(fuelI));
327 
328  this->wFuel_ == mgft*pc*omegaFuelBar;
329 }
330 
331 
332 template<class CombThermoType, class ThermoType>
334 {
335  this->wFuel_ ==
337 
338  if (this->active())
339  {
340  calculateSourceNorm();
341  }
342 }
343 
344 
345 template<class CombThermoType, class ThermoType>
347 {
349  {
350  this->coeffs().lookup("Cv") >> Cv_ ;
351  this->coeffs().lookup("ftVarMin") >> ftVarMin_;
352  reactionRateFlameArea_->read(this->coeffs());
353  return true;
354  }
355  else
356  {
357  return false;
358  }
359 }
360 
361 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
362 
363 } // End namespace combustionModels
364 } // End namespace Foam
365 
366 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Foam::combustionModels::FSD::read
virtual bool read()
Update properties.
Definition: FSD.C:346
Foam::IOobject
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:91
Foam::IOobject::groupName
static word groupName(Name name, const word &group)
Foam::combustionModels::FSD::~FSD
virtual ~FSD()
Definition: FSD.C:89
Foam::dimless
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:47
Foam::fvc::grad
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh >> grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcGrad.C:52
Foam::word
A class for handling words, derived from string.
Definition: word.H:59
Foam::combustionModels::FSD::correct
virtual void correct()
Correct combustion rate.
Definition: FSD.C:333
Foam::IOobject::AUTO_WRITE
@ AUTO_WRITE
Definition: IOobject.H:117
Foam::dimLength
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:50
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:118
fvcDiv.H
Calculate the divergence of the given field.
Foam::fvc::div
tmp< GeometricField< Type, fvPatchField, volMesh > > div(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcDiv.C:47
Foam::exp
dimensionedScalar exp(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:252
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::IOobject::NO_WRITE
@ NO_WRITE
Definition: IOobject.H:118
U
U
Definition: pEqn.H:46
Foam::combustionModels::singleStepCombustion
Base class for combustion models using singleStepReactingMixture.
Definition: singleStepCombustion.H:51
Foam::dimTime
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
Definition: dimensionSets.H:51
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Foam::constant::physicoChemical::b
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:28
Foam::combustionModels::FSD::calculateSourceNorm
void calculateSourceNorm()
Calculate the normalised fuel source term.
Definition: FSD.C:96
turbulence
autoPtr< compressible::turbulenceModel > turbulence
Definition: createFields.H:23
Foam::pow3
dimensionedScalar pow3(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:87
Foam::IOobject::NO_READ
@ NO_READ
Definition: IOobject.H:111
delta
scalar delta
Definition: LISASMDCalcMethod2.H:8
LESModel.H
Foam::dimensionedScalar
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Definition: dimensionedScalarFwd.H:41
FSD.H
Foam::pow
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
Definition: dimensionedScalar.C:73
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:18
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam::dimensioned
Generic dimensioned Type class.
Definition: dimensionedScalarFwd.H:41
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::dimMass
const dimensionSet dimMass(1, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:49
Foam::e
const double e
Elementary charge.
Definition: doubleFloat.H:94
s
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().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))
Foam::max
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::combustionModels::FSD::FSD
FSD(const FSD &)
Disallow copy construct.
Foam::reactionRateFlameArea::New
static autoPtr< reactionRateFlameArea > New(const dictionary &dict, const fvMesh &mesh, const combustionModel &combModel)
Definition: reactionRateFlameAreaNew.C:31
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:49
Foam::readScalar
bool readScalar(const char *buf, doubleScalar &s)
Read whole of buf as a scalar. Return true if succesful.
Definition: doubleScalar.H:63
Foam::List< label >
fvcGrad.H
Calculate the gradient of the given field.
timeName
word timeName
Definition: getTimeIndex.H:3
Foam::constant::physicoChemical::sigma
const dimensionedScalar sigma
Stefan-Boltzmann constant: default SI units: [W/m2/K4].
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Foam::GeometricField
Generic GeometricField class.
Definition: surfaceFieldsFwd.H:52
Foam::min
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
lookup
stressControl lookup("compactNormalStress") >> compactNormalStress