/** * Install a NASA9 polynomial thermodynamic property * parameterization for species k into a SpeciesThermo instance. * This is called by method installThermoForSpecies if a NASA9 * block is found in the XML input. */ static void installNasa9ThermoFromXML(std::string speciesName, SpeciesThermo& sp, int k, const std::vector<XML_Node*>& tp) { const XML_Node * fptr = tp[0]; int nRegTmp = tp.size(); int nRegions = 0; vector_fp cPoly; Nasa9Poly1 *np_ptr = 0; std::vector<Nasa9Poly1 *> regionPtrs; doublereal tmin, tmax, pref = OneAtm; // Loop over all of the possible temperature regions for (int i = 0; i < nRegTmp; i++) { fptr = tp[i]; if (fptr) { if (fptr->name() == "NASA9") { if (fptr->hasChild("floatArray")) { tmin = fpValue((*fptr)["Tmin"]); tmax = fpValue((*fptr)["Tmax"]); if ((*fptr).hasAttrib("P0")) { pref = fpValue((*fptr)["P0"]); } if ((*fptr).hasAttrib("Pref")) { pref = fpValue((*fptr)["Pref"]); } getFloatArray(fptr->child("floatArray"), cPoly, false); if (cPoly.size() != 9) { throw CanteraError("installNasa9ThermoFromXML", "Expected 9 coeff polynomial"); } np_ptr = new Nasa9Poly1(k, tmin, tmax, pref, DATA_PTR(cPoly)); regionPtrs.push_back(np_ptr); nRegions++; } } } } if (nRegions == 0) { throw UnknownSpeciesThermoModel("installThermoForSpecies", speciesName, " " ); } else if (nRegions == 1) { sp.install_STIT(np_ptr); } else { Nasa9PolyMultiTempRegion* npMulti_ptr = new Nasa9PolyMultiTempRegion(regionPtrs); sp.install_STIT(npMulti_ptr); } }
/** * Install a NASA96 polynomial thermodynamic property * parameterization for species k into a SpeciesThermo instance. */ static void installNasa96ThermoFromXML(std::string speciesName, SpeciesThermo& sp, int k, const XML_Node* f0ptr, const XML_Node* f1ptr) { doublereal tmin0, tmax0, tmin1, tmax1, tmin, tmid, tmax; const XML_Node& f0 = *f0ptr; bool dualRange = false; if (f1ptr) {dualRange = true;} tmin0 = fpValue(f0["Tmin"]); tmax0 = fpValue(f0["Tmax"]); tmin1 = tmax0; tmax1 = tmin1 + 0.0001; if (dualRange) { tmin1 = fpValue((*f1ptr)["Tmin"]); tmax1 = fpValue((*f1ptr)["Tmax"]); } doublereal p0 = OneAtm; if (f0.hasAttrib("P0")) { p0 = fpValue(f0["P0"]); } if (f0.hasAttrib("Pref")) { p0 = fpValue(f0["Pref"]); } vector_fp c0, c1; if (fabs(tmax0 - tmin1) < 0.01) { tmin = tmin0; tmid = tmax0; tmax = tmax1; getFloatArray(f0.child("floatArray"), c0, false); if (dualRange) getFloatArray(f1ptr->child("floatArray"), c1, false); else { c1.resize(7,0.0); copy(c0.begin(), c0.end(), c1.begin()); } } else if (fabs(tmax1 - tmin0) < 0.01) { tmin = tmin1; tmid = tmax1; tmax = tmax0; getFloatArray(f1ptr->child("floatArray"), c0, false); getFloatArray(f0.child("floatArray"), c1, false); } else { throw CanteraError("installNasaThermo", "non-continuous temperature ranges."); } array_fp c(15); c[0] = tmid; c[1] = c0[5]; c[2] = c0[6]; copy(c0.begin(), c0.begin()+5, c.begin() + 3); c[8] = c1[5]; c[9] = c1[6]; copy(c1.begin(), c1.begin()+5, c.begin() + 10); sp.install(speciesName, k, NASA, &c[0], tmin, tmax, p0); }
void SpeciesThermoFactory::installThermoForSpecies (size_t k, const XML_Node& speciesNode, ThermoPhase* th_ptr, SpeciesThermo& spthermo, const XML_Node* phaseNode_ptr) const { SpeciesThermoInterpType* stit = newSpeciesThermoInterpType(speciesNode); stit->validate(speciesNode["name"]); stit->setIndex(k); spthermo.install_STIT(stit); }
void SpeciesThermoFactory::installThermoForSpecies (size_t k, const XML_Node& speciesNode, ThermoPhase* th_ptr, SpeciesThermo& spthermo, const XML_Node* phaseNode_ptr) const { shared_ptr<SpeciesThermoInterpType> stit( newSpeciesThermoInterpType(speciesNode.child("thermo"))); stit->validate(speciesNode["name"]); spthermo.install_STIT(k, stit); }
/** * Install a Shomate polynomial thermodynamic property * parameterization for species k. */ static void installShomateThermoFromXML(std::string speciesName, SpeciesThermo& sp, int k, const XML_Node* f0ptr, const XML_Node* f1ptr) { doublereal tmin0, tmax0, tmin1, tmax1, tmin, tmid, tmax; const XML_Node& f0 = *f0ptr; bool dualRange = false; if (f1ptr) {dualRange = true;} tmin0 = fpValue(f0["Tmin"]); tmax0 = fpValue(f0["Tmax"]); tmin1 = tmax0; tmax1 = tmin1 + 0.0001; if (dualRange) { tmin1 = fpValue((*f1ptr)["Tmin"]); tmax1 = fpValue((*f1ptr)["Tmax"]); } vector_fp c0, c1; if (fabs(tmax0 - tmin1) < 0.01) { tmin = tmin0; tmid = tmax0; tmax = tmax1; getFloatArray(f0.child("floatArray"), c0, false); if (dualRange) getFloatArray(f1ptr->child("floatArray"), c1, false); else { c1.resize(7,0.0); copy(c0.begin(), c0.begin()+7, c1.begin()); } } else if (fabs(tmax1 - tmin0) < 0.01) { tmin = tmin1; tmid = tmax1; tmax = tmax0; getFloatArray(f1ptr->child("floatArray"), c0, false); getFloatArray(f0.child("floatArray"), c1, false); } else { throw CanteraError("installShomateThermoFromXML", "non-continuous temperature ranges."); } array_fp c(15); c[0] = tmid; doublereal p0 = OneAtm; copy(c0.begin(), c0.begin()+7, c.begin() + 1); copy(c1.begin(), c1.begin()+7, c.begin() + 8); sp.install(speciesName, k, SHOMATE, &c[0], tmin, tmax, p0); }
/** * Install a constant-cp thermodynamic property * parameterization for species k. */ static void installSimpleThermoFromXML(std::string speciesName, SpeciesThermo& sp, int k, const XML_Node& f) { doublereal tmin, tmax; tmin = fpValue(f["Tmin"]); tmax = fpValue(f["Tmax"]); if (tmax == 0.0) tmax = 1.0e30; vector_fp c(4); c[0] = getFloat(f, "t0", "toSI"); c[1] = getFloat(f, "h0", "toSI"); c[2] = getFloat(f, "s0", "toSI"); c[3] = getFloat(f, "cp0", "toSI"); doublereal p0 = OneAtm; sp.install(speciesName, k, SIMPLE, &c[0], tmin, tmax, p0); }
void installMu0ThermoFromXML(const std::string& speciesName, SpeciesThermo<ValAndDerivType>& sp, size_t k, const XML_Node* Mu0Node_ptr) { doublereal tmin, tmax; bool dimensionlessMu0Values = false; const XML_Node& Mu0Node = *Mu0Node_ptr; tmin = fpValue(Mu0Node["Tmin"]); tmax = fpValue(Mu0Node["Tmax"]); doublereal pref = fpValue(Mu0Node["Pref"]); doublereal h298 = 0.0; if (Mu0Node.hasChild("H298")) { h298 = getFloat(Mu0Node, "H298", "actEnergy"); } size_t numPoints = 1; if (Mu0Node.hasChild("numPoints")) { numPoints = getInteger(Mu0Node, "numPoints"); } vector_fp cValues(numPoints); const XML_Node* valNode_ptr = getByTitle(const_cast<XML_Node&>(Mu0Node), "Mu0Values"); if (!valNode_ptr) { throw CanteraError("installMu0ThermoFromXML", "missing required while processing " + speciesName); } getFloatArray(*valNode_ptr, cValues, true, "actEnergy"); /* * Check to see whether the Mu0's were input in a dimensionless * form. If they were, then the assumed temperature needs to be * adjusted from the assumed T = 273.15 */ string uuu = (*valNode_ptr)["units"]; if (uuu == "Dimensionless") { dimensionlessMu0Values = true; } size_t ns = cValues.size(); if (ns != numPoints) { throw CanteraError("installMu0ThermoFromXML", "numPoints inconsistent while processing " + speciesName); } vector_fp cTemperatures(numPoints); const XML_Node* tempNode_ptr = getByTitle(const_cast<XML_Node&>(Mu0Node), "Mu0Temperatures"); if (!tempNode_ptr) { throw CanteraError("installMu0ThermoFromXML", "missing required while processing + " + speciesName); } getFloatArray(*tempNode_ptr, cTemperatures, false); ns = cTemperatures.size(); if (ns != numPoints) { throw CanteraError("installMu0ThermoFromXML", "numPoints inconsistent while processing " + speciesName); } /* * Fix up dimensionless Mu0 values if input */ if (dimensionlessMu0Values) { for (size_t i = 0; i < numPoints; i++) { cValues[i] *= cTemperatures[i] / 273.15; } } vector_fp c(2 + 2 * numPoints); c[0] = static_cast<double>(numPoints); c[1] = h298; for (size_t i = 0; i < numPoints; i++) { c[2 + i * 2] = cTemperatures[i]; c[2 + i * 2 + 1] = cValues[i]; } sp.install(speciesName, k, MU0_INTERP, &c[0], tmin, tmax, pref); }
static void installMinEQ3asShomateThermoFromXML(std::string speciesName, ThermoPhase *th_ptr, SpeciesThermo& sp, int k, const XML_Node* MinEQ3node) { array_fp coef(15), c0(7, 0.0); std::string astring = (*MinEQ3node)["Tmin"]; doublereal tmin0 = strSItoDbl(astring); astring = (*MinEQ3node)["Tmax"]; doublereal tmax0 = strSItoDbl(astring); astring = (*MinEQ3node)["Pref"]; doublereal p0 = strSItoDbl(astring); doublereal deltaG_formation_pr_tr = getFloatDefaultUnits(*MinEQ3node, "DG0_f_Pr_Tr", "cal/gmol", "actEnergy"); doublereal deltaH_formation_pr_tr = getFloatDefaultUnits(*MinEQ3node, "DH0_f_Pr_Tr", "cal/gmol", "actEnergy"); doublereal Entrop_pr_tr = getFloatDefaultUnits(*MinEQ3node, "S0_Pr_Tr", "cal/gmol/K"); doublereal a = getFloatDefaultUnits(*MinEQ3node, "a", "cal/gmol/K"); doublereal b = getFloatDefaultUnits(*MinEQ3node, "b", "cal/gmol/K2"); doublereal c = getFloatDefaultUnits(*MinEQ3node, "c", "cal-K/gmol"); doublereal dg = deltaG_formation_pr_tr * 4.184 * 1.0E3; doublereal fac = convertDGFormation(k, th_ptr); doublereal Mu0_tr_pr = fac + dg; doublereal e = Entrop_pr_tr * 1.0E3 * 4.184; doublereal Hcalc = Mu0_tr_pr + 298.15 * e; doublereal DHjmol = deltaH_formation_pr_tr * 1.0E3 * 4.184; // If the discrepency is greater than 100 cal gmol-1, print // an error and exit. if (fabs(Hcalc -DHjmol) > 10.* 1.0E6 * 4.184) { throw CanteraError("installMinEQ3asShomateThermoFromXML()", "DHjmol is not consistent with G and S" + fp2str(Hcalc) + " vs " + fp2str(DHjmol)); } /* * Now calculate the shomate polynomials * * Cp first * * Shomate: (Joules / gmol / K) * Cp = As + Bs * t + Cs * t*t + Ds * t*t*t + Es / (t*t) * where * t = temperature(Kelvin) / 1000 */ double As = a * 4.184; double Bs = b * 4.184 * 1000.; double Cs = 0.0; double Ds = 0.0; double Es = c * 4.184 / (1.0E6); double t = 298.15 / 1000.; double H298smFs = As * t + Bs * t * t / 2.0 - Es / t; double HcalcS = Hcalc / 1.0E6; double Fs = HcalcS - H298smFs; double S298smGs = As * log(t) + Bs * t - Es/(2.0*t*t); double ScalcS = e / 1.0E3; double Gs = ScalcS - S298smGs; c0[0] = As; c0[1] = Bs; c0[2] = Cs; c0[3] = Ds; c0[4] = Es; c0[5] = Fs; c0[6] = Gs; coef[0] = tmax0 - 0.001; copy(c0.begin(), c0.begin()+7, coef.begin() + 1); copy(c0.begin(), c0.begin()+7, coef.begin() + 8); sp.install(speciesName, k, SHOMATE, &coef[0], tmin0, tmax0, p0); }
/** * Install a NASA polynomial thermodynamic property * parameterization for species k into a SpeciesThermo instance. * This is called by method installThermoForSpecies if a NASA * block is found in the XML input. */ static void installNasaThermoFromXML(std::string speciesName, SpeciesThermo& sp, int k, const XML_Node* f0ptr, const XML_Node* f1ptr) { doublereal tmin0, tmax0, tmin1, tmax1, tmin, tmid, tmax; const XML_Node& f0 = *f0ptr; // default to a single temperature range bool dualRange = false; // but if f1ptr is suppled, then it is a two-range // parameterization if (f1ptr) {dualRange = true;} tmin0 = fpValue(f0["Tmin"]); tmax0 = fpValue(f0["Tmax"]); doublereal p0 = OneAtm; if (f0.hasAttrib("P0")) { p0 = fpValue(f0["P0"]); } if (f0.hasAttrib("Pref")) { p0 = fpValue(f0["Pref"]); } p0 = OneAtm; tmin1 = tmax0; tmax1 = tmin1 + 0.0001; if (dualRange) { tmin1 = fpValue((*f1ptr)["Tmin"]); tmax1 = fpValue((*f1ptr)["Tmax"]); } vector_fp c0, c1; if (fabs(tmax0 - tmin1) < 0.01) { // f0 has the lower T data, and f1 the higher T data tmin = tmin0; tmid = tmax0; tmax = tmax1; getFloatArray(f0.child("floatArray"), c0, false); if (dualRange) getFloatArray(f1ptr->child("floatArray"), c1, false); else { // if there is no higher range data, then copy c0 to c1. c1.resize(7,0.0); copy(c0.begin(), c0.end(), c1.begin()); } } else if (fabs(tmax1 - tmin0) < 0.01) { // f1 has the lower T data, and f0 the higher T data tmin = tmin1; tmid = tmax1; tmax = tmax0; getFloatArray(f1ptr->child("floatArray"), c0, false); getFloatArray(f0.child("floatArray"), c1, false); } else { throw CanteraError("installNasaThermo", "non-continuous temperature ranges."); } // The NasaThermo species property manager expects the // coefficients in a different order, so rearrange them. array_fp c(15); c[0] = tmid; c[1] = c0[5]; c[2] = c0[6]; copy(c0.begin(), c0.begin()+5, c.begin() + 3); c[8] = c1[5]; c[9] = c1[6]; copy(c1.begin(), c1.begin()+5, c.begin() + 10); sp.install(speciesName, k, NASA, &c[0], tmin, tmax, p0); }