7#ifndef FvSysEqnDetChem_H_
8#define FvSysEqnDetChem_H_
21#if defined(WITH_CANTERA)
23#pragma GCC diagnostic push
24#pragma GCC diagnostic ignored "-Wunused-parameter"
25#pragma GCC diagnostic ignored "-Wfloat-equal"
26#include "cantera/base/Solution.h"
27#include "cantera/thermo/IdealGasPhase.h"
28#include "cantera/thermo/Species.h"
29#include "cantera/thermo/SpeciesThermoInterpType.h"
30#include "cantera/transport.h"
31#include "cantera/zerodim.h"
32#pragma GCC diagnostic pop
33using namespace Cantera;
49 template <MInt stencil = AUSM>
57 template <MInt stencil>
64 TERMM(1,
"Viscous Flux Scheme not implemented.");
69 template <MInt stencil>
75 TERMM(1,
"Three point viscous Flux Scheme not implemented for SysEqnDetChem.");
77 TERMM(1,
"Viscous Flux Scheme not implemented.");
88 const MFloat f1, std::vector<MFloat>& J, std::vector<MFloat>& dXdn,
92 MFloat*
const srfcCoeff, std::shared_ptr<Cantera::ThermoPhase> gas,
93 std::shared_ptr<Cantera::Transport> trans);
96 const MFloat*
const pvarsCell,
const MFloat*
const avarsCell,
97 MFloat*
const reactionRatesCell, Cantera::IdealGasReactor* zeroD_reactor,
98 Cantera::ReactorNet* zeroD_reactorNet, std::shared_ptr<Cantera::Solution> sol,
99 std::shared_ptr<Cantera::ThermoPhase> gas);
102 const MFloat*
const avarsCell);
105 const MFloat*
const avarsCell);
108 const MFloat& meanMolarMass);
118 std::shared_ptr<Cantera::ThermoPhase> gas);
123 const MFloat*
const cvarsCell,
124 const MFloat*
const avarsCell,
125 const MFloat*
const slopesCell);
200 static const MInt Segfault = std::numeric_limits<MInt>::min();
202 static constexpr MInt RHO_U = 0;
203 static constexpr MInt RHO_V = 1;
204 static constexpr MInt RHO_W = (nDim == 3) ? 2 : Segfault;
206 static constexpr MInt RHO_E = nDim;
207 static constexpr MInt RHO = nDim + 1;
209 static constexpr MInt RHO_C = nDim + 2;
231 static const MInt Segfault = std::numeric_limits<MInt>::min();
235 static constexpr MInt W = (nDim == 3) ? 2 : Segfault;
237 static constexpr MInt RHO = nDim;
238 static constexpr MInt P = nDim + 1;
240 static constexpr MInt C = nDim + 2;
245 const std::array<MString, nDim + 3> varNames = [] {
246 IF_CONSTEXPR(nDim == 2) {
247 std::array<MString, nDim + 3>
a = {
"u",
"v",
"rho",
"p",
"c"};
251 std::array<MString, nDim + 3>
a = {
"u",
"v",
"w",
"rho",
"p",
"c"};
260 for(
MInt i = 0; i < noVariables; i++) {
261 names[i] = varNames[i];
306 static constexpr MFloat referenceTemp = 298.0;
307 static constexpr MFloat transitionTemp = 1000.0;
309 static constexpr MInt totalNumberCoefficientsPerSpecies = 15;
310 static constexpr MInt noNASACoefficients = 7;
311 static constexpr MInt noNASACoefficientsCpPolynomial = 5;
319 MFloat* lowTempIntegrationConstantsEnergy =
nullptr;
320 MFloat* highTempIntegrationConstantsEnergy =
nullptr;
322 MFloat* lowTempIntegrationConstantsEnthalpy =
nullptr;
323 MFloat* highTempIntegrationConstantsEnthalpy =
nullptr;
340 static const MInt Segfault = std::numeric_limits<MInt>::min();
347 static constexpr MInt LAMBDA = 1;
349 static constexpr MInt W_MEAN = 3;
356 const MInt noThermalDiffusionCoefficients);
367 static constexpr MInt noVariables = 2;
369 static constexpr MInt GAMMA = 0;
370 static constexpr MInt W_MEAN = 1;
375template <MInt stencil>
377 const MFloat*
const leftVars,
const MFloat*
const rightVars,
380 const MFloat CP = srfcCoeff[SC->CP];
383 MFloat fMeanMolarWeightL = 0.0;
384 MFloat fMeanMolarWeightR = 0.0;
386 for(
MUint s = 0; s < PV->m_noSpecies; ++s) {
387 fMeanMolarWeightL += leftVars[PV->Y[s]] * m_species->fMolarMass[s];
388 fMeanMolarWeightR += rightVars[PV->Y[s]] * m_species->fMolarMass[s];
391 const MFloat meanMolarWeightL = F1 / fMeanMolarWeightL;
392 const MFloat meanMolarWeightR = F1 / fMeanMolarWeightR;
393 const MFloat specificGasConstantL = m_gasConstant * fMeanMolarWeightL;
394 const MFloat specificGasConstantR = m_gasConstant * fMeanMolarWeightR;
395 const MFloat CVL = CP - specificGasConstantL;
396 const MFloat CVR = CP - specificGasConstantR;
397 const MFloat gammaL = CP / CVL;
398 const MFloat gammaR = CP / CVR;
402 const MFloat RHOL = leftVars[PV->RHO];
403 const MFloat PL = leftVars[PV->P];
404 const MFloat AL = sqrt(gammaL *
mMax(MFloatEps, PL /
mMax(MFloatEps, RHOL)));
405 const MFloat ML = leftVars[orientation] / AL;
407 const MFloat RHOR = rightVars[PV->RHO];
408 const MFloat PR = rightVars[PV->P];
409 const MFloat AR = sqrt(gammaR *
mMax(MFloatEps, PR /
mMax(MFloatEps, RHOR)));
410 const MFloat MR = rightVars[orientation] / AR;
413 const MFloat MLR = 0.5 * (ML + MR);
414 const MFloat PLR = PL * (0.5 + upwindCoefficient * ML) + PR * (0.5 - upwindCoefficient * MR);
417 const MFloat RHO_AL = RHOL * AL;
418 const MFloat RHO_AR = RHOR * AR;
421 const MFloat RHO_U2 = 0.25 * (MLR * (RHO_AL + RHO_AR) + fabs(MLR) * (RHO_AL - RHO_AR));
422 const MFloat AbsRHO_U2 = fabs(RHO_U2);
425 const MFloat U2L = std::inner_product(&leftVars[PV->U], &leftVars[PV->U] + nDim, &leftVars[PV->U], 0.0);
426 const MFloat U2R = std::inner_product(&rightVars[PV->U], &rightVars[PV->U] + nDim, &rightVars[PV->U], 0.0);
430 MFloat sensibleEnergyL = F0;
431 this->evaluateSensibleEnergy(sensibleEnergyL, leftVars, meanMolarWeightL);
434 MFloat sensibleEnergyR = F0;
435 this->evaluateSensibleEnergy(sensibleEnergyR, rightVars, meanMolarWeightR);
437 const MFloat PLfRHOL = PL / RHOL;
438 const MFloat PRfRHOR = PR / RHOR;
440 const MFloat e0 = sensibleEnergyL + 0.5 * U2L + PLfRHOL;
441 const MFloat e1 = sensibleEnergyR + 0.5 * U2R + PRfRHOR;
443 std::array<MFloat, nDim> pFactor{};
444 pFactor[orientation] = 1.0;
446 for(
MUint n = 0; n < nDim; n++) {
447 flux[FV->RHO_VV[n]] = (RHO_U2 * (leftVars[PV->VV[n]] + rightVars[PV->VV[n]])
448 + AbsRHO_U2 * (leftVars[PV->VV[n]] - rightVars[PV->VV[n]]) + PLR * pFactor[n])
452 flux[FV->RHO_E] = (RHO_U2 * (e0 + e1) + AbsRHO_U2 * (e0 - e1)) * A;
453 flux[FV->RHO] = 2.0 * RHO_U2 * A;
455 for(
MUint s = 0; s < PV->m_noSpecies; ++s) {
456 const MFloat YsL = leftVars[PV->Y[s]];
457 const MFloat YsR = rightVars[PV->Y[s]];
458 flux[FV->RHO_Y[s]] = (RHO_U2 * (YsL + YsR) + AbsRHO_U2 * (YsL - YsR)) * A;
464 const MFloat*
const leftVars,
const MFloat*
const rightVars,
466 const MFloat PL = leftVars[PV->P];
467 const MFloat PR = rightVars[PV->P];
468 const MFloat PLR = 0.5 * (PR + PL);
470 std::array<MFloat, nDim> pFactor{};
471 pFactor[orientation] = 1.0;
473 for(
MUint n = 0; n < nDim; n++) {
474 flux[FV->RHO_VV[n]] = PLR * pFactor[n] * A;
477 flux[FV->RHO_E] = 0.0;
482 for(
MUint s = 0; s < PV->m_noSpecies; ++s) {
483 flux[FV->RHO_Y[s]] = 0.0;
493 std::vector<MFloat> dXdn(PV->m_noSpecies, F0);
494 std::vector<MFloat> J(PV->m_noSpecies, F0);
495 std::vector<MFloat> speciesSensibleEnthalpy(PV->m_noSpecies, F0);
499 const MFloat mue = srfcCoeff[SC->MU];
500 const MFloat lambda = srfcCoeff[SC->LAMBDA];
501 const MFloat meanMolarMass = srfcCoeff[SC->W_MEAN];
505 const std::array<MFloat, nDim> velocity = [&] {
506 std::array<MFloat, nDim> tmp{};
507 for(
MUint n = 0; n < nDim; n++) {
508 tmp[n] = F1B2 * (vars0[PV->VV[n]] + vars1[PV->VV[n]]);
513 const MFloat rho = F1B2 * (vars0[PV->RHO] + vars1[PV->RHO]);
514 const MFloat Frho = F1 / rho;
515 const MFloat p = F1B2 * (vars0[PV->P] + vars1[PV->P]);
518 const MFloat T = p * Frho * meanMolarMass * m_fGasConstant;
521 const MUint id0 = orientation;
522 const MUint id1 = index0[orientation];
523 const MUint id2 = index1[orientation];
525 const MBool isLowTempRegion = (T < m_NASA->transitionTemp);
526 const MFloat*
const NASAIntegralCoeffs =
527 isLowTempRegion ? ALIGNED_F(m_NASA->integralLowTemp) : ALIGNED_F(m_NASA->integralHighTemp);
528 const MFloat*
const NASAIntegralConstants = isLowTempRegion ? ALIGNED_F(m_NASA->lowTempIntegrationConstantsEnthalpy)
529 : ALIGNED_F(m_NASA->highTempIntegrationConstantsEnthalpy);
532 for(
MUint s = 0; s < PV->m_noSpecies; ++s) {
533 const MFloat speciesSpecificGasConstant = m_species->specificGasConstant[s];
535 MFloat sensibleEnthalpy = F0;
536 MInt offsetIntegralCoeffs = m_NASA->noNASACoefficientsCpPolynomial * s;
538 for(
MInt i = 4; (i < 5) && (i >= 0); --i) {
539 sensibleEnthalpy = sensibleEnthalpy * T + NASAIntegralCoeffs[offsetIntegralCoeffs + i];
542 sensibleEnthalpy *= speciesSpecificGasConstant * T;
543 sensibleEnthalpy -= NASAIntegralConstants[s];
545 speciesSensibleEnthalpy[s] = sensibleEnthalpy;
550 MFloat diffEnthalpyFlux = F0;
552 std::fill(J.begin(), J.end(), F0);
553 std::fill(dXdn.begin(), dXdn.end(), F0);
555 getSpeciesDiffusionMassFluxes(orientation, vars0, vars1, slope0, slope1, srfcCoeff, f0, f1, J, dXdn, dTdn,
559 for(
MUint s = 0; s < PV->m_noSpecies; ++s) {
560 diffEnthalpyFlux += speciesSensibleEnthalpy[s] * J[s];
563 const MFloat q = lambda * dTdn - diffEnthalpyFlux;
566 const MUint s00 = id0 * nDim + id0;
567 const MUint s01 = id0 * nDim + id1;
568 const MUint s10 = id1 * nDim + id0;
569 const MUint s11 = id1 * nDim + id1;
571 std::array<MFloat, nDim> tau{};
572 IF_CONSTEXPR(nDim == 2) {
573 tau[id0] = (mue + mue_wm)
574 * (f0 * (F4B3 * slope0[s00] - F2B3 * slope0[s11]) + f1 * (F4B3 * slope1[s00] - F2B3 * slope1[s11]));
575 tau[id1] = (mue + mue_wm) * (f0 * (slope0[s01] + slope0[s10]) + f1 * (slope1[s01] + slope1[s10]));
577 else IF_CONSTEXPR(nDim == 3) {
578 const MUint s22 = id2 * nDim + id2;
579 const MUint s02 = id0 * nDim + id2;
580 const MUint s20 = id2 * nDim + id0;
581 tau[id0] = (mue + mue_wm)
582 * (f0 * (F4B3 * slope0[s00] - F2B3 * (slope0[s11] + slope0[s22]))
583 + f1 * (F4B3 * slope1[s00] - F2B3 * (slope1[s11] + slope1[s22])));
584 tau[id1] = (mue + mue_wm) * (f0 * (slope0[s01] + slope0[s10]) + f1 * (slope1[s01] + slope1[s10]));
585 tau[id2] = (mue + mue_wm) * (f0 * (slope0[s02] + slope0[s20]) + f1 * (slope1[s02] + slope1[s20]));
589 for(
MUint n = 0; n < nDim; n++) {
590 flux[FV->RHO_VV[n]] -= A * tau[n];
592 flux[FV->RHO_E] -= A * (std::inner_product(velocity.begin(), velocity.end(), tau.begin(), 0.0) + q);
596 for(
MUint s = 0; s < PV->m_noSpecies; ++s) {
597 flux[FV->RHO_Y[s]] -= -A * J[s];
604 const MFloat*
const slope1,
const MFloat*
const srfcCoeff,
const MFloat f0,
const MFloat f1, std::vector<MFloat>& J,
605 std::vector<MFloat>& dXdn,
MFloat& dTdn,
const MBool soretEffect) {
606 std::vector<MFloat> speciesDiffusionMassFlux(PV->m_noSpecies, F0);
607 std::vector<MFloat> d(PV->m_noSpecies, F0);
608 std::vector<MFloat> VX(PV->m_noSpecies, F0);
610 const MFloat rho = F1B2 * (vars0[PV->RHO] + vars1[PV->RHO]);
611 const MFloat Frho = F1 / rho;
612 const MFloat p = F1B2 * (vars0[PV->P] + vars1[PV->P]);
615 const MFloat meanMolarMass = srfcCoeff[SC->W_MEAN];
616 const MFloat fMeanMolarMass = F1 / meanMolarMass;
619 const MFloat T = p * Frho * meanMolarMass * m_fGasConstant;
623 const MUint id0 = orientation;
625 const MUint sq0 = PV->P * nDim + id0;
626 const MUint sq1 = PV->RHO * nDim + id0;
628 const MFloat dPdn = f0 * slope0[sq0] + f1 * slope1[sq0];
629 const MFloat dRhodn = f0 * slope0[sq1] + f1 * slope1[sq1];
631 MFloat summSpeciesGradients = F0;
632 for(
MUint s = 0; s < PV->m_noSpecies; s++) {
633 const MUint sqs = PV->Y[s] * nDim + id0;
634 summSpeciesGradients += m_species->fMolarMass[s] * (f0 * slope0[sqs] + f1 * slope1[sqs]);
637 const MFloat dWdn = -
POW2(srfcCoeff[SC->W_MEAN]) * summSpeciesGradients;
639 for(
MUint s = 0; s < PV->m_noSpecies; s++) {
640 const MUint sqs = PV->Y[s] * nDim + id0;
641 const MFloat Ys = F1B2 * (vars0[PV->Y[s]] + vars1[PV->Y[s]]);
642 dXdn[s] = m_species->fMolarMass[s] * (meanMolarMass * (f0 * slope0[sqs] + f1 * slope1[sqs]) + dWdn * Ys);
645 dTdn = m_fGasConstant * (p * Frho * dWdn + (Frho * meanMolarMass * (dPdn - p * Frho * dRhodn)));
647 for(
MUint s = 0; s < PV->m_noSpecies; ++s) {
648 const MFloat Ys = F1B2 * (vars0[PV->Y[s]] + vars1[PV->Y[s]]);
649 d[s] = dXdn[s] + (meanMolarMass * m_species->fMolarMass[s] * Ys - Ys) * Fp * dPdn;
652 if(m_multiDiffusion) {
653 for(
MUint s = 0; s < PV->m_noSpecies; ++s) {
654 for(
MUint j = 0; j < PV->m_noSpecies; ++j) {
656 VX[s] += m_species->molarMass[j] * srfcCoeff[SC->D[PV->m_noSpecies * j + s]] * d[j];
659 VX[s] *= fMeanMolarMass;
661 if(soretEffect) VX[s] -= srfcCoeff[SC->DT[s]] * meanMolarMass * Frho * m_species->fMolarMass[s] * FT * dTdn;
663 J[s] = rho * m_species->molarMass[s] * fMeanMolarMass * VX[s];
666 for(
MUint s = 0; s < PV->m_noSpecies; ++s) {
668 VX[s] = -srfcCoeff[SC->D[s]] * dXdn[s];
670 J[s] = rho * m_species->molarMass[s] * fMeanMolarMass * VX[s];
677 const MFloat*
const avarsCell) {
678 const MFloat fRho = F1 / cvarsCell[CV->RHO];
681 for(
MInt n = 0; n < nDim; ++n) {
682 pvarsCell[PV->VV[n]] = cvarsCell[CV->RHO_VV[n]] * fRho;
683 velPOW2 +=
POW2(pvarsCell[PV->VV[n]]);
687 pvarsCell[PV->RHO] = cvarsCell[CV->RHO];
690 for(
MUint s = 0; s < PV->m_noSpecies; ++s) {
691 pvarsCell[PV->Y[s]] =
mMax(F0,
mMin(F1, cvarsCell[CV->RHO_Y[s]] * fRho));
695 iterateTemperature(T, cvarsCell, pvarsCell, avarsCell, velPOW2);
697 pvarsCell[PV->P] = pvarsCell[PV->RHO] * T * m_gasConstant / avarsCell[AV->W_MEAN];
700 if(isnan(pvarsCell[PV->P]) || isnan(pvarsCell[PV->RHO]) || isnan(T)) {
701 std::cout <<
"FvSysEqnDetChem<nDim>::computePrimitiveVariables has NaN value. T: " << T
702 <<
", rho: " << pvarsCell[PV->RHO] <<
", p: " << pvarsCell[PV->P] << std::endl;
705 if(pvarsCell[PV->P] < 0 || pvarsCell[PV->RHO] < 0 || T < 0) {
706 std::cout <<
"FvSysEqnDetChem<nDim>::computePrimitiveVariables has negative value. T: " << T
707 <<
", rho: " << pvarsCell[PV->RHO] <<
", p: " << pvarsCell[PV->P] << std::endl;
725 const MFloat*
const NotUsed(pvarsCell),
727 const MFloat energyZeroLevel = m_gasConstant * m_species->referenceTemp / avarsCell[AV->W_MEAN];
729 MFloat LHS = cvarsCell[CV->RHO_E] / cvarsCell[CV->RHO] - F1B2 * velPOW2 + energyZeroLevel;
735 for(
MInt it = 0; it < 10; ++it) {
736 const MBool isLowTempRegion = (T_n < m_NASA->transitionTemp);
738 const MFloat*
const NASACoeffs = isLowTempRegion ? ALIGNED_F(m_NASA->lowTemp) : ALIGNED_F(m_NASA->highTemp);
739 const MFloat*
const NASAIntegralCoeffs =
740 isLowTempRegion ? ALIGNED_F(m_NASA->integralLowTemp) : ALIGNED_F(m_NASA->integralHighTemp);
741 const MFloat*
const NASAIntegralConstants = isLowTempRegion ? ALIGNED_F(m_NASA->lowTempIntegrationConstantsEnergy)
742 : ALIGNED_F(m_NASA->highTempIntegrationConstantsEnergy);
744 MFloat T_nPlus1 = F0, f_xi = F0, fS_xi = F0;
745 for(
MUint s = 0; s < PV->m_noSpecies; s++) {
746 const MInt offsetIntegralCoeffs = m_NASA->noNASACoefficientsCpPolynomial * s;
747 const MInt offsetNASAPolynomial = m_NASA->noNASACoefficients * s;
748 const MFloat Y_s = cvarsCell[CV->RHO_Y[s]] / cvarsCell[CV->RHO];
749 const MFloat specificGasConstant = m_species->specificGasConstant[s];
752 MFloat NASAIntegralPolynomial = F0, NASAPolynomial = F0;
753 for(
MInt i = 4; (i < 5) && (i >= 0); i--) {
754 NASAIntegralPolynomial = NASAIntegralPolynomial * T_n + NASAIntegralCoeffs[offsetIntegralCoeffs + i];
755 NASAPolynomial = NASAPolynomial * T_n + NASACoeffs[offsetNASAPolynomial + i];
758 NASAIntegralPolynomial *= specificGasConstant;
759 NASAPolynomial *= specificGasConstant;
761 NASAIntegralPolynomial = (NASAIntegralPolynomial - specificGasConstant) * T_n;
762 NASAPolynomial -= specificGasConstant;
764 f_xi += NASAIntegralPolynomial * Y_s;
765 f_xi -= NASAIntegralConstants[s] * Y_s;
766 fS_xi += NASAPolynomial * Y_s;
770 T_nPlus1 = T_n - (f_xi / fS_xi);
787 const MFloat& meanMolarMass) {
788 const MFloat T = pvarsCell[PV->P] / pvarsCell[PV->RHO] * meanMolarMass * m_fGasConstant;
789 const MBool isLowTempRegion = (T < m_NASA->transitionTemp);
791 const MFloat*
const NASAIntegralCoeffs =
792 isLowTempRegion ? ALIGNED_F(m_NASA->integralLowTemp) : ALIGNED_F(m_NASA->integralHighTemp);
793 const MFloat*
const NASAIntegralConstants = isLowTempRegion ? ALIGNED_F(m_NASA->lowTempIntegrationConstantsEnergy)
794 : ALIGNED_F(m_NASA->highTempIntegrationConstantsEnergy);
796 for(
MUint s = 0; s < PV->m_noSpecies; s++) {
797 MInt offsetIntegralCoeffs = m_NASA->noNASACoefficientsCpPolynomial * s;
800 MFloat sensibleEnergySpecies = F0, NASAIntegralPolynomial = F0;
801 for(
MInt i = 4; (i < 5) && (i >= 0); --i) {
802 NASAIntegralPolynomial = NASAIntegralPolynomial * T + NASAIntegralCoeffs[offsetIntegralCoeffs + i];
805 NASAIntegralPolynomial *= m_species->specificGasConstant[s];
806 NASAIntegralPolynomial = (NASAIntegralPolynomial - m_species->specificGasConstant[s]) * T;
807 sensibleEnergySpecies = NASAIntegralPolynomial - NASAIntegralConstants[s];
808 sensibleEnergy += sensibleEnergySpecies * pvarsCell[PV->Y[s]];
812 sensibleEnergy -= m_gasConstant * m_NASA->referenceTemp / meanMolarMass;
818 const MFloat*
const avarsCell) {
821 for(
MInt vel = 0; vel < nDim; ++vel) {
822 const MFloat v = pvarsCell[vel];
823 cvarsCell[vel] = v * pvarsCell[PV->RHO];
828 cvarsCell[CV->RHO] = pvarsCell[PV->RHO];
830 MFloat sensibleEnergy = F0;
831 evaluateSensibleEnergy(sensibleEnergy, pvarsCell, avarsCell[AV->W_MEAN]);
833 cvarsCell[CV->RHO_E] = pvarsCell[PV->RHO] * sensibleEnergy + F1B2 * pvarsCell[PV->RHO] * velPOW2;
836 for(
MUint s = 0; s < PV->m_noSpecies; ++s) {
837 cvarsCell[CV->RHO_Y[s]] = pvarsCell[PV->Y[s]] * pvarsCell[PV->RHO];
860 const MFloat& m_timeStep,
const MFloat& NotUsed(cellVolume),
const MFloat*
const pvarsCell,
861 const MFloat*
const avarsCell,
MFloat*
const reactionRatesCell, Cantera::IdealGasReactor* zeroD_reactor,
862 Cantera::ReactorNet* zeroD_reactorNet, std::shared_ptr<Cantera::Solution> sol,
863 std::shared_ptr<Cantera::ThermoPhase> gas) {
864 const MFloat p = pvarsCell[PV->P];
865 const MFloat rho = pvarsCell[PV->RHO];
866 const MFloat meanMolarMass = avarsCell[AV->W_MEAN];
867 const MFloat T = p / rho * meanMolarMass * m_fGasConstant;
869 gas->setState_TPY(T, p, &pvarsCell[PV->Y[0]]);
871 zeroD_reactor->insert(sol);
872 zeroD_reactorNet->setInitialTime(0.0);
874 const MFloat timeStep = m_timeStep;
875 const MFloat reactorDensity_t0 = zeroD_reactor->density();
877 zeroD_reactorNet->advance(timeStep);
879 auto reactorMassFractions = zeroD_reactor->massFractions();
880 const MFloat reactorDensity = zeroD_reactor->density();
882 MFloat C_k_t_0, C_k_deltaT;
883 for(
MUint s = 0; s < PV->m_noSpecies; s++) {
884 C_k_t_0 = pvarsCell[PV->Y[s]] * reactorDensity_t0 * m_species->fMolarMass[s];
885 C_k_deltaT = reactorMassFractions[s] * reactorDensity * m_species->fMolarMass[s];
886 reactionRatesCell[s] = ((C_k_deltaT - C_k_t_0) / (timeStep)) * m_species->molarMass[s];
905 std::shared_ptr<Cantera::ThermoPhase> gas,
906 std::shared_ptr<Cantera::Transport> trans) {
908 std::vector<MFloat> Y_k(PV->m_noSpecies, F0);
909 MFloat fMeanMolarMass = F0;
910 for(
MUint s = 0; s < PV->m_noSpecies; ++s) {
911 Y_k[s] = F1B2 * (vars0[PV->Y[s]] + vars1[PV->Y[s]]);
912 fMeanMolarMass += Y_k[s] * m_species->fMolarMass[s];
915 srfcCoeff[SC->W_MEAN] = F1 / fMeanMolarMass;
918 if(RKStep == 0 || m_computeSrfcCoeffsEveryRKStep) {
919 const MFloat p = F1B2 * (vars0[PV->P] + vars1[PV->P]);
920 const MFloat rho = F1B2 * (vars0[PV->RHO] + vars1[PV->RHO]);
921 const MFloat T = p / rho * srfcCoeff[SC->W_MEAN] * m_fGasConstant;
924 gas->setState_TPY(T, p, &Y_k[0]);
926 srfcCoeff[SC->CP] = gas->cp_mass();
928 srfcCoeff[SC->MU] = trans->viscosity();
929 srfcCoeff[SC->LAMBDA] = trans->thermalConductivity();
931 if(m_multiDiffusion) {
933 trans->getMultiDiffCoeffs(PV->m_noSpecies, &srfcCoeff[SC->D[0]]);
934 trans->getThermalDiffCoeffs(&srfcCoeff[SC->DT[0]]);
936 trans->getMixDiffCoeffs(&srfcCoeff[SC->D[0]]);
951 std::shared_ptr<Cantera::ThermoPhase> gas) {
952 const MFloat T = pvarsCell[PV->P] / pvarsCell[PV->RHO] * avarsCell[AV->W_MEAN] * m_fGasConstant;
954 gas->setState_TPY(T, pvarsCell[PV->P], &pvarsCell[PV->Y[0]]);
956 const MFloat Cp = gas->cp_mass();
957 const MFloat Cv = Cp - m_gasConstant / avarsCell[AV->W_MEAN];
959 avarsCell[AV->GAMMA] = Cp / Cv;
974inline std::vector<std::vector<MFloat>>
976 const MFloat*
const avarsCell,
const MFloat*
const slopesCell) {
978 for(
MInt i = 0; i < nDim; i++) {
979 U2 +=
POW2(pvarsCell[PV->VV[i]]);
982 std::vector<std::vector<MFloat>> dQ(PV->noVariables, std::vector<MFloat>(nDim));
983 for(
MInt d = 0; d < nDim; d++) {
984 MFloat term1 = F0, term2 = F0, term3 = F0;
985 const MFloat meanMolarMass = avarsCell[AV->W_MEAN];
986 const MFloat T = pvarsCell[PV->P] / pvarsCell[PV->RHO] * meanMolarMass * m_fGasConstant;
987 const MBool isLowTempRegion = (T < m_NASA->transitionTemp);
989 const MFloat*
const NASACoeffs = isLowTempRegion ? ALIGNED_F(m_NASA->lowTemp) : ALIGNED_F(m_NASA->highTemp);
990 const MFloat*
const NASAIntegralCoeffs =
991 isLowTempRegion ? ALIGNED_F(m_NASA->integralLowTemp) : ALIGNED_F(m_NASA->integralHighTemp);
992 const MFloat*
const NASAIntegralConstants = isLowTempRegion ? ALIGNED_F(m_NASA->lowTempIntegrationConstantsEnergy)
993 : ALIGNED_F(m_NASA->highTempIntegrationConstantsEnergy);
997 MFloat sensibleEnergy = F0;
998 dT0Term += slopesCell[PV->RHO * nDim + d] * m_gasConstant * m_NASA->referenceTemp / meanMolarMass;
999 for(
MUint s = 0; s < PV->m_noSpecies; s++) {
1000 dT0Term += pvarsCell[PV->RHO] * m_gasConstant * m_NASA->referenceTemp * slopesCell[PV->Y[s] * nDim + d]
1001 * m_species->fMolarMass[s];
1004 MFloat summ_YIntCvdT = F0;
1005 MFloat summ_dYIntCvdT = F0;
1006 for(
MUint s = 0; s < PV->m_noSpecies; s++) {
1007 const MInt offsetIntegralCoeffs = m_NASA->noNASACoefficientsCpPolynomial * s;
1011 MFloat NASAIntegralPolynomial = F0;
1014 for(
MInt i = 4; i >= 0; --i) {
1015 NASAIntegralPolynomial = NASAIntegralPolynomial * T + NASAIntegralCoeffs[offsetIntegralCoeffs + i];
1018 NASAIntegralPolynomial *= m_species->specificGasConstant[s];
1019 NASAIntegralPolynomial = (NASAIntegralPolynomial - m_species->specificGasConstant[s]) * T;
1020 IntCvdT = NASAIntegralPolynomial - NASAIntegralConstants[s];
1021 sensibleEnergy += pvarsCell[PV->Y[s]] * IntCvdT;
1022 summ_YIntCvdT += IntCvdT * pvarsCell[PV->Y[s]];
1023 summ_dYIntCvdT += IntCvdT * slopesCell[PV->Y[s] * nDim + d];
1026 term1 = slopesCell[PV->RHO * nDim + d] * summ_YIntCvdT;
1027 term2 = pvarsCell[PV->RHO] * summ_dYIntCvdT;
1030 MFloat summSpeciesGradients = F0;
1031 for(
MUint s = 0; s < PV->m_noSpecies; s++) {
1032 summSpeciesGradients += m_species->fMolarMass[s] * slopesCell[PV->Y[s] * nDim + d];
1035 const MFloat dW_dx = -(
POW2(avarsCell[AV->W_MEAN])) * summSpeciesGradients;
1037 const MFloat dT_dx = m_fGasConstant
1038 * (pvarsCell[PV->P] / pvarsCell[PV->RHO] * dW_dx
1039 + F1 / pvarsCell[PV->RHO] * meanMolarMass
1040 * (slopesCell[PV->P * nDim + d]
1041 - pvarsCell[PV->P] / pvarsCell[PV->RHO] * slopesCell[PV->RHO * nDim + d]));
1045 for(
MUint s = 0; s < PV->m_noSpecies; s++) {
1047 const MInt offsetNASAPolynomial = m_NASA->noNASACoefficients * s;
1072 for(
MInt i = 4; i >= 0; --i) {
1073 Cv = Cv * T + NASACoeffs[offsetNASAPolynomial + i];
1077 Cv *= m_species->specificGasConstant[s];
1080 Cv -= m_species->specificGasConstant[s];
1082 term3sub2 += pvarsCell[PV->RHO] * pvarsCell[PV->Y[s]] * Cv * dT_dx;
1087 MFloat sensibleEnergyTerm = term1 + term2 + term3 - dT0Term;
1089 MFloat velocityTerm = F1B2 * U2 * slopesCell[PV->RHO * nDim + d];
1091 for(
MInt j = 0; j < nDim; j++) {
1092 velocityTerm += pvarsCell[PV->RHO] * pvarsCell[PV->VV[j]] * slopesCell[PV->VV[j] * nDim + d];
1095 dQ[CV->RHO_E][d] = sensibleEnergyTerm + velocityTerm;
1097 dQ[CV->RHO][d] = slopesCell[PV->RHO * nDim + d];
1099 for(
MInt j = 0; j < nDim; j++) {
1100 dQ[CV->RHO_VV[j]][d] =
1101 pvarsCell[PV->VV[j]] * slopesCell[PV->RHO * nDim + d] + pvarsCell[PV->RHO] * slopesCell[PV->VV[j] * nDim + d];
1103 for(
MUint s = 0; s < PV->m_noSpecies; ++s) {
1104 dQ[CV->RHO_Y[s]][d] =
1105 pvarsCell[PV->Y[s]] * slopesCell[PV->RHO * nDim + d] + pvarsCell[PV->RHO] * slopesCell[PV->Y[s] * nDim + d];
1121 MFloat fMeanMolarWeight = F0;
1122 for(
MUint s = 0; s < PV->m_noSpecies; ++s) {
1123 MFloat fRho = F1 / cvarsCell[CV->RHO];
1124 const MFloat Y_s = fRho * cvarsCell[CV->RHO_Y[s]];
1125 fMeanMolarWeight += Y_s * m_species->fMolarMass[s];
1127 avarsCell[AV->W_MEAN] = (F1 / fMeanMolarWeight);
1139 MFloat fMeanMolarWeight = F0;
1140 for(
MUint s = 0; s < PV->m_noSpecies; ++s) {
1141 fMeanMolarWeight += pvarsCell[PV->Y[s]] * m_species->fMolarMass[s];
1143 avarsCell[AV->W_MEAN] = (F1 / fMeanMolarWeight);
1148 MInt indexOxidizer = m_species->speciesMap[m_oxidizer];
1149 MInt indexFuel = m_species->speciesMap[m_fuel];
1151 MFloat stochiometricMolarMassRatio = m_species->molarMass[indexFuel] / m_species->molarMass[indexOxidizer];
1153 MFloat phi = (Y[indexFuel] / Y[indexOxidizer]) / (m_fuelOxidizerStochiometricRatio * stochiometricMolarMassRatio);
1194 const MString majorSpecies =
"N2";
1195 MInt majorSpeciesIndex;
1197 const MFloat referenceTemp = 298.0;
1199 std::map<std::string, MInt> speciesMap;
1201 std::vector<MString> speciesName;
1202 MFloat* molarMass =
nullptr;
1203 MFloat* fMolarMass =
nullptr;
1204 MFloat* specificGasConstant =
nullptr;
1205 MFloat* fSpecificGasConstant =
nullptr;
1206 MFloat* standardHeatFormation =
nullptr;
1212 static const MInt Segfault = std::numeric_limits<MInt>::min();
1218 static constexpr MInt MU = 0;
1219 static constexpr MInt LAMBDA = 1;
1220 static constexpr MInt CP = 2;
1221 static constexpr MInt W_MEAN = 3;
1222 static constexpr MInt D0 = 4;
1231 static constexpr MInt noVariables = 2;
1233 static constexpr MInt GAMMA = 0;
1234 static constexpr MInt W_MEAN = 1;
Class containing the special methods of the detailed chemistry formulation. Inherits from the Navier-...
void computePrimitiveVariables(const MFloat *const cvarsCell, MFloat *const pvarsCell, const MFloat *const avarsCell)
void computeConservativeVariables(const MFloat *const pvarsCell, MFloat *const cvarsCell, const MFloat *const avarsCell)
void AusmBndryCorrection(const MInt orientation, const MFloat A, const MFloat *const leftVars, const MFloat *const rightVars, MFloat *const flux)
static constexpr std::array< MInt, nDim > getArray012()
void viscousFluxFivePoint(const MInt orientation, const MFloat A, const MFloat *const vars0, const MFloat *const vars1, const MFloat *const slope0, const MFloat *const slope1, const MFloat *const srfcCoeff, const MFloat f0, const MFloat f1, MFloat *const flux)
void Ausm(const MInt orientation, const MFloat upwindCoefficient, const MFloat A, const MFloat *const leftVars, const MFloat *const rightVars, const MFloat *const srfcCoeff, MFloat *const flux)
void computeSurfaceCoefficients(const MInt RKStep, const MFloat *const vars0, const MFloat *const vars1, MFloat *const srfcCoeff, std::shared_ptr< Cantera::ThermoPhase > gas, std::shared_ptr< Cantera::Transport > trans)
Computes the transport coefficients at the surface. These are then used in the computation of the sur...
MInt m_noSurfaceCoefficients
void computeMeanMolarWeight_CV(const MFloat *const pvarsCell, MFloat *const avarsCell)
Computes the mean molar weight from the conservative variables at the cell.
void readProperties()
Reads important variable values from the properties.toml file.
void computeMeanMolarWeight_PV(const MFloat *const, MFloat *const)
MFloat m_fuelOxidizerStochiometricRatio
ConservativeVariables * CV
void viscousFlux(const MInt, const MFloat, const MBool, const MFloat *const, const MFloat *const, const MFloat *const, const MFloat *const, const MFloat *const, const MFloat *const, const MFloat *const, const MFloat *const, const MFloat *const, const MFloat, const MFloat, MFloat *const)
void iterateTemperature(MFloat &T, const MFloat *const cvarsCell, const MFloat *const pvarsCell, const MFloat *const avarsCell, const MFloat &velPOW2)
Iterates the temperature from the sensible energy. Iteration is necessary, since the heat capacities ...
void allocateNoDiffusionCoefficients(const MInt)
Allocates the correct number of diffusion coefficients depending on the chosen diffusion model....
MInt m_noDiffusionCoefficients
MBool m_computeSrfcCoeffsEveryRKStep
void viscousFlux(const MInt orientation, const MFloat A, const MFloat *const vars0, const MFloat *const vars1, const MFloat *const slope0, const MFloat *const slope1, const MFloat *const srfcCoeff, const MFloat f0, const MFloat f1, MFloat *const flux)
void computeMeanMolarWeight_PV(const MFloat *const pvarsCell, MFloat *const avarsCell)
Computes the mean molar weight from the primitive variables at the cell.
MString m_reactionMechanism
FvSysEqnDetChem(const MInt solverId, const MInt noSpecies)
SpeciesProperties * m_species
NASACoefficients * m_NASA
MInt m_noThermalDiffusionCoefficients
void getSpeciesDiffusionMassFluxes(const MInt orientation, const MFloat *const vars0, const MFloat *const vars1, const MFloat *const slope0, const MFloat *const slope1, const MFloat *const srfcCoeff, const MFloat f0, const MFloat f1, std::vector< MFloat > &J, std::vector< MFloat > &dXdn, MFloat &dTdn, const MBool soretEffect)
MFloat computePhi(const MFloat *const Y)
void evaluateSensibleEnergy(MFloat &sensibleEnergy, const MFloat *const pvarsCell, const MFloat &meanMolarMass)
Computes the sensible energy. Species sensible energy is computed as: e_s = Int(cv(T)dT) - R*T_ref/W_...
static constexpr MBool hasAV
void computeGamma(const MFloat *const pvarsCell, MFloat *const avarsCell, std::shared_ptr< Cantera::ThermoPhase > gas)
Computes gamma at the cell. Used for the computation of the time step.
static constexpr MBool hasSC
void evaluateSensibleEnergy(MFloat &, const MFloat *const, const MFloat &)
std::vector< std::vector< MFloat > > conservativeSlopes(const MFloat *const pvarsCell, const MFloat *const cvarsCell, const MFloat *const avarsCell, const MFloat *const slopesCell)
Reconstructs the conservative slopes from the primitive variables and primitive slopes at the cell....
void computeSpeciesReactionRates(const MFloat &m_timeStep, const MFloat &cellVolume, const MFloat *const pvarsCell, const MFloat *const avarsCell, MFloat *const reactionRatesCell, Cantera::IdealGasReactor *zeroD_reactor, Cantera::ReactorNet *zeroD_reactorNet, std::shared_ptr< Cantera::Solution > sol, std::shared_ptr< Cantera::ThermoPhase > gas)
Computes the species reaction rates. A reactor is constructed at each cell, with equal thermodynamic ...
void computeMeanMolarWeight_CV(const MFloat *const, MFloat *const)
MFloat m_sutherlandConstant
static constexpr std::array< MInt, nDim > getArray012()
MFloat m_sutherlandPlusOneThermal
MFloat m_sutherlandPlusOne
MFloat m_referenceTemperature
MFloat m_F1BGammaMinusOne
static const MUint index1[nDim]
static const MUint index0[nDim]
MFloat m_sutherlandConstantThermal
constexpr Real POW2(const Real x)
constexpr T mMin(const T &x, const T &y)
constexpr T mMax(const T &x, const T &y)
std::basic_string< char > MString
Static indices for accessing additional variables.
Static indices for accessing conservative variables in nDim spatial dimensions.
Static indices for accessing flux variables. In this SysEqn identical to the conservative variables.
Stores all NASA coefficients. NASA coefficients are used to compute the cp and cv values....
Static indices for accessing primitive variables in nDim spatial dimensions.
void getPrimitiveVariableNames(MString *names)
Struct for storing all relevant species information, which is read from a given mechanism file.
std::vector< MString > speciesName
std::map< std::string, MInt > speciesMap
Static indices for accessing surface coefficients.
const MInt m_noThermalDiffusionCoefficients
const MInt m_noDiffusionCoefficients
const MInt m_noSurfaceCoefficients