|
|
|
|
@ -49,6 +49,7 @@ mutex_t SpeciesThermoFactory::species_thermo_mutex;
|
|
|
|
|
* @param has_other Return int that indicates whether the phase has a form for one of its species that is not one of the ones listed above.
|
|
|
|
|
*
|
|
|
|
|
* @todo Make sure that spDadta_node is species Data XML node by checking its name is speciesData
|
|
|
|
|
* @deprecated
|
|
|
|
|
*/
|
|
|
|
|
static void getSpeciesThermoTypes(std::vector<XML_Node*> & spDataNodeList,
|
|
|
|
|
int& has_nasa, int& has_shomate, int& has_simple,
|
|
|
|
|
@ -239,32 +240,22 @@ SpeciesThermoInterpType* newSpeciesThermoInterpType(const std::string& stype,
|
|
|
|
|
return newSpeciesThermoInterpType(itype, tlow, thigh, pref, coeffs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//! Install a NASA polynomial thermodynamic property parameterization for species k into a SpeciesThermo instance.
|
|
|
|
|
//! Create a NASA polynomial thermodynamic property parameterization for a
|
|
|
|
|
//! species from a set ! of XML nodes
|
|
|
|
|
/*!
|
|
|
|
|
* This is called by method installThermoForSpecies if a NASA block is found in the XML input.
|
|
|
|
|
* This is called if a 'NASA' node is found in the XML input.
|
|
|
|
|
*
|
|
|
|
|
* @param speciesName String name of the species
|
|
|
|
|
* @param sp SpeciesThermo object that will receive the NASA polynomial object
|
|
|
|
|
* @param k Species index within the phase
|
|
|
|
|
* @param f0ptr Ptr to the first XML_Node for the first NASA polynomial
|
|
|
|
|
* @param f1ptr Ptr to the first XML_Node for the first NASA polynomial
|
|
|
|
|
* @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 void installNasaThermoFromXML(const std::string& speciesName,
|
|
|
|
|
SpeciesThermo& sp, size_t k,
|
|
|
|
|
const XML_Node* f0ptr, const XML_Node* f1ptr)
|
|
|
|
|
static SpeciesThermoInterpType* newNasaThermoFromXML(
|
|
|
|
|
const std::string& speciesName, vector<XML_Node*> nodes)
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
const XML_Node& f0 = *nodes[0];
|
|
|
|
|
bool dualRange = (nodes.size() > 1);
|
|
|
|
|
|
|
|
|
|
tmin0 = fpValue(f0["Tmin"]);
|
|
|
|
|
tmax0 = fpValue(f0["Tmax"]);
|
|
|
|
|
@ -281,8 +272,8 @@ static void installNasaThermoFromXML(const std::string& speciesName,
|
|
|
|
|
tmin1 = tmax0;
|
|
|
|
|
tmax1 = tmin1 + 0.0001;
|
|
|
|
|
if (dualRange) {
|
|
|
|
|
tmin1 = fpValue((*f1ptr)["Tmin"]);
|
|
|
|
|
tmax1 = fpValue((*f1ptr)["Tmax"]);
|
|
|
|
|
tmin1 = fpValue(nodes[1]->attrib("Tmin"));
|
|
|
|
|
tmax1 = fpValue(nodes[1]->attrib("Tmax"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vector_fp c0, c1;
|
|
|
|
|
@ -293,7 +284,7 @@ static void installNasaThermoFromXML(const std::string& speciesName,
|
|
|
|
|
tmax = tmax1;
|
|
|
|
|
getFloatArray(f0.child("floatArray"), c0, false);
|
|
|
|
|
if (dualRange) {
|
|
|
|
|
getFloatArray(f1ptr->child("floatArray"), c1, false);
|
|
|
|
|
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);
|
|
|
|
|
@ -304,7 +295,7 @@ static void installNasaThermoFromXML(const std::string& speciesName,
|
|
|
|
|
tmin = tmin1;
|
|
|
|
|
tmid = tmax1;
|
|
|
|
|
tmax = tmax0;
|
|
|
|
|
getFloatArray(f1ptr->child("floatArray"), c0, false);
|
|
|
|
|
getFloatArray(nodes[1]->child("floatArray"), c0, false);
|
|
|
|
|
getFloatArray(f0.child("floatArray"), c1, false);
|
|
|
|
|
} else {
|
|
|
|
|
throw CanteraError("installNasaThermo",
|
|
|
|
|
@ -322,7 +313,7 @@ static void installNasaThermoFromXML(const std::string& speciesName,
|
|
|
|
|
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);
|
|
|
|
|
return newSpeciesThermoInterpType(NASA, tmin, tmax, p0, &c[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//! Look up the elemental reference state entropies
|
|
|
|
|
@ -352,22 +343,22 @@ static doublereal LookupGe(const std::string& elemName, ThermoPhase* th_ptr)
|
|
|
|
|
* @param k species index
|
|
|
|
|
* @param th_ptr Pointer to the ThermoPhase
|
|
|
|
|
*/
|
|
|
|
|
static doublereal convertDGFormation(size_t k, ThermoPhase* th_ptr)
|
|
|
|
|
static doublereal convertDGFormation(const compositionMap& comp, ThermoPhase* th_ptr)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Ok let's get the element compositions and conversion factors.
|
|
|
|
|
*/
|
|
|
|
|
size_t ne = th_ptr->nElements();
|
|
|
|
|
doublereal na;
|
|
|
|
|
doublereal ge;
|
|
|
|
|
string ename;
|
|
|
|
|
|
|
|
|
|
doublereal totalSum = 0.0;
|
|
|
|
|
for (size_t m = 0; m < ne; m++) {
|
|
|
|
|
na = th_ptr->nAtoms(k, m);
|
|
|
|
|
for (compositionMap::const_iterator iter = comp.begin();
|
|
|
|
|
iter != comp.end();
|
|
|
|
|
++iter) {
|
|
|
|
|
na = iter->second;
|
|
|
|
|
if (na > 0.0) {
|
|
|
|
|
ename = th_ptr->elementName(m);
|
|
|
|
|
ge = LookupGe(ename, th_ptr);
|
|
|
|
|
ge = LookupGe(iter->first, th_ptr);
|
|
|
|
|
totalSum += na * ge;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -375,40 +366,34 @@ static doublereal convertDGFormation(size_t k, ThermoPhase* th_ptr)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Install a NASA96 polynomial thermodynamic property parameterization for species k into a SpeciesThermo instance.
|
|
|
|
|
//! Create a Shomate polynomial from an XML node giving the 'EQ3' coefficients
|
|
|
|
|
/*!
|
|
|
|
|
* This is called by method installThermoForSpecies if a MinEQ3node block is found in the XML input.
|
|
|
|
|
* This is called if a 'MinEQ3' node is found in the XML input.
|
|
|
|
|
*
|
|
|
|
|
* @param speciesName String name of the species
|
|
|
|
|
* @param th_ptr Pointer to the %ThermoPhase object
|
|
|
|
|
* @param sp SpeciesThermo object that will receive the NASA polynomial object
|
|
|
|
|
* @param k Species index within the phase
|
|
|
|
|
* @param MinEQ3node Ptr to the first XML_Node for the first MinEQ3 parameterization
|
|
|
|
|
* @param speciesName name of the species
|
|
|
|
|
* @param MinEQ3node The XML_Node containing the MinEQ3 parameterization
|
|
|
|
|
*/
|
|
|
|
|
static void installMinEQ3asShomateThermoFromXML(const std::string& speciesName,
|
|
|
|
|
ThermoPhase* th_ptr,
|
|
|
|
|
SpeciesThermo& sp, size_t k,
|
|
|
|
|
const XML_Node* MinEQ3node)
|
|
|
|
|
SpeciesThermoInterpType* newShomateForMineralEQ3(const std::string& name,
|
|
|
|
|
const XML_Node& MinEQ3node)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
vector_fp coef(15), c0(7, 0.0);
|
|
|
|
|
std::string astring = (*MinEQ3node)["Tmin"];
|
|
|
|
|
std::string astring = MinEQ3node["Tmin"];
|
|
|
|
|
doublereal tmin0 = strSItoDbl(astring);
|
|
|
|
|
astring = (*MinEQ3node)["Tmax"];
|
|
|
|
|
astring = MinEQ3node["Tmax"];
|
|
|
|
|
doublereal tmax0 = strSItoDbl(astring);
|
|
|
|
|
astring = (*MinEQ3node)["Pref"];
|
|
|
|
|
astring = MinEQ3node["Pref"];
|
|
|
|
|
doublereal p0 = strSItoDbl(astring);
|
|
|
|
|
|
|
|
|
|
doublereal deltaG_formation_pr_tr =
|
|
|
|
|
getFloatDefaultUnits(*MinEQ3node, "DG0_f_Pr_Tr", "cal/gmol", "actEnergy");
|
|
|
|
|
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");
|
|
|
|
|
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 fac = 0; // convertDGFormation(comp, 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;
|
|
|
|
|
@ -459,45 +444,43 @@ static void installMinEQ3asShomateThermoFromXML(const std::string& speciesName,
|
|
|
|
|
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);
|
|
|
|
|
return newSpeciesThermoInterpType(SHOMATE, tmin0, tmax0, p0, &coef[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//! Install a Shomate polynomial thermodynamic property parameterization for species k into a SpeciesThermo instance.
|
|
|
|
|
//! Create a Shomate polynomial thermodynamic property parameterization for a
|
|
|
|
|
//! species
|
|
|
|
|
/*!
|
|
|
|
|
* This is called by method installThermoForSpecies if a Shomate block is found in the XML input.
|
|
|
|
|
* This is called if a 'Shomate' node is found in the XML input.
|
|
|
|
|
*
|
|
|
|
|
* @param speciesName String name of the species
|
|
|
|
|
* @param sp SpeciesThermo object that will receive the NASA polynomial object
|
|
|
|
|
* @param k Species index within the phase
|
|
|
|
|
* @param f0ptr Ptr to the first XML_Node for the first NASA polynomial
|
|
|
|
|
* @param f1ptr Ptr to the first XML_Node for the first NASA polynomial
|
|
|
|
|
* @param speciesName name of the species
|
|
|
|
|
* @param nodes vector of 1 or 2 'Shomate' XML_Nodes, each defining the
|
|
|
|
|
* coefficients for a temperature range
|
|
|
|
|
*/
|
|
|
|
|
static void installShomateThermoFromXML(const std::string& speciesName, SpeciesThermo& sp, size_t k,
|
|
|
|
|
const XML_Node* f0ptr, const XML_Node* f1ptr)
|
|
|
|
|
static SpeciesThermoInterpType* newShomateThermoFromXML(
|
|
|
|
|
const std::string& speciesName, vector<XML_Node*>& nodes)
|
|
|
|
|
{
|
|
|
|
|
doublereal tmin0, tmax0, tmin1, tmax1, tmin, tmid, tmax;
|
|
|
|
|
const XML_Node& f0 = *f0ptr;
|
|
|
|
|
bool dualRange = false;
|
|
|
|
|
if (f1ptr) {
|
|
|
|
|
if (nodes.size() == 2) {
|
|
|
|
|
dualRange = true;
|
|
|
|
|
}
|
|
|
|
|
tmin0 = fpValue(f0["Tmin"]);
|
|
|
|
|
tmax0 = fpValue(f0["Tmax"]);
|
|
|
|
|
tmin0 = fpValue(nodes[0]->attrib("Tmin"));
|
|
|
|
|
tmax0 = fpValue(nodes[0]->attrib("Tmax"));
|
|
|
|
|
|
|
|
|
|
doublereal p0 = OneAtm;
|
|
|
|
|
if (f0.hasAttrib("P0")) {
|
|
|
|
|
p0 = fpValue(f0["P0"]);
|
|
|
|
|
if (nodes[0]->hasAttrib("P0")) {
|
|
|
|
|
p0 = fpValue(nodes[0]->attrib("P0"));
|
|
|
|
|
}
|
|
|
|
|
if (f0.hasAttrib("Pref")) {
|
|
|
|
|
p0 = fpValue(f0["Pref"]);
|
|
|
|
|
if (nodes[0]->hasAttrib("Pref")) {
|
|
|
|
|
p0 = fpValue(nodes[0]->attrib("Pref"));
|
|
|
|
|
}
|
|
|
|
|
p0 = OneAtm;
|
|
|
|
|
|
|
|
|
|
tmin1 = tmax0;
|
|
|
|
|
tmax1 = tmin1 + 0.0001;
|
|
|
|
|
if (dualRange) {
|
|
|
|
|
tmin1 = fpValue((*f1ptr)["Tmin"]);
|
|
|
|
|
tmax1 = fpValue((*f1ptr)["Tmax"]);
|
|
|
|
|
tmin1 = fpValue(nodes[1]->attrib("Tmin"));
|
|
|
|
|
tmax1 = fpValue(nodes[1]->attrib("Tmax"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vector_fp c0, c1;
|
|
|
|
|
@ -505,9 +488,9 @@ static void installShomateThermoFromXML(const std::string& speciesName, SpeciesT
|
|
|
|
|
tmin = tmin0;
|
|
|
|
|
tmid = tmax0;
|
|
|
|
|
tmax = tmax1;
|
|
|
|
|
getFloatArray(f0.child("floatArray"), c0, false);
|
|
|
|
|
getFloatArray(nodes[0]->child("floatArray"), c0, false);
|
|
|
|
|
if (dualRange) {
|
|
|
|
|
getFloatArray(f1ptr->child("floatArray"), c1, false);
|
|
|
|
|
getFloatArray(nodes[1]->child("floatArray"), c1, false);
|
|
|
|
|
} else {
|
|
|
|
|
if(c0.size() != 7)
|
|
|
|
|
{
|
|
|
|
|
@ -521,8 +504,8 @@ static void installShomateThermoFromXML(const std::string& speciesName, SpeciesT
|
|
|
|
|
tmin = tmin1;
|
|
|
|
|
tmid = tmax1;
|
|
|
|
|
tmax = tmax0;
|
|
|
|
|
getFloatArray(f1ptr->child("floatArray"), c0, false);
|
|
|
|
|
getFloatArray(f0.child("floatArray"), c1, false);
|
|
|
|
|
getFloatArray(nodes[1]->child("floatArray"), c0, false);
|
|
|
|
|
getFloatArray(nodes[0]->child("floatArray"), c1, false);
|
|
|
|
|
} else {
|
|
|
|
|
throw CanteraError("installShomateThermoFromXML",
|
|
|
|
|
"non-continuous temperature ranges.");
|
|
|
|
|
@ -536,25 +519,22 @@ static void installShomateThermoFromXML(const std::string& speciesName, SpeciesT
|
|
|
|
|
c[0] = tmid;
|
|
|
|
|
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);
|
|
|
|
|
return newSpeciesThermoInterpType(SHOMATE, tmin, tmax, p0, &c[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//! Install a Simple thermodynamic property parameterization for species k into a SpeciesThermo instance.
|
|
|
|
|
//! Create a "simple" constant heat capacity thermodynamic property
|
|
|
|
|
//! parameterization for a ! species
|
|
|
|
|
/*!
|
|
|
|
|
* This is called by method installThermoForSpecies if a SimpleThermo block is found
|
|
|
|
|
* This is called if a 'const_cp' XML node is found
|
|
|
|
|
*
|
|
|
|
|
* @param speciesName String name of the species
|
|
|
|
|
* @param sp SpeciesThermo object that will receive the NASA polynomial object
|
|
|
|
|
* @param k Species index within the phase
|
|
|
|
|
* @param f XML_Node for the SimpleThermo block
|
|
|
|
|
* @param speciesName name of the species
|
|
|
|
|
* @param f 'const_cp' XML node
|
|
|
|
|
*/
|
|
|
|
|
static void installSimpleThermoFromXML(const std::string& speciesName,
|
|
|
|
|
SpeciesThermo& sp, size_t k,
|
|
|
|
|
const XML_Node& f)
|
|
|
|
|
static SpeciesThermoInterpType* newConstCpThermoFromXML(
|
|
|
|
|
const std::string& speciesName, XML_Node& f)
|
|
|
|
|
{
|
|
|
|
|
doublereal tmin, tmax;
|
|
|
|
|
tmin = fpValue(f["Tmin"]);
|
|
|
|
|
tmax = fpValue(f["Tmax"]);
|
|
|
|
|
double tmin = fpValue(f["Tmin"]);
|
|
|
|
|
double tmax = fpValue(f["Tmax"]);
|
|
|
|
|
if (tmax == 0.0) {
|
|
|
|
|
tmax = 1.0e30;
|
|
|
|
|
}
|
|
|
|
|
@ -565,133 +545,95 @@ static void installSimpleThermoFromXML(const std::string& speciesName,
|
|
|
|
|
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);
|
|
|
|
|
return newSpeciesThermoInterpType(CONSTANT_CP, tmin, tmax, p0, &c[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Install a NASA9 polynomial thermodynamic property parameterization for species k into a SpeciesThermo instance.
|
|
|
|
|
//! Create a NASA9 polynomial thermodynamic property parameterization for a
|
|
|
|
|
//! species
|
|
|
|
|
/*!
|
|
|
|
|
* This is called by method installThermoForSpecies if a NASA9 block is found in the XML input.
|
|
|
|
|
* This is called if a 'NASA9' Node is found in the XML input.
|
|
|
|
|
*
|
|
|
|
|
* @param speciesName String name of the species
|
|
|
|
|
* @param sp SpeciesThermo object that will receive the NASA polynomial object
|
|
|
|
|
* @param k Species index within the phase
|
|
|
|
|
* @param tp Vector of XML Nodes that make up the parameterization
|
|
|
|
|
* @param speciesName name of the species
|
|
|
|
|
* @param tp Vector of XML Nodes that make up the parameterization
|
|
|
|
|
*/
|
|
|
|
|
static void installNasa9ThermoFromXML(const std::string& speciesName,
|
|
|
|
|
SpeciesThermo& sp, size_t k,
|
|
|
|
|
const std::vector<XML_Node*>& tp)
|
|
|
|
|
static SpeciesThermoInterpType* newNasa9ThermoFromXML(
|
|
|
|
|
const std::string& speciesName, const std::vector<XML_Node*>& tp)
|
|
|
|
|
{
|
|
|
|
|
const XML_Node* fptr = tp[0];
|
|
|
|
|
int nRegions = 0;
|
|
|
|
|
vector_fp cPoly;
|
|
|
|
|
Nasa9Poly1* np_ptr = 0;
|
|
|
|
|
std::vector<Nasa9Poly1*> regionPtrs;
|
|
|
|
|
doublereal tmin, tmax, pref = OneAtm;
|
|
|
|
|
doublereal pref = OneAtm;
|
|
|
|
|
// Loop over all of the possible temperature regions
|
|
|
|
|
for (size_t i = 0; i < tp.size(); 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++;
|
|
|
|
|
}
|
|
|
|
|
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(0, tmin, tmax, pref, &cPoly[0]));
|
|
|
|
|
nRegions++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (nRegions == 0) {
|
|
|
|
|
throw UnknownSpeciesThermoModel("installThermoForSpecies",
|
|
|
|
|
speciesName, " ");
|
|
|
|
|
} else if (nRegions == 1) {
|
|
|
|
|
sp.install_STIT(np_ptr);
|
|
|
|
|
return regionPtrs[0];
|
|
|
|
|
} else {
|
|
|
|
|
Nasa9PolyMultiTempRegion* npMulti_ptr = new Nasa9PolyMultiTempRegion(regionPtrs);
|
|
|
|
|
sp.install_STIT(npMulti_ptr);
|
|
|
|
|
return new Nasa9PolyMultiTempRegion(regionPtrs);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Install a stat mech based property solver
|
|
|
|
|
* for species k into a SpeciesThermo instance.
|
|
|
|
|
* Create a stat mech based property solver for a species
|
|
|
|
|
* @deprecated
|
|
|
|
|
*/
|
|
|
|
|
static void installStatMechThermoFromXML(const std::string& speciesName,
|
|
|
|
|
SpeciesThermo& sp, int k,
|
|
|
|
|
const std::vector<XML_Node*>& tp)
|
|
|
|
|
static StatMech* newStatMechThermoFromXML(const std::string& speciesName, XML_Node& f)
|
|
|
|
|
{
|
|
|
|
|
const XML_Node* fptr = tp[0];
|
|
|
|
|
int nRegTmp = tp.size();
|
|
|
|
|
vector_fp cPoly;
|
|
|
|
|
std::vector<StatMech*> regionPtrs;
|
|
|
|
|
doublereal tmin = 0.0;
|
|
|
|
|
doublereal tmax = 0.0;
|
|
|
|
|
doublereal tmin = fpValue(f["Tmin"]);
|
|
|
|
|
doublereal tmax = fpValue(f["Tmax"]);
|
|
|
|
|
doublereal 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() == "StatMech") {
|
|
|
|
|
tmin = fpValue((*fptr)["Tmin"]);
|
|
|
|
|
tmax = fpValue((*fptr)["Tmax"]);
|
|
|
|
|
if ((*fptr).hasAttrib("P0")) {
|
|
|
|
|
pref = fpValue((*fptr)["P0"]);
|
|
|
|
|
}
|
|
|
|
|
if ((*fptr).hasAttrib("Pref")) {
|
|
|
|
|
pref = fpValue((*fptr)["Pref"]);
|
|
|
|
|
}
|
|
|
|
|
if (fptr->hasChild("floatArray")) {
|
|
|
|
|
getFloatArray(fptr->child("floatArray"), cPoly, false);
|
|
|
|
|
if (cPoly.size() != 0) {
|
|
|
|
|
throw CanteraError("installStatMechThermoFromXML",
|
|
|
|
|
"Expected no coeff: this is not a polynomial representation");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
(&sp)->install(speciesName, k, STAT, &coeffs[0], tmin, tmax, pref);
|
|
|
|
|
return new StatMech(0, tmin, tmax, pref, &coeffs[0], speciesName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//! Install a Adsorbate polynomial thermodynamic property parameterization for species k into a SpeciesThermo instance.
|
|
|
|
|
//! Create an Adsorbate polynomial thermodynamic property parameterization for a
|
|
|
|
|
//! species
|
|
|
|
|
/*!
|
|
|
|
|
* This is called by method installThermoForSpecies if a Adsorbate block is found in the XML input.
|
|
|
|
|
* This is called if a 'Adsorbate' node is found in the XML input.
|
|
|
|
|
*
|
|
|
|
|
* @param speciesName String name of the species
|
|
|
|
|
* @param sp SpeciesThermo object that will receive the NASA polynomial object
|
|
|
|
|
* @param k Species index within the phase
|
|
|
|
|
* @param f XML Node that contains the parameterization
|
|
|
|
|
* @param speciesName name of the species
|
|
|
|
|
* @param f XML Node that contains the parameterization
|
|
|
|
|
*/
|
|
|
|
|
static void installAdsorbateThermoFromXML(const std::string& speciesName,
|
|
|
|
|
SpeciesThermo& sp, size_t k,
|
|
|
|
|
const XML_Node& f)
|
|
|
|
|
static SpeciesThermoInterpType* newAdsorbateThermoFromXML(
|
|
|
|
|
const std::string& speciesName, const XML_Node& f)
|
|
|
|
|
{
|
|
|
|
|
vector_fp freqs;
|
|
|
|
|
doublereal tmin, tmax, pref = OneAtm;
|
|
|
|
|
size_t nfreq = 0;
|
|
|
|
|
tmin = fpValue(f["Tmin"]);
|
|
|
|
|
tmax = fpValue(f["Tmax"]);
|
|
|
|
|
doublereal pref = OneAtm;
|
|
|
|
|
double tmin = fpValue(f["Tmin"]);
|
|
|
|
|
double tmax = fpValue(f["Tmax"]);
|
|
|
|
|
if (f.hasAttrib("P0")) {
|
|
|
|
|
pref = fpValue(f["P0"]);
|
|
|
|
|
}
|
|
|
|
|
@ -704,8 +646,8 @@ static void installAdsorbateThermoFromXML(const std::string& speciesName,
|
|
|
|
|
|
|
|
|
|
if (f.hasChild("floatArray")) {
|
|
|
|
|
getFloatArray(f.child("floatArray"), freqs, false);
|
|
|
|
|
nfreq = freqs.size();
|
|
|
|
|
}
|
|
|
|
|
size_t nfreq = freqs.size();
|
|
|
|
|
for (size_t n = 0; n < nfreq; n++) {
|
|
|
|
|
freqs[n] *= 3.0e10;
|
|
|
|
|
}
|
|
|
|
|
@ -713,92 +655,17 @@ static void installAdsorbateThermoFromXML(const std::string& speciesName,
|
|
|
|
|
coeffs[0] = static_cast<double>(nfreq);
|
|
|
|
|
coeffs[1] = getFloat(f, "binding_energy", "toSI");
|
|
|
|
|
copy(freqs.begin(), freqs.end(), coeffs.begin() + 2);
|
|
|
|
|
(&sp)->install(speciesName, k, ADSORBATE, &coeffs[0], tmin, tmax, pref);
|
|
|
|
|
return new Adsorbate(0, tmin, tmax, pref, &coeffs[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SpeciesThermoFactory::installThermoForSpecies
|
|
|
|
|
(size_t k, const XML_Node& speciesNode, ThermoPhase* th_ptr,
|
|
|
|
|
SpeciesThermo& spthermo, const XML_Node* phaseNode_ptr) const
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Check to see that the species block has a thermo block
|
|
|
|
|
* before processing. Throw an error if not there.
|
|
|
|
|
*/
|
|
|
|
|
if (!(speciesNode.hasChild("thermo"))) {
|
|
|
|
|
throw UnknownSpeciesThermoModel("installThermoForSpecies",
|
|
|
|
|
speciesNode["name"], "<nonexistent>");
|
|
|
|
|
}
|
|
|
|
|
const XML_Node& thermo = speciesNode.child("thermo");
|
|
|
|
|
|
|
|
|
|
// Get the children of the thermo XML node. In the next bit of code we take out the comments that
|
|
|
|
|
// may have been children of the thermo XML node by doing a selective copy.
|
|
|
|
|
// These shouldn't interfere with the algorithm at any point.
|
|
|
|
|
const std::vector<XML_Node*>& tpWC = thermo.children();
|
|
|
|
|
std::vector<XML_Node*> tp;
|
|
|
|
|
for (size_t i = 0; i < tpWC.size(); i++) {
|
|
|
|
|
if (!(tpWC[i])->isComment()) {
|
|
|
|
|
tp.push_back(tpWC[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (thermo["model"] == "MineralEQ3") {
|
|
|
|
|
const XML_Node* f = tp[0];
|
|
|
|
|
if (f->name() != "MinEQ3") {
|
|
|
|
|
throw CanteraError("SpeciesThermoFactory::installThermoForSpecies",
|
|
|
|
|
"confused: expedted MinEQ3");
|
|
|
|
|
}
|
|
|
|
|
installMinEQ3asShomateThermoFromXML(speciesNode["name"], th_ptr, spthermo, k, f);
|
|
|
|
|
} else {
|
|
|
|
|
if (tp.size() == 1) {
|
|
|
|
|
const XML_Node* f = tp[0];
|
|
|
|
|
if (f->name() == "Shomate") {
|
|
|
|
|
installShomateThermoFromXML(speciesNode["name"], spthermo, k, f, 0);
|
|
|
|
|
} else if (f->name() == "const_cp") {
|
|
|
|
|
installSimpleThermoFromXML(speciesNode["name"], spthermo, k, *f);
|
|
|
|
|
} else if (f->name() == "NASA") {
|
|
|
|
|
installNasaThermoFromXML(speciesNode["name"], spthermo, k, f, 0);
|
|
|
|
|
} else if (f->name() == "Mu0") {
|
|
|
|
|
installMu0ThermoFromXML(speciesNode["name"], spthermo, k, f);
|
|
|
|
|
} else if (f->name() == "NASA9") {
|
|
|
|
|
installNasa9ThermoFromXML(speciesNode["name"], spthermo, k, tp);
|
|
|
|
|
} else if (f->name() == "StatMech") {
|
|
|
|
|
installStatMechThermoFromXML(speciesNode["name"], spthermo, k, tp);
|
|
|
|
|
} else if (f->name() == "adsorbate") {
|
|
|
|
|
installAdsorbateThermoFromXML(speciesNode["name"], spthermo, k, *f);
|
|
|
|
|
} else {
|
|
|
|
|
throw UnknownSpeciesThermoModel("installThermoForSpecies",
|
|
|
|
|
speciesNode["name"], f->name());
|
|
|
|
|
}
|
|
|
|
|
} else if (tp.size() == 2) {
|
|
|
|
|
const XML_Node* f0 = tp[0];
|
|
|
|
|
const XML_Node* f1 = tp[1];
|
|
|
|
|
if (f0->name() == "NASA" && f1->name() == "NASA") {
|
|
|
|
|
installNasaThermoFromXML(speciesNode["name"], spthermo, k, f0, f1);
|
|
|
|
|
} else if (f0->name() == "Shomate" && f1->name() == "Shomate") {
|
|
|
|
|
installShomateThermoFromXML(speciesNode["name"], spthermo, k, f0, f1);
|
|
|
|
|
} else if (f0->name() == "StatMech") {
|
|
|
|
|
installStatMechThermoFromXML(speciesNode["name"], spthermo, k, tp);
|
|
|
|
|
} else if (f0->name() == "NASA9" && f1->name() == "NASA9") {
|
|
|
|
|
installNasa9ThermoFromXML(speciesNode["name"], spthermo, k, tp);
|
|
|
|
|
} else {
|
|
|
|
|
throw UnknownSpeciesThermoModel("installThermoForSpecies", speciesNode["name"],
|
|
|
|
|
f0->name() + " and " + f1->name());
|
|
|
|
|
}
|
|
|
|
|
} else if (tp.size() > 2) {
|
|
|
|
|
const XML_Node* f0 = tp[0];
|
|
|
|
|
if (f0->name() == "NASA9") {
|
|
|
|
|
installNasa9ThermoFromXML(speciesNode["name"], spthermo, k, tp);
|
|
|
|
|
} else if (f0->name() == "StatMech") {
|
|
|
|
|
installStatMechThermoFromXML(speciesNode["name"], spthermo, k, tp);
|
|
|
|
|
} else {
|
|
|
|
|
throw UnknownSpeciesThermoModel("installThermoForSpecies", speciesNode["name"],
|
|
|
|
|
"multiple");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
throw UnknownSpeciesThermoModel("installThermoForSpecies", speciesNode["name"],
|
|
|
|
|
"multiple");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
SpeciesThermoInterpType* stit = newSpeciesThermoInterpType(speciesNode);
|
|
|
|
|
stit->validate(speciesNode["name"]);
|
|
|
|
|
stit->setIndex(k);
|
|
|
|
|
spthermo.install_STIT(stit);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SpeciesThermoFactory::installVPThermoForSpecies(size_t k,
|
|
|
|
|
@ -831,6 +698,74 @@ void SpeciesThermoFactory::installVPThermoForSpecies(size_t k,
|
|
|
|
|
vp_ptr->createInstallPDSS(k, speciesNode, phaseNode_ptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SpeciesThermoInterpType* newSpeciesThermoInterpType(const XML_Node& speciesNode)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Check to see that the species block has a thermo block
|
|
|
|
|
* before processing. Throw an error if not there.
|
|
|
|
|
*/
|
|
|
|
|
if (!(speciesNode.hasChild("thermo"))) {
|
|
|
|
|
throw UnknownSpeciesThermoModel("installThermoForSpecies",
|
|
|
|
|
speciesNode["name"], "<nonexistent>");
|
|
|
|
|
}
|
|
|
|
|
const XML_Node& thermo = speciesNode.child("thermo");
|
|
|
|
|
|
|
|
|
|
// Get the children of the thermo XML node. In the next bit of code we take out the comments that
|
|
|
|
|
// may have been children of the thermo XML node by doing a selective copy.
|
|
|
|
|
// These shouldn't interfere with the algorithm at any point.
|
|
|
|
|
const std::vector<XML_Node*>& tpWC = thermo.children();
|
|
|
|
|
std::vector<XML_Node*> tp;
|
|
|
|
|
for (size_t i = 0; i < tpWC.size(); i++) {
|
|
|
|
|
if (!(tpWC[i])->isComment()) {
|
|
|
|
|
tp.push_back(tpWC[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string thermoType = lowercase(tp[0]->name());
|
|
|
|
|
std::string specName = speciesNode["name"];
|
|
|
|
|
|
|
|
|
|
for (size_t i = 1; i < tp.size(); i++) {
|
|
|
|
|
if (lowercase(tp[i]->name()) != thermoType) {
|
|
|
|
|
throw CanteraError("newSpeciesThermoInterpType",
|
|
|
|
|
"Encounter unsupported mixed species thermo parameterizations "
|
|
|
|
|
"for species '" + specName + "'.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ((tp.size() > 2 && thermoType != "nasa9") ||
|
|
|
|
|
(tp.size() > 1 && (thermoType == "const_cp" ||
|
|
|
|
|
thermoType == "mu0" ||
|
|
|
|
|
thermoType == "adsorbate"))) {
|
|
|
|
|
throw CanteraError("newSpeciesThermoInterpType",
|
|
|
|
|
"Too many regions in thermo parameterization for species '" +
|
|
|
|
|
specName + "'.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (thermo["model"] == "MineralEQ3") {
|
|
|
|
|
if (thermoType != "mineq3") {
|
|
|
|
|
throw CanteraError("SpeciesThermoFactory::installThermoForSpecies",
|
|
|
|
|
"confused: expedted MinEQ3");
|
|
|
|
|
}
|
|
|
|
|
return newShomateForMineralEQ3(specName, *tp[0]);
|
|
|
|
|
} else if (thermoType == "shomate") {
|
|
|
|
|
return newShomateThermoFromXML(specName, tp);
|
|
|
|
|
} else if (thermoType == "const_cp") {
|
|
|
|
|
return newConstCpThermoFromXML(specName, *tp[0]);
|
|
|
|
|
} else if (thermoType == "nasa") {
|
|
|
|
|
return newNasaThermoFromXML(specName, tp);
|
|
|
|
|
} else if (thermoType == "mu0") {
|
|
|
|
|
return newMu0ThermoFromXML(specName, *tp[0]);
|
|
|
|
|
} else if (thermoType == "nasa9") {
|
|
|
|
|
return newNasa9ThermoFromXML(specName, tp);
|
|
|
|
|
} else if (thermoType == "adsorbate") {
|
|
|
|
|
return newAdsorbateThermoFromXML(specName, *tp[0]);
|
|
|
|
|
} else if (thermoType == "statmech") {
|
|
|
|
|
return newStatMechThermoFromXML(specName, *tp[0]);
|
|
|
|
|
} else {
|
|
|
|
|
throw UnknownSpeciesThermoModel("installThermoForSpecies",
|
|
|
|
|
specName, thermoType);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SpeciesThermo* newSpeciesThermoMgr(int type, SpeciesThermoFactory* f)
|
|
|
|
|
{
|
|
|
|
|
warn_deprecated("newSpeciesThermoMgr", "To be removed after Cantera 2.2. "
|
|
|
|
|
|