Mu0Poly* newMu0ThermoFromXML(const XML_Node& Mu0Node) { bool dimensionlessMu0Values = false; 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(Mu0Node, "Mu0Values"); if (!valNode_ptr) { throw CanteraError("installMu0ThermoFromXML", "missing Mu0Values"); } 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 if (valNode_ptr->attrib("units") == "Dimensionless") { dimensionlessMu0Values = true; } if (cValues.size() != numPoints) { throw CanteraError("installMu0ThermoFromXML", "numPoints inconsistent"); } vector_fp cTemperatures(numPoints); const XML_Node* tempNode_ptr = getByTitle(Mu0Node, "Mu0Temperatures"); if (!tempNode_ptr) { throw CanteraError("installMu0ThermoFromXML", "missing Mu0Temperatures"); } getFloatArray(*tempNode_ptr, cTemperatures, false); if (cTemperatures.size() != numPoints) { throw CanteraError("installMu0ThermoFromXML", "numPoints inconsistent"); } // 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]; } return new Mu0Poly(fpValue(Mu0Node["Tmin"]), fpValue(Mu0Node["Tmax"]), fpValue(Mu0Node["Pref"]), &c[0]); }
static void installAdsorbateThermoFromXML(std::string speciesName, SpeciesThermo& sp, int k, const XML_Node& f) { vector_fp freqs; doublereal tmin, tmax, pref = OneAtm; int nfreq = 0; tmin = fpValue(f["Tmin"]); tmax = fpValue(f["Tmax"]); if (f.hasAttrib("P0")) { pref = fpValue(f["P0"]); } if (f.hasAttrib("Pref")) { pref = fpValue(f["Pref"]); } if (tmax == 0.0) tmax = 1.0e30; if (f.hasChild("floatArray")) { getFloatArray(f.child("floatArray"), freqs, false); nfreq = freqs.size(); } for (int n = 0; n < nfreq; n++) { freqs[n] *= 3.0e10; } vector_fp coeffs(nfreq + 2); coeffs[0] = nfreq; coeffs[1] = getFloat(f, "binding_energy", "toSI"); copy(freqs.begin(), freqs.end(), coeffs.begin() + 2); //posc = new Adsorbate(k, tmin, tmax, pref, // DATA_PTR(coeffs)); (&sp)->install(speciesName, k, ADSORBATE, &coeffs[0], tmin, tmax, pref); }
/*! * This is called if a 'Adsorbate' node is found in the XML input. * * @param f XML Node that contains the parameterization */ static SpeciesThermoInterpType* newAdsorbateThermoFromXML(const XML_Node& f) { vector_fp freqs; doublereal pref = OneAtm; double tmin = fpValue(f["Tmin"]); double tmax = fpValue(f["Tmax"]); if (f.hasAttrib("P0")) { pref = fpValue(f["P0"]); } if (f.hasAttrib("Pref")) { pref = fpValue(f["Pref"]); } if (tmax == 0.0) { tmax = 1.0e30; } if (f.hasChild("floatArray")) { getFloatArray(f.child("floatArray"), freqs, false); } for (size_t n = 0; n < freqs.size(); n++) { freqs[n] *= 3.0e10; } vector_fp coeffs(freqs.size() + 2); coeffs[0] = static_cast<double>(freqs.size()); coeffs[1] = getFloat(f, "binding_energy", "toSI"); copy(freqs.begin(), freqs.end(), coeffs.begin() + 2); return new Adsorbate(tmin, tmax, pref, &coeffs[0]); }
/* * This function will read a child node to the current XML node, with the * name "floatArray". It will have a title attribute, and the body * of the XML node will be filled out with a comma separated list of * doublereals. * Get an array of floats from the XML Node. The argument field * is assumed to consist of an arbitrary number of comma * separated floats, with an arbitrary amount of white space * separating each field. * If the node array has an units attribute field, then * the units are used to convert the floats, iff convert is true. * * Example: * * Code snipet: * @verbatum const XML_Node &State_XMLNode; vector_fp v; bool convert = true; unitsString = ""; nodeName="floatArray"; getFloatArray(State_XMLNode, v, convert, unitsString, nodeName); @endverbatum * * reads the corresponding XML file: * * @verbatum <state> <floatArray units="m3"> 32.4, 1, 100. <\floatArray> <\state> @endverbatum * * Will produce the vector * * v[0] = 32.4 * v[1] = 1.0 * v[2] = 100. * * * @param node XML parent node of the floatArray * @param v Output vector of floats containing the floatArray information. * @param convert Conversion to SI is carried out if this boolean is * True. The default is true. * @param typeString String name of the type attribute. This is an optional * parameter. The default is to have an empty string. * The only string that is recognized is actEnergy. * Anything else has no effect. This affects what * units converter is used. * @param nodeName XML Name of the XML node to read. * The default value for the node name is floatArray */ void getFunction(const Cantera::XML_Node& node, std::string& type, doublereal& xmin, doublereal& xmax, Cantera::vector_fp& coeffs) { const XML_Node& c = node.child("floatArray"); coeffs.clear(); getFloatArray(c,coeffs); xmin = Cantera::Undef; xmin = Cantera::Undef; if (node["min"] != "") xmin = fpValue(node["min"]); if (node["max"] != "") xmax = fpValue(node["max"]); type = node["type"]; }
/** * 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 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); }
void installElements(Phase& th, const XML_Node& phaseNode) { // get the declared element names if (!phaseNode.hasChild("elementArray")) { throw CanteraError("installElements", "phase XML node doesn't have \"elementArray\" XML Node"); } XML_Node& elements = phaseNode.child("elementArray"); vector<string> enames; getStringArray(elements, enames); // // element database defaults to elements.xml string element_database = "elements.xml"; if (elements.hasAttrib("datasrc")) { element_database = elements["datasrc"]; } XML_Node* doc = get_XML_File(element_database); XML_Node* dbe = &doc->child("elementData"); XML_Node& root = phaseNode.root(); XML_Node* local_db = 0; if (root.hasChild("elementData")) { local_db = &root.child("elementData"); } for (size_t i = 0; i < enames.size(); i++) { // Find the element data XML_Node* e = 0; if (local_db) { e = local_db->findByAttr("name",enames[i]); } if (!e) { e = dbe->findByAttr("name",enames[i]); } if (!e) { throw CanteraError("addElementsFromXML","no data for element " +enames[i]); } // Add the element doublereal weight = 0.0; if (e->hasAttrib("atomicWt")) { weight = fpValue(e->attrib("atomicWt")); } int anum = 0; if (e->hasAttrib("atomicNumber")) { anum = intValue(e->attrib("atomicNumber")); } string symbol = e->attrib("name"); doublereal entropy298 = ENTROPY298_UNKNOWN; if (e->hasChild("entropy298")) { XML_Node& e298Node = e->child("entropy298"); if (e298Node.hasAttrib("value")) { entropy298 = fpValueCheck(e298Node["value"]); } } th.addElement(symbol, weight, anum, entropy298); } }
/** * 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 Phase::addElement(const XML_Node& e) { warn_deprecated("Phase::addElement(XML_Node&)", "To be removed after Cantera 2.2."); doublereal weight = 0.0; if (e.hasAttrib("atomicWt")) { weight = fpValue(stripws(e["atomicWt"])); } int anum = 0; if (e.hasAttrib("atomicNumber")) { anum = atoi(stripws(e["atomicNumber"]).c_str()); } string symbol = e["name"]; doublereal entropy298 = ENTROPY298_UNKNOWN; if (e.hasChild("entropy298")) { XML_Node& e298Node = e.child("entropy298"); if (e298Node.hasAttrib("value")) { entropy298 = fpValueCheck(stripws(e298Node["value"])); } } if (weight != 0.0) { addElement(symbol, weight, anum, entropy298); } else { addElement(symbol); } }
/*! * This is called if a 'const_cp' XML node is found * * @param f 'const_cp' XML node */ static SpeciesThermoInterpType* newConstCpThermoFromXML(XML_Node& f) { double tmin = fpValue(f["Tmin"]); double 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; return newSpeciesThermoInterpType(CONSTANT_CP, tmin, tmax, p0, &c[0]); }
/********************************************************************* * Utility Functions *********************************************************************/ void MaskellSolidSolnPhase::initThermoXML(XML_Node& phaseNode, const std::string& id_) { if (id_.size() > 0 && phaseNode.id() != id_) { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "phasenode and Id are incompatible"); } /* * Check on the thermo field. Must have: * <thermo model="MaskellSolidSolution" /> */ if (phaseNode.hasChild("thermo")) { XML_Node& thNode = phaseNode.child("thermo"); std::string mString = thNode.attrib("model"); if (lowercase(mString) != "maskellsolidsolnphase") { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "Unknown thermo model: " + mString); } /* * Parse the enthalpy of mixing constant */ if (thNode.hasChild("h_mix")) { set_h_mix(fpValue(thNode.child("h_mix").value())); } else { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "Mixing enthalpy parameter not specified."); } if (thNode.hasChild("product_species")) { std::string product_species_name = thNode.child("product_species").value(); product_species_index = speciesIndex(product_species_name); if (product_species_index == static_cast<int>(npos)) { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "Species " + product_species_name + " not found."); } if (product_species_index == 0) { reactant_species_index = 1; } else { reactant_species_index = 0; } } } else { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "Unspecified thermo model"); } // Confirm that the phase only contains 2 species if (m_kk != 2) { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "MaskellSolidSolution model requires exactly 2 species."); } /* * Call the base initThermo, which handles setting the initial * state. */ VPStandardStateTP::initThermoXML(phaseNode, id_); }
doublereal getFloatCurrent(const XML_Node& node, const std::string& type) { doublereal fctr = 1.0; doublereal x = node.fp_value(); const string& units = node["units"]; const string& vmin = node["min"]; const string& vmax = node["max"]; if (vmin != "" && x < fpValue(vmin) - Tiny) { writelog("\nWarning: value "+node.value()+" is below lower limit of " +vmin+".\n"); } if (node["max"] != "" && x > fpValue(vmax) + Tiny) { writelog("\nWarning: value "+node.value()+" is above upper limit of " +vmax+".\n"); } // Note, most types of converters default to toSI() type atm. // This may change and become more specific in the future. if (type == "actEnergy" && units != "") { fctr = actEnergyToSI(units); } else if (type == "toSI" && units != "") { fctr = toSI(units); } else if (type == "temperature" && units != "") { fctr = toSI(units); } else if (type == "density" && units != "") { fctr = toSI(units); } else if (type == "pressure" && units != "") { fctr = toSI(units); } else if (type != "" && units != "") { fctr = toSI(units); #ifdef DEBUG_MODE writelog("\nWarning: conversion toSI() was done on node value " + node.name() + "but wasn't explicitly requested. Type was \"" + type + "\"\n"); #endif } // Note, below currently produces a lot of output due to transport blocks. // This needs to be addressed. #ifdef DEBUG_MODE_MORE else if (type == "" && units != "") { writelog("\nWarning: XML node " + node.name() + "has a units attribute, \"" + units + "\"," "but no conversion was done because the getFloat() command didn't have a type\n"); } #endif return fctr*x; }
/** * Create a stat mech based property solver for a species * @deprecated */ static StatMech* newStatMechThermoFromXML(const std::string& speciesName, XML_Node& f) { doublereal tmin = fpValue(f["Tmin"]); doublereal tmax = fpValue(f["Tmax"]); doublereal pref = OneAtm; if (f.hasAttrib("P0")) { pref = fpValue(f["P0"]); } if (f.hasAttrib("Pref")) { pref = fpValue(f["Pref"]); } // set properties tmin = 0.1; vector_fp coeffs(1); coeffs[0] = 0.0; return new StatMech(0, tmin, tmax, pref, &coeffs[0], speciesName); }
/** * 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); }
/*! * This is called if a 'NASA' node is found in the XML input. * * @param speciesName name of the species * @param nodes vector of 1 or 2 'NASA' XML_Nodes, each defining the * coefficients for a temperature range */ static SpeciesThermoInterpType* newNasaThermoFromXML( const std::string& speciesName, vector<XML_Node*> nodes) { const XML_Node& f0 = *nodes[0]; bool dualRange = (nodes.size() > 1); double tmin0 = fpValue(f0["Tmin"]); double 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; double tmin1 = tmax0; double tmax1 = tmin1 + 0.0001; if (dualRange) { tmin1 = fpValue(nodes[1]->attrib("Tmin")); tmax1 = fpValue(nodes[1]->attrib("Tmax")); } vector_fp c0, c1; doublereal tmin, tmid, tmax; 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(nodes[1]->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(nodes[1]->child("floatArray"), c0, false); getFloatArray(f0.child("floatArray"), c1, false); } else { throw CanteraError("installNasaThermo", "non-continuous temperature ranges."); } vector_fp c(15); c[0] = tmid; copy(c1.begin(), c1.begin()+7, c.begin() + 1); // high-T coefficients copy(c0.begin(), c0.begin()+7, c.begin() + 8); // low-T coefficients return newSpeciesThermoInterpType(NASA, tmin, tmax, p0, &c[0]); }
/*! * This is called if a 'NASA9' Node is found in the XML input. * * @param speciesName name of the species * @param tp Vector of XML Nodes that make up the parameterization */ static SpeciesThermoInterpType* newNasa9ThermoFromXML( const std::string& speciesName, const std::vector<XML_Node*>& tp) { int nRegions = 0; vector_fp cPoly; std::vector<Nasa9Poly1*> regionPtrs; doublereal pref = OneAtm; // Loop over all of the possible temperature regions for (size_t i = 0; i < tp.size(); i++) { const XML_Node& fptr = *tp[i]; if (fptr.name() == "NASA9" && fptr.hasChild("floatArray")) { double tmin = fpValue(fptr["Tmin"]); double 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"); } regionPtrs.push_back(new Nasa9Poly1(tmin, tmax, pref, &cPoly[0])); nRegions++; } } if (nRegions == 0) { throw UnknownSpeciesThermoModel("installThermoForSpecies", speciesName, " "); } else if (nRegions == 1) { return regionPtrs[0]; } else { return new Nasa9PolyMultiTempRegion(regionPtrs); } }
doublereal fpValueCheck(const std::string& val) { std::string str = ba::trim_copy(val); if (str.empty()) { throw CanteraError("fpValueCheck", "string has zero length"); } int numDot = 0; int numExp = 0; char ch; int istart = 0; ch = str[0]; if (ch == '+' || ch == '-') { istart = 1; } for (size_t i = istart; i < str.size(); i++) { ch = str[i]; if (isdigit(ch)) { } else if (ch == '.') { numDot++; if (numDot > 1) { throw CanteraError("fpValueCheck", "string has more than one ."); } if (numExp > 0) { throw CanteraError("fpValueCheck", "string has decimal point in exponent"); } } else if (ch == 'e' || ch == 'E' || ch == 'd' || ch == 'D') { numExp++; str[i] = 'E'; if (numExp > 1) { throw CanteraError("fpValueCheck", "string has more than one exp char"); } ch = str[i+1]; if (ch == '+' || ch == '-') { i++; } } else { throw CanteraError("fpValueCheck", "Trouble processing string, " + str); } } return fpValue(str); }
void MaskellSolidSolnPhase::initThermoXML(XML_Node& phaseNode, const std::string& id_) { if (id_.size() > 0 && phaseNode.id() != id_) { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "phasenode and Id are incompatible"); } // Check on the thermo field. Must have: // <thermo model="MaskellSolidSolution" /> if (phaseNode.hasChild("thermo")) { XML_Node& thNode = phaseNode.child("thermo"); if (!ba::iequals(thNode["model"], "maskellsolidsolnphase")) { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "Unknown thermo model: " + thNode["model"]); } // Parse the enthalpy of mixing constant if (thNode.hasChild("h_mix")) { set_h_mix(fpValue(thNode.child("h_mix").value())); } else { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "Mixing enthalpy parameter not specified."); } if (thNode.hasChild("product_species")) { setProductSpecies(thNode.child("product_species").value()); } else { setProductSpecies(speciesName(0)); // default } } else { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "Unspecified thermo model"); } // Confirm that the phase only contains 2 species if (m_kk != 2) { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "MaskellSolidSolution model requires exactly 2 species."); } // Call the base initThermo, which handles setting the initial state. VPStandardStateTP::initThermoXML(phaseNode, id_); }
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); }
/** * 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); }
void Phase::addElement(const XML_Node& e) { doublereal weight = fpValue(e["atomicWt"]); string symbol = e["name"]; addElement(symbol, weight); }
/*! * This is called if a 'Shomate' node is found in the XML input. * * @param nodes vector of 1 or 2 'Shomate' XML_Nodes, each defining the * coefficients for a temperature range */ static SpeciesThermoInterpType* newShomateThermoFromXML( vector<XML_Node*>& nodes) { bool dualRange = false; if (nodes.size() == 2) { dualRange = true; } double tmin0 = fpValue(nodes[0]->attrib("Tmin")); double tmax0 = fpValue(nodes[0]->attrib("Tmax")); doublereal p0 = OneAtm; if (nodes[0]->hasAttrib("P0")) { p0 = fpValue(nodes[0]->attrib("P0")); } if (nodes[0]->hasAttrib("Pref")) { p0 = fpValue(nodes[0]->attrib("Pref")); } p0 = OneAtm; double tmin1 = tmax0; double tmax1 = tmin1 + 0.0001; if (dualRange) { tmin1 = fpValue(nodes[1]->attrib("Tmin")); tmax1 = fpValue(nodes[1]->attrib("Tmax")); } vector_fp c0, c1; doublereal tmin, tmid, tmax; if (fabs(tmax0 - tmin1) < 0.01) { tmin = tmin0; tmid = tmax0; tmax = tmax1; getFloatArray(nodes[0]->child("floatArray"), c0, false); if (dualRange) { getFloatArray(nodes[1]->child("floatArray"), c1, false); } else { if(c0.size() != 7) { throw CanteraError("installShomateThermoFromXML", "Shomate thermo requires 7 coefficients in float array."); } 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(nodes[1]->child("floatArray"), c0, false); getFloatArray(nodes[0]->child("floatArray"), c1, false); } else { throw CanteraError("installShomateThermoFromXML", "non-continuous temperature ranges."); } if(c0.size() != 7 || c1.size() != 7) { throw CanteraError("installShomateThermoFromXML", "Shomate thermo requires 7 coefficients in float array."); } vector_fp c(15); c[0] = tmid; copy(c0.begin(), c0.begin()+7, c.begin() + 1); copy(c1.begin(), c1.begin()+7, c.begin() + 8); return newSpeciesThermoInterpType(SHOMATE, tmin, tmax, p0, &c[0]); }