Use Species objects when adding species from XML

This commit is contained in:
Ray Speth 2014-10-17 23:44:47 +00:00
parent 11caddea1e
commit 4dd3e1d2bc
11 changed files with 236 additions and 303 deletions

View file

@ -220,9 +220,8 @@ private:
*
* @ingroup spthermo
*/
void installMu0ThermoFromXML(const std::string& speciesName,
SpeciesThermo& sp, size_t k,
const XML_Node* Mu0Node_ptr);
Mu0Poly* newMu0ThermoFromXML(const std::string& speciesName,
const XML_Node& Mu0Node);
}
#endif

View file

@ -34,7 +34,7 @@ public:
~Species();
//! Access the thermodynamic parameterization for the species
const SpeciesThermoInterpType& thermo() const;
SpeciesThermoInterpType& thermo();
//! The name of the species
std::string name;

View file

@ -296,6 +296,14 @@ SpeciesThermoInterpType* newSpeciesThermoInterpType(int type, double tlow,
SpeciesThermoInterpType* newSpeciesThermoInterpType(const std::string& type,
double tlow, double thigh, double pref, const double* coeffs);
//! Create a new SpeciesThermoInterpType object from XML_Node
/*!
* @param speciesNode XML_Node defining the species (with child 'thermo' node)
* @return Returns the pointer to the newly allocated
* SpeciesThermoInterpType object
*/
SpeciesThermoInterpType* newSpeciesThermoInterpType(const XML_Node& speciesNode);
}
#endif

View file

@ -338,7 +338,6 @@ void LatticeSolidPhase::installSlavePhases(Cantera::XML_Node* phaseNode)
{
size_t kk = 0;
size_t kstart = 0;
SpeciesThermoFactory* spFactory = SpeciesThermoFactory::factory();
m_speciesData.clear();
XML_Node& eosdata = phaseNode->child("thermo");
@ -347,7 +346,6 @@ void LatticeSolidPhase::installSlavePhases(Cantera::XML_Node* phaseNode)
la.getChildren("phase",lattices);
for (size_t n = 0; n < m_nlattice; n++) {
LatticePhase* lp = m_lattice[n];
XML_Node* phaseNode_ptr = lattices[n];
size_t nsp = lp->nSpecies();
vector<doublereal> constArr(lp->nElements());
const vector_fp& aws = lp->atomicWeights();
@ -383,8 +381,10 @@ void LatticeSolidPhase::installSlavePhases(Cantera::XML_Node* phaseNode)
double chrg = lp->charge(k);
double sz = lp->size(k);
addUniqueSpecies(sname, &ecomp[0], chrg, sz);
spFactory->installThermoForSpecies(kk, *(spNode[k]), this, *m_spthermo, phaseNode_ptr);
SpeciesThermoInterpType* stit = newSpeciesThermoInterpType(*spNode[k]);
stit->setIndex(kk);
stit->validate(spNode[k]->attrib("name"));
m_spthermo->install_STIT(stit);
m_speciesData.push_back(new XML_Node(*(spNode[k])));
kk++;
}

View file

@ -117,14 +117,11 @@ void Mu0Poly::modifyParameters(doublereal* coeffs)
processCoeffs(coeffs);
}
void installMu0ThermoFromXML(const std::string& speciesName,
SpeciesThermo& sp, size_t k,
const XML_Node* Mu0Node_ptr)
Mu0Poly* newMu0ThermoFromXML(const std::string& speciesName,
const XML_Node& Mu0Node)
{
doublereal tmin, tmax;
bool dimensionlessMu0Values = false;
const XML_Node& Mu0Node = *Mu0Node_ptr;
tmin = fpValue(Mu0Node["Tmin"]);
tmax = fpValue(Mu0Node["Tmax"]);
@ -200,7 +197,7 @@ void installMu0ThermoFromXML(const std::string& speciesName,
c[2+i*2+1] = cValues[i];
}
sp.install(speciesName, k, MU0_INTERP, &c[0], tmin, tmax, pref);
return new Mu0Poly(0, tmin, tmax, pref, &c[0]);
}
void Mu0Poly::processCoeffs(const doublereal* coeffs)

View file

