33 template<
class ThermoType>
40 log_(this->lookupOrDefault(
"log", false)),
41 cpuLoad_(this->lookupOrDefault(
"cpuLoad", false)),
44 this->
found(
"jacobian")
45 ? jacobianTypeNames_.
read(this->lookup(
"jacobian"))
52 specieThermos_(mixture_.specieThermos()),
53 reactions_(
thermo.species(), specieThermos_, this->mesh(), *this),
67 mechRed_(*mechRedPtr_),
69 tabulation_(*tabulationPtr_)
81 "RR." + Yvf_[fieldi].
name(),
93 Info<<
"chemistryModel: Number of species = " << nSpecie_
121 cpuSolveFile_ =
logFile(
"cpu_solve.out");
128 template<
class ThermoType>
135 template<
class ThermoType>
148 Y_[sToc_[i]] =
max(YTp[i], 0);
155 Y_[i] =
max(YTp[i], 0);
159 const scalar
T = YTp[nSpecie_];
160 const scalar
p = YTp[nSpecie_ + 1];
164 for (
label i=0; i<Y_.size(); i++)
166 rhoM += Y_[i]/specieThermos_[i].rho(
p,
T);
171 for (
label i=0; i<Y_.size(); i ++)
173 c_[i] = rhoM/specieThermos_[i].W()*Y_[i];
180 if (!mechRed_.reactionDisabled(ri))
182 reactions_[ri].dNdtByV
197 for (
label i=0; i<nSpecie_; i++)
199 const scalar WiByrhoM = specieThermos_[sToc(i)].W()/rhoM;
200 scalar& dYidt = dYTpdt[i];
208 for (
label i=0; i<Y_.size(); i++)
210 CpM += Y_[i]*specieThermos_[i].Cp(
p,
T);
214 scalar& dTdt = dYTpdt[nSpecie_];
215 for (
label i=0; i<nSpecie_; i++)
217 dTdt -= dYTpdt[i]*specieThermos_[sToc(i)].ha(
p,
T);
222 scalar& dpdt = dYTpdt[nSpecie_ + 1];
227 template<
class ThermoType>
241 Y_[sToc_[i]] =
max(YTp[i], 0);
248 Y_[i] =
max(YTp[i], 0);
252 const scalar
T = YTp[nSpecie_];
253 const scalar
p = YTp[nSpecie_ + 1];
257 for (
label i=0; i<Y_.size(); i++)
259 v[i] = 1/specieThermos_[i].rho(
p,
T);
262 for (
label i=0; i<Y_.size(); i++)
269 for (
label i=0; i<Y_.size(); i ++)
271 c_[i] = rhoM/specieThermos_[i].W()*Y_[i];
276 for (
label i=0; i<nSpecie_; i++)
278 const scalar rhoMByWi = rhoM/specieThermos_[sToc(i)].W();
279 switch (jacobianType_)
281 case jacobianType::fast:
283 dcdY(i, i) = rhoMByWi;
286 case jacobianType::exact:
287 for (
label j=0; j<nSpecie_; j++)
290 rhoMByWi*((i == j) - rhoM*v[sToc(j)]*Y_[sToc(i)]);
298 for (
label i=0; i<Y_.size(); i++)
300 alphavM += Y_[i]*rhoM*v[i]*specieThermos_[i].alphav(
p,
T);
306 for (
label i=0; i<nSpecie_ + 2; i++)
308 for (
label j=0; j<nSpecie_ + 2; j++)
310 ddNdtByVdcTp[i][j] = 0;
315 if (!mechRed_.reactionDisabled(ri))
317 reactions_[ri].ddNdtByVdcTp
336 for (
label i=0; i<nSpecie_; i++)
338 const scalar WiByrhoM = specieThermos_[sToc(i)].W()/rhoM;
339 scalar& dYidt = dYTpdt[i];
342 for (
label j=0; j<nSpecie_; j++)
344 scalar ddNidtByVdYj = 0;
345 switch (jacobianType_)
347 case jacobianType::fast:
349 const scalar ddNidtByVdcj = ddNdtByVdcTp(i, j);
350 ddNidtByVdYj = ddNidtByVdcj*dcdY(j, j);
353 case jacobianType::exact:
356 const scalar ddNidtByVdck = ddNdtByVdcTp(i,
k);
357 ddNidtByVdYj += ddNidtByVdck*dcdY(
k, j);
362 scalar& ddYidtdYj = J(i, j);
363 ddYidtdYj = WiByrhoM*ddNidtByVdYj + rhoM*v[sToc(j)]*dYidt;
366 scalar ddNidtByVdT = ddNdtByVdcTp(i, nSpecie_);
367 for (
label j=0; j<nSpecie_; j++)
369 const scalar ddNidtByVdcj = ddNdtByVdcTp(i, j);
370 ddNidtByVdT -= ddNidtByVdcj*c_[sToc(j)]*alphavM;
373 scalar& ddYidtdT = J(i, nSpecie_);
374 ddYidtdT = WiByrhoM*ddNidtByVdT + alphavM*dYidt;
376 scalar& ddYidtdp = J(i, nSpecie_ + 1);
384 scalar CpM = 0, dCpMdT = 0;
385 for (
label i=0; i<Y_.size(); i++)
387 Cp[i] = specieThermos_[i].Cp(
p,
T);
389 dCpMdT += Y_[i]*specieThermos_[i].dCpdT(
p,
T);
394 scalar& dTdt = dYTpdt[nSpecie_];
395 for (
label i=0; i<nSpecie_; i++)
397 ha[sToc(i)] = specieThermos_[sToc(i)].ha(
p,
T);
398 dTdt -= dYTpdt[i]*
ha[sToc(i)];
403 scalar& dpdt = dYTpdt[nSpecie_ + 1];
407 for (
label i=0; i<nSpecie_; i++)
409 scalar& ddTdtdYi = J(nSpecie_, i);
411 for (
label j=0; j<nSpecie_; j++)
413 const scalar ddYjdtdYi = J(j, i);
414 ddTdtdYi -= ddYjdtdYi*
ha[sToc(j)];
416 ddTdtdYi -=
Cp[sToc(i)]*dTdt;
421 scalar& ddTdtdT = J(nSpecie_, nSpecie_);
423 for (
label i=0; i<nSpecie_; i++)
425 const scalar dYidt = dYTpdt[i];
426 const scalar ddYidtdT = J(i, nSpecie_);
427 ddTdtdT -= dYidt*
Cp[sToc(i)] + ddYidtdT*
ha[sToc(i)];
429 ddTdtdT -= dTdt*dCpMdT;
433 scalar& ddTdtdp = J(nSpecie_, nSpecie_ + 1);
437 for (
label i=0; i<nSpecie_ + 2; i++)
439 scalar& ddpdtdYiTp = J(nSpecie_ + 1, i);
445 template<
class ThermoType>
449 const label reactioni
453 for (
label i=0; i<nSpecie_; i++)
460 "RR." + Yvf_[i].
name(),
467 if (!this->chemistry_ || mechRed_.reactionDisabled(reactioni))
480 reactionEvaluationScope scope(*
this);
486 const scalar
rho = rhovf[celli];
487 const scalar
T = Tvf[celli];
488 const scalar
p = pvf[celli];
490 for (
label i=0; i<nSpecie_; i++)
492 const scalar Yi = Yvf_[i][celli];
493 c_[i] =
rho*Yi/specieThermos_[i].W();
510 for (
label i=0; i<nSpecie_; i++)
512 RR[i][celli] = dNdtByV[i]*specieThermos_[i].W();
520 template<
class ThermoType>
523 if (!this->chemistry_)
536 reactionEvaluationScope scope(*
this);
540 const scalar
rho = rhovf[celli];
541 const scalar
T = Tvf[celli];
542 const scalar
p = pvf[celli];
544 for (
label i=0; i<nSpecie_; i++)
546 const scalar Yi = Yvf_[i][celli];
547 c_[i] =
rho*Yi/specieThermos_[i].W();
554 if (!mechRed_.reactionDisabled(ri))
556 reactions_[ri].dNdtByV
570 for (
label i=0; i<mechRed_.nActiveSpecies(); i++)
572 RR_[sToc(i)][celli] = dNdtByV[i]*specieThermos_[sToc(i)].W();
578 template<
class ThermoType>
579 template<
class DeltaTType>
582 const DeltaTType& deltaT
592 scalar totalSolveCpuTime = 0;
594 if (!this->chemistry_)
600 this->mesh().template lookupObject<volScalarField>
602 this->
thermo().phasePropertyName(
"rho")
608 reactionEvaluationScope scope(*
this);
617 scalar deltaTMin = great;
624 const scalar
rho0 = rho0vf[celli];
626 scalar
p = p0vf[celli];
627 scalar
T = T0vf[celli];
629 for (
label i=0; i<nSpecie_; i++)
631 Y_[i] =
Y0[i] = Yvf_[i].oldTime()[celli];
634 for (
label i=0; i<nSpecie_; i++)
636 phiq[i] = Yvf_[i].oldTime()[celli];
640 phiq[
nSpecie() + 2] = deltaT[celli];
643 scalar timeLeft = deltaT[celli];
651 if (tabulation_.retrieve(phiq, Rphiq))
670 for (
label i=0; i<nSpecie_; i++)
672 c_[i] =
rho0*Y_[i]/specieThermos_[i].W();
676 mechRed_.reduceMechanism(
p,
T, c_, cTos_, sToc_, celli);
679 sY_.setSize(nSpecie_);
680 for (
label i=0; i<nSpecie_; i++)
682 sY_[i] = Y_[sToc(i)];
693 while (timeLeft > small)
695 scalar dt = timeLeft;
709 for (
label i=0; i<mechRed_.nActiveSpecies(); i++)
711 Y_[sToc_[i]] = sY_[i];
716 solve(
p,
T, Y_, celli, dt, deltaTChem_[celli]);
728 if (tabulation_.tabulates())
734 Rphiq[Rphiq.
size()-3] =
T;
735 Rphiq[Rphiq.
size()-2] =
p;
736 Rphiq[Rphiq.
size()-1] = deltaT[celli];
742 mechRed_.nActiveSpecies(),
753 setNSpecie(mechRed_.nSpecie());
756 deltaTMin =
min(deltaTChem_[celli], deltaTMin);
757 deltaTChem_[celli] =
min(deltaTChem_[celli], deltaTChemMax_);
761 for (
label i=0; i<nSpecie_; i++)
763 RR_[i][celli] =
rho0*(Y_[i] -
Y0[i])/deltaT[celli];
775 << this->time().userTimeValue()
776 <<
" " << totalSolveCpuTime <<
endl;
780 tabulation_.update();
791 template<
class ThermoType>
806 template<
class ThermoType>
812 return this->solve<scalarField>(deltaT);
816 template<
class ThermoType>
827 extrapolatedCalculatedFvPatchScalarField::typeName
832 if (!this->chemistry_)
834 ttc.
ref().correctBoundaryConditions();
844 reactionEvaluationScope scope(*
this);
848 const scalar
rho = rhovf[celli];
849 const scalar
T = Tvf[celli];
850 const scalar
p = pvf[celli];
852 for (
label i=0; i<nSpecie_; i++)
854 c_[i] =
rho*Yvf_[i][celli]/specieThermos_[i].W();
874 scalar sumW = 0, sumWRateByCTot = 0;
878 scalar omegaf, omegar;
879 R.omega(
p,
T, c_, celli, omegaf, omegar);
884 wf +=
R.rhs()[
s].stoichCoeff*omegaf;
887 sumWRateByCTot +=
sqr(wf);
892 wr +=
R.lhs()[
s].stoichCoeff*omegar;
895 sumWRateByCTot +=
sqr(wr);
899 sumWRateByCTot == 0 ? vGreat : sumW/sumWRateByCTot*
sum(c_);
902 ttc.
ref().correctBoundaryConditions();
907 template<
class ThermoType>
921 if (!this->chemistry_)
926 reactionEvaluationScope scope(*
this);
934 const scalar hi = specieThermos_[i].hf();
935 Qdot[celli] -= hi*RR_[i][celli];
scalar Cp(const scalar p, const scalar T) const
scalar ha(const scalar p, const scalar T) const
#define forAll(list, i)
Loop across all elements in list.
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
static tmp< DimensionedField< Type, GeoMesh > > New(const word &name, const Mesh &mesh, const dimensionSet &, const Field< Type > &)
Return a temporary field constructed from name, mesh,.
Generic GeometricField class.
static tmp< GeometricField< Type, PatchField, GeoMesh > > New(const word &name, const Internal &, const PtrList< PatchField< Type >> &, const HashPtrTable< Source > &=HashPtrTable< Source >())
Return a temporary field constructed from name,.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
const Time & time() const
Return time.
void size(const label)
Override size to be inconsistent with allocated storage.
const FieldType & oldTime() const
Return the old time field.
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Simple extension of ThermoType to handle reaction kinetics in addition to the equilibrium thermodynam...
const fluidMulticomponentThermo & thermo() const
Return const access to the thermo.
jacobianType
Enumeration for the type of Jacobian to be calculated by the.
const fvMesh & mesh() const
Return const access to the mesh.
virtual const fvMesh & mesh() const =0
Return const access to the mesh.
virtual const volScalarField & T() const =0
Temperature [K].
Extends base chemistry model by adding a thermo package, and ODE functions. Introduces chemistry equa...
virtual void jacobian(const scalar t, const scalarField &YTp, const label li, scalarField &dYTpdt, scalarSquareMatrix &J) const
Calculate the ODE jacobian.
virtual tmp< volScalarField > tc() const
Return the chemical time scale.
virtual void derivatives(const scalar t, const scalarField &YTp, const label li, scalarField &dYTpdt) const
Calculate the ODE derivatives.
virtual label nReaction() const
The number of reactions.
virtual ~chemistryModel()
Destructor.
virtual PtrList< volScalarField::Internal > reactionRR(const label reactioni) const
Return reaction rates of the species in reactioni [kg/m^3/s].
virtual tmp< volScalarField > Qdot() const
Return the heat release rate [kg/m/s^3].
virtual void calculate()
Calculates the reaction rates.
An abstract class for methods of chemical mechanism reduction.
An abstract class for chemistry tabulation.
Starts timing CPU usage and return elapsed time from start.
double cpuTimeIncrement() const
Return CPU time (in seconds) since last call to cpuTimeIncrement()
const fileName & name() const
Return the dictionary name.
Base-class for multi-component fluid thermodynamic properties.
virtual const volScalarField & p() const =0
Pressure [Pa].
Foam::multicomponentMixture.
void syncSpeciesActive() const
Synchronise the specie active flags.
void setSpecieInactive(const label speciei) const
Set specie inactive.
Extends base chemistry model adding an ODESystem and the reduction maps needed for tabulation.
autoPtr< OFstream > logFile(const word &name) const
Create and return a TDAC log file of the given name.
friend class chemistryModel
virtual void resetCpuTime()
Reset the CPU time (dummy)
virtual void cpuTimeIncrement(const label celli)
Cache the CPU time increment for celli (dummy)
static optionalCpuLoad & New(const word &name, const polyMesh &mesh, const bool loadBalancing)
Construct from polyMesh if loadBalancing is true.
A class for managing temporary objects.
T & ref() const
Return non-const reference or generate a fatal error.
Templated form of IOobject providing type information for file reading and header type checking.
bool headerOk()
Read header (uses typeGlobalFile to find file) and check.
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.name(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
autoPtr< CompressibleMomentumTransportModel > New(const volScalarField &rho, const volVectorField &U, const surfaceScalarField &phi, const viscosity &viscosity)
const dimensionedScalar RR
Universal gas constant: default SI units: [J/kmol/K].
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
const dimensionSet dimEnergy
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Ostream & endl(Ostream &os)
Add newline and flush stream.
word name(const bool)
Return a word representation of a bool.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
To & dynamicCast(From &r)
Reference type cast template function,.
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
const dimensionSet dimTime
const dimensionSet dimVolume
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
static scalar R(const scalar a, const scalar x)
const dimensionSet dimMass
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
SolverPerformance< Type > solve(fvMatrix< Type > &, const word &)
Solve returning the solution statistics given convergence tolerance.
scalarList Y0(nSpecie, 0.0)
fluidMulticomponentThermo & thermo