32 template<
class ThermoType>
39 log_(this->lookupOrDefault(
"log", false)),
40 cpuLoad_(this->lookupOrDefault(
"cpuLoad", false)),
43 this->
found(
"jacobian")
44 ? jacobianTypeNames.
read(this->
lookup(
"jacobian"))
51 specieThermos_(mixture_.specieThermos()),
52 reactions_(
thermo.species(), specieThermos_, this->
mesh(), *this),
66 mechRed_(*mechRedPtr_),
68 tabulation_(*tabulationPtr_)
92 Info<<
"chemistryModel: Number of species = " <<
nSpecie_
122 cpuSolveFile_ =
logFile(
"cpu_solve.out");
129 template<
class ThermoType>
136 template<
class ThermoType>
149 Y_[sToc_[i]] =
max(YTp[i], 0);
156 Y_[i] =
max(YTp[i], 0);
160 const scalar
T = YTp[nSpecie_];
161 const scalar
p = YTp[nSpecie_ + 1];
165 for (
label i=0; i<Y_.size(); i++)
167 rhoM += Y_[i]/specieThermos_[i].rho(
p,
T);
172 for (
label i=0; i<Y_.size(); i ++)
174 c_[i] = rhoM/specieThermos_[i].W()*Y_[i];
181 if (!mechRed_.reactionDisabled(ri))
183 reactions_[ri].dNdtByV
198 for (
label i=0; i<nSpecie_; i++)
200 const scalar WiByrhoM = specieThermos_[sToc(i)].W()/rhoM;
201 scalar& dYidt = dYTpdt[i];
209 for (
label i=0; i<Y_.size(); i++)
211 CpM += Y_[i]*specieThermos_[i].Cp(
p,
T);
215 scalar& dTdt = dYTpdt[nSpecie_];
216 for (
label i=0; i<nSpecie_; i++)
218 dTdt -= dYTpdt[i]*specieThermos_[sToc(i)].ha(
p,
T);
223 scalar& dpdt = dYTpdt[nSpecie_ + 1];
228 template<
class ThermoType>
242 Y_[sToc_[i]] =
max(YTp[i], 0);
249 Y_[i] =
max(YTp[i], 0);
253 const scalar
T = YTp[nSpecie_];
254 const scalar
p = YTp[nSpecie_ + 1];
258 for (
label i=0; i<Y_.size(); i++)
260 v[i] = 1/specieThermos_[i].rho(
p,
T);
263 for (
label i=0; i<Y_.size(); i++)
270 for (
label i=0; i<Y_.size(); i ++)
272 c_[i] = rhoM/specieThermos_[i].W()*Y_[i];
277 for (
label i=0; i<nSpecie_; i++)
279 const scalar rhoMByWi = rhoM/specieThermos_[sToc(i)].W();
280 switch (jacobianType_)
282 case jacobianType::fast:
284 dcdY(i, i) = rhoMByWi;
287 case jacobianType::exact:
288 for (
label j=0; j<nSpecie_; j++)
291 rhoMByWi*((i == j) - rhoM*v[sToc(j)]*Y_[sToc(i)]);
299 for (
label i=0; i<Y_.size(); i++)
301 alphavM += Y_[i]*rhoM*v[i]*specieThermos_[i].alphav(
p,
T);
307 for (
label i=0; i<nSpecie_ + 2; i++)
309 for (
label j=0; j<nSpecie_ + 2; j++)
311 ddNdtByVdcTp[i][j] = 0;
316 if (!mechRed_.reactionDisabled(ri))
318 reactions_[ri].ddNdtByVdcTp
337 for (
label i=0; i<nSpecie_; i++)
339 const scalar WiByrhoM = specieThermos_[sToc(i)].W()/rhoM;
340 scalar& dYidt = dYTpdt[i];
343 for (
label j=0; j<nSpecie_; j++)
345 scalar ddNidtByVdYj = 0;
346 switch (jacobianType_)
348 case jacobianType::fast:
350 const scalar ddNidtByVdcj = ddNdtByVdcTp(i, j);
351 ddNidtByVdYj = ddNidtByVdcj*dcdY(j, j);
354 case jacobianType::exact:
357 const scalar ddNidtByVdck = ddNdtByVdcTp(i,
k);
358 ddNidtByVdYj += ddNidtByVdck*dcdY(
k, j);
363 scalar& ddYidtdYj = J(i, j);
364 ddYidtdYj = WiByrhoM*ddNidtByVdYj + rhoM*v[sToc(j)]*dYidt;
367 scalar ddNidtByVdT = ddNdtByVdcTp(i, nSpecie_);
368 for (
label j=0; j<nSpecie_; j++)
370 const scalar ddNidtByVdcj = ddNdtByVdcTp(i, j);
371 ddNidtByVdT -= ddNidtByVdcj*c_[sToc(j)]*alphavM;
374 scalar& ddYidtdT = J(i, nSpecie_);
375 ddYidtdT = WiByrhoM*ddNidtByVdT + alphavM*dYidt;
377 scalar& ddYidtdp = J(i, nSpecie_ + 1);
385 scalar CpM = 0, dCpMdT = 0;
386 for (
label i=0; i<Y_.size(); i++)
388 Cp[i] = specieThermos_[i].Cp(
p,
T);
390 dCpMdT += Y_[i]*specieThermos_[i].dCpdT(
p,
T);
395 scalar& dTdt = dYTpdt[nSpecie_];
396 for (
label i=0; i<nSpecie_; i++)
398 ha[sToc(i)] = specieThermos_[sToc(i)].ha(
p,
T);
399 dTdt -= dYTpdt[i]*
ha[sToc(i)];
404 scalar& dpdt = dYTpdt[nSpecie_ + 1];
408 for (
label i=0; i<nSpecie_; i++)
410 scalar& ddTdtdYi = J(nSpecie_, i);
412 for (
label j=0; j<nSpecie_; j++)
414 const scalar ddYjdtdYi = J(j, i);
415 ddTdtdYi -= ddYjdtdYi*
ha[sToc(j)];
417 ddTdtdYi -=
Cp[sToc(i)]*dTdt;
422 scalar& ddTdtdT = J(nSpecie_, nSpecie_);
424 for (
label i=0; i<nSpecie_; i++)
426 const scalar dYidt = dYTpdt[i];
427 const scalar ddYidtdT = J(i, nSpecie_);
428 ddTdtdT -= dYidt*
Cp[sToc(i)] + ddYidtdT*
ha[sToc(i)];
430 ddTdtdT -= dTdt*dCpMdT;
434 scalar& ddTdtdp = J(nSpecie_, nSpecie_ + 1);
438 for (
label i=0; i<nSpecie_ + 2; i++)
440 scalar& ddpdtdYiTp = J(nSpecie_ + 1, i);
446 template<
class ThermoType>
450 const label reactioni
456 "RR:" + reactions_[reactioni].
name(),
462 if (!this->chemistry_ || mechRed_.reactionDisabled(reactioni))
473 reactionEvaluationScope scope(*
this);
477 const label nZoneCells = zone_.nCells();
478 for(
label zci = 0; zci<nZoneCells; zci++)
480 const label celli = zone_.celli(zci);
482 const scalar
rho = rhovf[celli];
483 const scalar
T = Tvf[celli];
484 const scalar
p = pvf[celli];
486 for (
label i=0; i<nSpecie_; i++)
488 const scalar Yi = Yvf_[i][celli];
489 c_[i] =
rho*Yi/specieThermos_[i].W();
492 scalar omegaf, omegar;
510 template<
class ThermoType>
514 const label reactioni
518 for (
label i=0; i<nSpecie_; i++)
525 "RR:" + reactions_[reactioni].
name() +
":" + Yvf_[i].
name(),
532 if (!this->chemistry_ || mechRed_.reactionDisabled(reactioni))
545 reactionEvaluationScope scope(*
this);
549 const label nZoneCells = zone_.nCells();
550 for(
label zci = 0; zci<nZoneCells; zci++)
552 const label celli = zone_.celli(zci);
554 const scalar
rho = rhovf[celli];
555 const scalar
T = Tvf[celli];
556 const scalar
p = pvf[celli];
558 for (
label i=0; i<nSpecie_; i++)
560 const scalar Yi = Yvf_[i][celli];
561 c_[i] =
rho*Yi/specieThermos_[i].W();
578 for (
label i=0; i<nSpecie_; i++)
580 RR[i][celli] = dNdtByV[i]*specieThermos_[i].W();
588 template<
class ThermoType>
591 if (!this->chemistry_)
612 reactionEvaluationScope scope(*
this);
614 const label nZoneCells = zone_.nCells();
615 for(
label zci = 0; zci<nZoneCells; zci++)
617 const label celli = zone_.celli(zci);
619 const scalar
rho = rhovf[celli];
620 const scalar
T = Tvf[celli];
621 const scalar
p = pvf[celli];
623 for (
label i=0; i<nSpecie_; i++)
625 const scalar Yi = Yvf_[i][celli];
626 c_[i] =
rho*Yi/specieThermos_[i].W();
633 if (!mechRed_.reactionDisabled(ri))
635 reactions_[ri].dNdtByV
649 for (
label i=0; i<mechRed_.nActiveSpecies(); i++)
651 RR_[sToc(i)][celli] = dNdtByV[i]*specieThermos_[sToc(i)].W();
657 template<
class ThermoType>
658 template<
class DeltaTType>
661 const DeltaTType& deltaT
671 scalar totalSolveCpuTime = 0;
673 if (!this->chemistry_)
687 this->
mesh().template lookupObject<volScalarField>
689 this->
thermo().phasePropertyName(
"rho")
695 reactionEvaluationScope scope(*
this);
704 scalar deltaTMin = great;
710 const label nZoneCells = zone_.nCells();
711 for(
label zci = 0; zci<nZoneCells; zci++)
713 const label celli = zone_.celli(zci);
715 const scalar
rho0 = rho0vf[celli];
717 scalar
p = p0vf[celli];
718 scalar
T = T0vf[celli];
720 for (
label i=0; i<nSpecie_; i++)
722 Y_[i] =
Y0[i] = Yvf_[i].oldTime()[celli];
725 for (
label i=0; i<nSpecie_; i++)
727 phiq[i] = Yvf_[i].oldTime()[celli];
731 phiq[
nSpecie() + 2] = deltaT[celli];
734 scalar timeLeft = deltaT[celli];
742 if (tabulation_.retrieve(phiq, Rphiq))
761 for (
label i=0; i<nSpecie_; i++)
763 c_[i] =
rho0*Y_[i]/specieThermos_[i].W();
767 mechRed_.reduceMechanism(
p,
T, c_, cTos_, sToc_, celli);
770 sY_.setSize(nSpecie_);
771 for (
label i=0; i<nSpecie_; i++)
773 sY_[i] = Y_[sToc(i)];
784 while (timeLeft > small)
786 scalar dt = timeLeft;
800 for (
label i=0; i<mechRed_.nActiveSpecies(); i++)
802 Y_[sToc_[i]] = sY_[i];
807 solve(
p,
T, Y_, celli, dt, deltaTChem_[celli]);
819 if (tabulation_.tabulates())
825 Rphiq[Rphiq.
size()-3] =
T;
826 Rphiq[Rphiq.
size()-2] =
p;
827 Rphiq[Rphiq.
size()-1] = deltaT[celli];
833 mechRed_.nActiveSpecies(),
844 setNSpecie(mechRed_.nSpecie());
847 deltaTMin =
min(deltaTChem_[celli], deltaTMin);
848 deltaTChem_[celli] =
min(deltaTChem_[celli], deltaTChemMax_);
852 for (
label i=0; i<nSpecie_; i++)
854 RR_[i][celli] =
rho0*(Y_[i] -
Y0[i])/deltaT[celli];
866 << this->
time().userTimeValue()
867 <<
" " << totalSolveCpuTime <<
endl;
871 tabulation_.update();
875 this->
thermo().syncSpeciesActive();
882 template<
class ThermoType>
897 template<
class ThermoType>
903 return this->solve<scalarField>(deltaT);
907 template<
class ThermoType>
923 if (!this->chemistry_)
925 ttc.
ref().correctBoundaryConditions();
935 reactionEvaluationScope scope(*
this);
937 const label nZoneCells = zone_.nCells();
938 for(
label zci = 0; zci<nZoneCells; zci++)
940 const label celli = zone_.celli(zci);
942 const scalar
rho = rhovf[celli];
943 const scalar
T = Tvf[celli];
944 const scalar
p = pvf[celli];
946 for (
label i=0; i<nSpecie_; i++)
948 c_[i] =
rho*Yvf_[i][celli]/specieThermos_[i].W();
968 scalar sumW = 0, sumWRateByCTot = 0;
972 scalar omegaf, omegar;
973 R.omega(
p,
T, c_, celli, omegaf, omegar);
978 wf +=
R.rhs()[
s].stoichCoeff*omegaf;
981 sumWRateByCTot +=
sqr(wf);
986 wr +=
R.lhs()[
s].stoichCoeff*omegar;
989 sumWRateByCTot +=
sqr(wr);
993 sumWRateByCTot == 0 ? vGreat : sumW/sumWRateByCTot*
sum(c_);
996 ttc.
ref().correctBoundaryConditions();
1001 template<
class ThermoType>
1015 if (!this->chemistry_)
1020 reactionEvaluationScope scope(*
this);
1026 const label nZoneCells = zone_.nCells();
1027 for(
label zci = 0; zci<nZoneCells; zci++)
1029 const label celli = zone_.celli(zci);
1031 const scalar hi = specieThermos_[i].hf();
1032 Qdot[celli] -= hi*RR_[i][celli];
1040 template<
class ThermoType>
1053 if (odeSolver_->resize())
1055 odeSolver_->resizeField(cTp_);
1073 this->check(0, cTp_, dcTp, li);
1076 odeSolver_->solve(0, deltaT, cTp_, li, subDeltaT);
1080 c[i] =
max(0.0, cTp_[i]);
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, PrimitiveField > > New(const word &name, const GeoMesh &mesh, const dimensionSet &, const PrimitiveField< Type > &)
Return a temporary field constructed from name, mesh,.
Generic GeometricField class.
static tmp< GeometricField< Type, GeoMesh, PrimitiveField > > New(const word &name, const Internal &, const PtrList< Patch > &, 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.
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...
virtual const fvMesh & mesh() const =0
Return const access to the mesh.
const fluidMulticomponentThermo & thermo() const
Return const access to the thermo.
const fvMesh & mesh() const
Return const access to the mesh.
Extension to Foam::chemistryModels::standard templated on thermo and provides stiff ODE integration f...
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 tmp< volScalarField::Internal > reactionRR(const label reactioni) const
Return the rate of reactioni [kmol/m^3/s].
Standard(const fluidMulticomponentThermo &thermo)
Construct from thermo.
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 ~Standard()
Destructor.
virtual PtrList< volScalarField::Internal > specieReactionRR(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.
Non-templated Base class for Foam::chemistryModels::Standard.
label nSpecie_
Number of species.
jacobianType
Enumeration for the type of Jacobian to be calculated by the.
autoPtr< OFstream > logFile(const word &name) const
Create and return a TDAC log file of the given name.
const PtrList< volScalarField > & Yvf_
Reference to the field of specie mass fractions.
bool reduction_
Is chemistry reduction active.
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.
Foam::multicomponentMixture.
void setSpecieInactive(const label speciei) const
Set specie inactive.
virtual void syncSpeciesActive() const =0
Synchronise the specie active flags.
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.
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.name(), lagrangian::cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
const dimensionedScalar RR
Universal gas constant: default SI units: [J/kmol/K].
const dimensionedScalar c
Speed of light in a vacuum.
const unitSet & lookup(const word &unitName)
Lookup and return the named unit from the table.
const dimensionSet & dimMoles
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 & dimMass
Ostream & endl(Ostream &os)
Add newline and flush stream.
String typeName(const std::type_info &info)
Return the un-mangled name given the standard type info.
const dimensionSet & dimVolume
To & dynamicCast(From &r)
Reference type cast template function,.
tmp< DimensionedField< typename outerProduct< Type, Type >::type, GeoMesh, Field >> sqr(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
const dimensionSet & dimTime
dimensioned< Type > min(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
static scalar R(const scalar a, const scalar x)
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
const dimensionSet & dimEnergy
tmp< DimensionedField< TypeR, GeoMesh, Field > > New(const tmp< DimensionedField< TypeR, GeoMesh, Field >> &tdf1, const word &name, const dimensionSet &dimensions)
void T(GeometricField< Type, GeoMesh, PrimitiveField1 > &gf, const GeometricField< Type, GeoMesh, PrimitiveField2 > &gf1)
dimensioned< Type > max(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
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