33 template<
class ThermoType>
40 log_(this->lookupOrDefault(
"log", false)),
41 loadBalancing_(this->lookupOrDefault(
"loadBalancing", false)),
44 this->
found(
"jacobian")
45 ? jacobianTypeNames_.
read(this->lookup(
"jacobian"))
49 specieThermos_(mixture_.specieThermos()),
50 reactions_(mixture_.species(), specieThermos_, this->mesh(), *this),
64 mechRed_(*mechRedPtr_),
66 tabulation_(*tabulationPtr_)
78 "RR." + Yvf_[fieldi].
name(),
90 Info<<
"chemistryModel: Number of species = " << nSpecie_
120 cpuSolveFile_ =
logFile(
"cpu_solve.out");
127 template<
class ThermoType>
134 template<
class ThermoType>
147 Y_[sToc_[i]] =
max(YTp[i], 0);
154 Y_[i] =
max(YTp[i], 0);
158 const scalar
T = YTp[nSpecie_];
159 const scalar
p = YTp[nSpecie_ + 1];
163 for (
label i=0; i<Y_.size(); i++)
165 rhoM += Y_[i]/specieThermos_[i].rho(
p,
T);
170 for (
label i=0; i<Y_.size(); i ++)
172 c_[i] = rhoM/specieThermos_[i].W()*Y_[i];
179 if (!mechRed_.reactionDisabled(ri))
181 reactions_[ri].dNdtByV
196 for (
label i=0; i<nSpecie_; i++)
198 const scalar WiByrhoM = specieThermos_[sToc(i)].W()/rhoM;
199 scalar& dYidt = dYTpdt[i];
207 for (
label i=0; i<Y_.size(); i++)
209 CpM += Y_[i]*specieThermos_[i].Cp(
p,
T);
213 scalar& dTdt = dYTpdt[nSpecie_];
214 for (
label i=0; i<nSpecie_; i++)
216 dTdt -= dYTpdt[i]*specieThermos_[sToc(i)].Ha(
p,
T);
221 scalar& dpdt = dYTpdt[nSpecie_ + 1];
226 template<
class ThermoType>
240 Y_[sToc_[i]] =
max(YTp[i], 0);
247 Y_[i] =
max(YTp[i], 0);
251 const scalar
T = YTp[nSpecie_];
252 const scalar
p = YTp[nSpecie_ + 1];
256 for (
label i=0; i<Y_.size(); i++)
258 v[i] = 1/specieThermos_[i].rho(
p,
T);
261 for (
label i=0; i<Y_.size(); i++)
268 for (
label i=0; i<Y_.size(); i ++)
270 c_[i] = rhoM/specieThermos_[i].W()*Y_[i];
275 for (
label i=0; i<nSpecie_; i++)
277 const scalar rhoMByWi = rhoM/specieThermos_[sToc(i)].W();
278 switch (jacobianType_)
280 case jacobianType::fast:
282 dcdY(i, i) = rhoMByWi;
285 case jacobianType::exact:
286 for (
label j=0; j<nSpecie_; j++)
289 rhoMByWi*((i == j) - rhoM*v[sToc(j)]*Y_[sToc(i)]);
297 for (
label i=0; i<Y_.size(); i++)
299 alphavM += Y_[i]*rhoM*v[i]*specieThermos_[i].alphav(
p,
T);
305 for (
label i=0; i<nSpecie_ + 2; i++)
307 for (
label j=0; j<nSpecie_ + 2; j++)
309 ddNdtByVdcTp[i][j] = 0;
314 if (!mechRed_.reactionDisabled(ri))
316 reactions_[ri].ddNdtByVdcTp
335 for (
label i=0; i<nSpecie_; i++)
337 const scalar WiByrhoM = specieThermos_[sToc(i)].W()/rhoM;
338 scalar& dYidt = dYTpdt[i];
341 for (
label j=0; j<nSpecie_; j++)
343 scalar ddNidtByVdYj = 0;
344 switch (jacobianType_)
346 case jacobianType::fast:
348 const scalar ddNidtByVdcj = ddNdtByVdcTp(i, j);
349 ddNidtByVdYj = ddNidtByVdcj*dcdY(j, j);
352 case jacobianType::exact:
355 const scalar ddNidtByVdck = ddNdtByVdcTp(i,
k);
356 ddNidtByVdYj += ddNidtByVdck*dcdY(
k, j);
361 scalar& ddYidtdYj = J(i, j);
362 ddYidtdYj = WiByrhoM*ddNidtByVdYj + rhoM*v[sToc(j)]*dYidt;
365 scalar ddNidtByVdT = ddNdtByVdcTp(i, nSpecie_);
366 for (
label j=0; j<nSpecie_; j++)
368 const scalar ddNidtByVdcj = ddNdtByVdcTp(i, j);
369 ddNidtByVdT -= ddNidtByVdcj*c_[sToc(j)]*alphavM;
372 scalar& ddYidtdT = J(i, nSpecie_);
373 ddYidtdT = WiByrhoM*ddNidtByVdT + alphavM*dYidt;
375 scalar& ddYidtdp = J(i, nSpecie_ + 1);
383 scalar CpM = 0, dCpMdT = 0;
384 for (
label i=0; i<Y_.size(); i++)
386 Cp[i] = specieThermos_[i].Cp(
p,
T);
388 dCpMdT += Y_[i]*specieThermos_[i].dCpdT(
p,
T);
393 scalar& dTdt = dYTpdt[nSpecie_];
394 for (
label i=0; i<nSpecie_; i++)
396 Ha[sToc(i)] = specieThermos_[sToc(i)].Ha(
p,
T);
397 dTdt -= dYTpdt[i]*
Ha[sToc(i)];
402 scalar& dpdt = dYTpdt[nSpecie_ + 1];
406 for (
label i=0; i<nSpecie_; i++)
408 scalar& ddTdtdYi = J(nSpecie_, i);
410 for (
label j=0; j<nSpecie_; j++)
412 const scalar ddYjdtdYi = J(j, i);
413 ddTdtdYi -= ddYjdtdYi*
Ha[sToc(j)];
415 ddTdtdYi -=
Cp[sToc(i)]*dTdt;
420 scalar& ddTdtdT = J(nSpecie_, nSpecie_);
422 for (
label i=0; i<nSpecie_; i++)
424 const scalar dYidt = dYTpdt[i];
425 const scalar ddYidtdT = J(i, nSpecie_);
426 ddTdtdT -= dYidt*
Cp[sToc(i)] + ddYidtdT*
Ha[sToc(i)];
428 ddTdtdT -= dTdt*dCpMdT;
432 scalar& ddTdtdp = J(nSpecie_, nSpecie_ + 1);
436 for (
label i=0; i<nSpecie_ + 2; i++)
438 scalar& ddpdtdYiTp = J(nSpecie_ + 1, i);
444 template<
class ThermoType>
448 const label reactioni
452 for (
label i=0; i<nSpecie_; i++)
459 "RR." + Yvf_[i].
name(),
466 if (!this->chemistry_ || mechRed_.reactionDisabled(reactioni))
479 reactionEvaluationScope scope(*
this);
485 const scalar
rho = rhovf[celli];
486 const scalar
T = Tvf[celli];
487 const scalar
p = pvf[celli];
489 for (
label i=0; i<nSpecie_; i++)
491 const scalar Yi = Yvf_[i][celli];
492 c_[i] =
rho*Yi/specieThermos_[i].W();
509 for (
label i=0; i<nSpecie_; i++)
511 RR[i][celli] = dNdtByV[i]*specieThermos_[i].W();
519 template<
class ThermoType>
522 if (!this->chemistry_)
535 reactionEvaluationScope scope(*
this);
539 const scalar
rho = rhovf[celli];
540 const scalar
T = Tvf[celli];
541 const scalar
p = pvf[celli];
543 for (
label i=0; i<nSpecie_; i++)
545 const scalar Yi = Yvf_[i][celli];
546 c_[i] =
rho*Yi/specieThermos_[i].W();
553 if (!mechRed_.reactionDisabled(ri))
555 reactions_[ri].dNdtByV
569 for (
label i=0; i<mechRed_.nActiveSpecies(); i++)
571 RR_[sToc(i)][celli] = dNdtByV[i]*specieThermos_[sToc(i)].W();
577 template<
class ThermoType>
578 template<
class DeltaTType>
581 const DeltaTType& deltaT
591 scalar totalSolveCpuTime = 0;
593 if (!this->chemistry_)
599 this->mesh().template lookupObject<volScalarField>
601 this->
thermo().phasePropertyName(
"rho")
607 reactionEvaluationScope scope(*
this);
616 scalar deltaTMin = great;
619 chemistryCpuTime.
reset();
623 const scalar
rho0 = rho0vf[celli];
625 scalar
p = p0vf[celli];
626 scalar
T = T0vf[celli];
628 for (
label i=0; i<nSpecie_; i++)
630 Y_[i] =
Y0[i] = Yvf_[i].oldTime()[celli];
633 for (
label i=0; i<nSpecie_; i++)
635 phiq[i] = Yvf_[i].oldTime()[celli];
639 phiq[
nSpecie() + 2] = deltaT[celli];
642 scalar timeLeft = deltaT[celli];
650 if (tabulation_.retrieve(phiq, Rphiq))
669 for (
label i=0; i<nSpecie_; i++)
671 c_[i] =
rho0*Y_[i]/specieThermos_[i].W();
675 mechRed_.reduceMechanism(
p,
T, c_, cTos_, sToc_, celli);
678 sY_.setSize(nSpecie_);
679 for (
label i=0; i<nSpecie_; i++)
681 sY_[i] = Y_[sToc(i)];
692 while (timeLeft > small)
694 scalar dt = timeLeft;
708 for (
label i=0; i<mechRed_.nActiveSpecies(); i++)
710 Y_[sToc_[i]] = sY_[i];
715 solve(
p,
T, Y_, celli, dt, deltaTChem_[celli]);
727 if (tabulation_.tabulates())
733 Rphiq[Rphiq.
size()-3] =
T;
734 Rphiq[Rphiq.
size()-2] =
p;
735 Rphiq[Rphiq.
size()-1] = deltaT[celli];
741 mechRed_.nActiveSpecies(),
752 setNSpecie(mechRed_.nSpecie());
755 deltaTMin =
min(deltaTChem_[celli], deltaTMin);
756 deltaTChem_[celli] =
min(deltaTChem_[celli], deltaTChemMax_);
760 for (
label i=0; i<nSpecie_; i++)
762 RR_[i][celli] =
rho0*(Y_[i] -
Y0[i])/deltaT[celli];
774 << this->time().userTimeValue()
775 <<
" " << totalSolveCpuTime <<
endl;
779 tabulation_.update();
802 template<
class ThermoType>
817 template<
class ThermoType>
823 return this->solve<scalarField>(deltaT);
827 template<
class ThermoType>
838 extrapolatedCalculatedFvPatchScalarField::typeName
843 if (!this->chemistry_)
845 ttc.
ref().correctBoundaryConditions();
855 reactionEvaluationScope scope(*
this);
859 const scalar
rho = rhovf[celli];
860 const scalar
T = Tvf[celli];
861 const scalar
p = pvf[celli];
863 for (
label i=0; i<nSpecie_; i++)
865 c_[i] =
rho*Yvf_[i][celli]/specieThermos_[i].W();
885 scalar sumW = 0, sumWRateByCTot = 0;
889 scalar omegaf, omegar;
890 R.omega(
p,
T, c_, celli, omegaf, omegar);
895 wf +=
R.rhs()[
s].stoichCoeff*omegaf;
898 sumWRateByCTot +=
sqr(wf);
903 wr +=
R.lhs()[
s].stoichCoeff*omegar;
906 sumWRateByCTot +=
sqr(wr);
910 sumWRateByCTot == 0 ? vGreat : sumW/sumWRateByCTot*
sum(c_);
913 ttc.
ref().correctBoundaryConditions();
918 template<
class ThermoType>
932 if (!this->chemistry_)
937 reactionEvaluationScope scope(*
this);
945 const scalar hi = specieThermos_[i].Hf();
946 Qdot[celli] -= hi*RR_[i][celli];
scalar Ha(const scalar p, const scalar T) const
scalar Cp(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.
const GeometricField< Type, PatchField, GeoMesh > & oldTime() const
Return old time field.
static tmp< GeometricField< Type, PatchField, GeoMesh > > New(const word &name, const Internal &, const PtrList< PatchField< Type >> &)
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.
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
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...
static bool & parRun()
Is this a parallel run?
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.
Specialisation of basicMixture for a mixture consisting of a number for molecular species.
void setActive(label speciei) const
Set speciei active.
bool active(label speciei) const
Return true for active species.
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 basicSpecieMixture & composition()=0
Return the composition of the multi-component mixture.
virtual volScalarField & p()=0
Pressure [Pa].
Foam::multicomponentMixture.
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 reset()
Dummy reset function.
virtual void cpuTimeIncrement(const label celli)
Dummy cpuTimeIncrement function.
static optionalCpuLoad & New(const fvMesh &mesh, const word &name, const bool loadBalancing)
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].
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
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)
To & refCast(From &r)
Reference type cast template function.
Ostream & endl(Ostream &os)
Add newline and flush stream.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
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
word name(const complex &)
Return a string representation of a complex.
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
SolverPerformance< Type > solve(fvMatrix< Type > &, const word &)
Solve returning the solution statistics given convergence tolerance.
scalarList Y0(nSpecie, 0.0)
basicSpecieMixture & composition
fluidMulticomponentThermo & thermo