@ -62,7 +62,7 @@ Species& Species::operator=(const Species& other)
}
const SpeciesThermoInterpType& Species::thermo() const
SpeciesThermoInterpType& Species::thermo()
{
if (thermo_) {
return *thermo_;

View file

@ -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. "

View file

@ -585,32 +585,22 @@ bool installSpecies(size_t k, const XML_Node& s, thermo_t& th,
throw CanteraError("installSpecies",
"Unexpected XML name of species XML_Node: " + xname);
}
if (rule) {
th.ignoreUndefinedElements();
}
// get the composition of the species
const XML_Node& a = s.child("atomArray");
map<string,string> comp;
getMap(a, comp);
// check that all elements in the species exist in 'p'. If rule != 0,
// quietly skip this species if some elements are undeclared; otherwise,
// throw an exception
map<string,string>::const_iterator _b = comp.begin();
for (; _b != comp.end(); ++_b) {
if (th.elementIndex(_b->first) == npos) {
if (rule == 0) {
throw CanteraError("installSpecies",
"Species " + s["name"] +
" contains undeclared element " + _b->first);
} else {
return false;
}
}
}
// construct a vector of atom numbers for each element in phase th. Elements
// not declared in the species (i.e., not in map comp) will have zero
// entries in the vector.
size_t nel = th.nElements();
vector_fp ecomp(nel, 0.0);
compositionMap comp_map = parseCompString(a.value());
for (size_t m = 0; m < nel; m++) {
std::string& es = comp[th.elementName(m)];
if (!es.empty()) {
@ -618,7 +608,6 @@ bool installSpecies(size_t k, const XML_Node& s, thermo_t& th,
}
}
// get the species charge, if any. Note that the charge need
// not be explicitly specified if special element 'E'
// (electron) is one of the elements.
@ -634,16 +623,13 @@ bool installSpecies(size_t k, const XML_Node& s, thermo_t& th,
sz = getFloat(s, "size");
}
// add the species to phase th
th.addUniqueSpecies(s["name"], &ecomp[0], chrg, sz);
if (vpss_ptr) {
th.addUniqueSpecies(s["name"], &ecomp[0], chrg, sz);
VPStandardStateTP* vp_ptr = dynamic_cast<VPStandardStateTP*>(&th);
factory->installVPThermoForSpecies(k, s, vp_ptr, phaseNode_ptr);
} else {
// install the thermo parameterization for this species into
// the species thermo manager for phase th
factory->installThermoForSpecies(k, s, &th, *spthermo_ptr, phaseNode_ptr);
SpeciesThermoInterpType* st = newSpeciesThermoInterpType(s);
th.addSpecies(Species(s["name"], comp_map, st, chrg, sz));
}
return true;

View file

@ -699,7 +699,10 @@ bool ThermoPhase::addSpecies(const Species& spec)
{
bool added = Phase::addSpecies(spec);
if (added) {
m_spthermo->install_STIT(spec.thermo().duplMyselfAsSpeciesThermoInterpType());
Species& s = m_species[spec.name];
s.thermo().validate(spec.name);
s.thermo().setIndex(m_kk-1);
m_spthermo->install_STIT(s.thermo().duplMyselfAsSpeciesThermoInterpType());
}
return added;
}

View file

@ -18,6 +18,7 @@
#include "cantera/thermo/PDSS.h"
#include "cantera/thermo/GeneralSpeciesThermo.h"
#include "cantera/base/vec_functions.h"
#include "cantera/base/xml.h"
using namespace std;
@ -400,9 +401,10 @@ void VPSSMgr::initThermoXML(XML_Node& phaseNode, const std::string& id)
void VPSSMgr::installSTSpecies(size_t k, const XML_Node& s,
const XML_Node* phaseNode_ptr)
{
SpeciesThermoFactory* f = SpeciesThermoFactory::factory();
f->installThermoForSpecies(k, s, m_vptp_ptr, *m_spthermo, phaseNode_ptr);
SpeciesThermoInterpType* stit = newSpeciesThermoInterpType(s);
stit->setIndex(k);
stit->validate(s["name"]);
m_spthermo->install_STIT(stit);
if (m_p0 < 0.0) {
m_p0 = m_spthermo->refPressure(k);
}

View file

@ -16,6 +16,7 @@
#include "cantera/base/ctml.h"
#include "cantera/thermo/SpeciesThermoFactory.h"
#include "cantera/thermo/PDSS_IdealGas.h"
#include "cantera/thermo/SpeciesThermoInterpType.h"
using namespace std;
using namespace ctml;
@ -103,8 +104,10 @@ VPSSMgr_IdealGas::createInstallPDSS(size_t k, const XML_Node& speciesNode,
m_Vss.resize(k+1, 0.0);
}
SpeciesThermoFactory* f = SpeciesThermoFactory::factory();
f->installThermoForSpecies(k, speciesNode,(ThermoPhase*) m_vptp_ptr, *m_spthermo, phaseNode_ptr);
SpeciesThermoInterpType* stit = newSpeciesThermoInterpType(speciesNode);
stit->setIndex(k);
stit->validate(speciesNode["name"]);
m_spthermo->install_STIT(stit);
PDSS* kPDSS = new PDSS_IdealGas(m_vptp_ptr, k, speciesNode,
*phaseNode_ptr, true);