[Thermo] Extract 'newSpecies(XML_Node&) from thermo initialization

VPStandardStateTP phases now use the same pathway for adding species as
other phase in importPhase. Deprecate the now-unused 'installSpecies'
function.
This commit is contained in:
Ray Speth 2015-04-18 15:12:30 -04:00
parent d27b9ef9b1
commit 2ca603838d
7 changed files with 67 additions and 76 deletions

View file

@ -11,6 +11,7 @@ namespace Cantera
class SpeciesThermoInterpType;
class TransportData;
class XML_Node;
//! Contains data about a single chemical species
/*!
@ -49,6 +50,9 @@ public:
shared_ptr<SpeciesThermoInterpType> thermo;
};
//! Create a new Species object from a 'species' XML_Node.
shared_ptr<Species> newSpecies(const XML_Node& species_node);
}
#endif

View file

@ -274,8 +274,8 @@ void installElements(Phase& th, const XML_Node& phaseNode);
* state thermo properties
* @param factory Pointer to the SpeciesThermoFactory .
* (defaults to 0)
* @deprecated The 'factory' argument is unused and will be removed after
* Cantera 2.2.
* @deprecated Use newSpecies and addSpecies. For VPStandardStateTP phases, call
* createInstallPDSS as well. To be removed after Cantera 2.2.
* @return
* Returns true if everything is ok, false otherwise.
*/

View file

@ -491,6 +491,8 @@ public:
*/
virtual void initThermoXML(XML_Node& phaseNode, const std::string& id);
using Phase::addSpecies;
virtual bool addSpecies(shared_ptr<Species> spec);
//! set the VPSS Mgr
/*!

View file

@ -1,11 +1,16 @@
#include "cantera/thermo/Species.h"
#include "cantera/thermo/SpeciesThermoInterpType.h"
#include "cantera/thermo/SpeciesThermoFactory.h"
#include "cantera/transport/TransportData.h"
#include "cantera/base/stringUtils.h"
#include "cantera/base/ctexceptions.h"
#include "cantera/base/ctml.h"
#include <iostream>
#include <limits>
using namespace ctml;
namespace Cantera {
Species::Species()
@ -55,4 +60,26 @@ Species& Species::operator=(const Species& other)
return *this;
}
shared_ptr<Species> newSpecies(const XML_Node& species_node)
{
std::string name = species_node["name"];
compositionMap comp = parseCompString(species_node.child("atomArray").value());
shared_ptr<Species> s(new Species(name, comp));
if (species_node.hasChild("charge")) {
s->charge = getFloat(species_node, "charge");
}
if (species_node.hasChild("size")) {
s->size = getFloat(species_node, "size");
}
s->thermo.reset(newSpeciesThermoInterpType(species_node.child("thermo")));
// Read transport data, if provided
if (species_node.hasChild("transport")) {
s->transport = newTransportData(species_node.child("transport"));
s->transport->validate(*s);
}
return s;
}
}

View file

@ -625,7 +625,8 @@ SpeciesThermoInterpType* newSpeciesThermoInterpType(const XML_Node& thermo)
"Too many regions in thermo parameterization.");
}
if (thermo["model"] == "MineralEQ3") {
std::string model = lowercase(thermo["model"]);
if (model == "mineraleq3") {
if (thermoType != "mineq3") {
throw CanteraError("SpeciesThermoFactory::installThermoForSpecies",
"confused: expected MinEQ3");
@ -645,6 +646,11 @@ SpeciesThermoInterpType* newSpeciesThermoInterpType(const XML_Node& thermo)
return newAdsorbateThermoFromXML(*tp[0]);
} else if (thermoType == "statmech") {
return newStatMechThermoFromXML(*tp[0]);
} else if (model == "hkft" || model == "ionfromneutral") {
// Some PDSS species use the 'thermo' node, but don't specify a
// SpeciesThermoInterpType parameterization. This function needs to just
// ignore this data.
return 0;
} else {
throw CanteraError("newSpeciesThermoInterpType",
"Unknown species thermo model '" + thermoType + "'.");

View file

@ -7,6 +7,7 @@
#include "cantera/thermo/ThermoFactory.h"
#include "cantera/thermo/Species.h"
#include "cantera/thermo/speciesThermoTypes.h"
#include "cantera/thermo/SpeciesThermoFactory.h"
#include "cantera/thermo/GeneralSpeciesThermo.h"
@ -52,8 +53,6 @@
#include "cantera/thermo/MixedSolventElectrolyte.h"
#include "cantera/thermo/IdealSolnGasVPSS.h"
#include "cantera/transport/TransportData.h"
#include "cantera/base/stringUtils.h"
using namespace std;
@ -454,17 +453,12 @@ bool importPhase(XML_Node& phase, ThermoPhase* th,
sparrays, dbases, sprule);
// Decide whether the the phase has a variable pressure ss or not
SpeciesThermo* spth = &th->speciesThermo();
VPSSMgr* vp_spth = 0;
if (ssConvention == cSS_CONVENTION_VPSS) {
vp_spth = newVPSSMgr(vpss_ptr, &phase, spDataNodeList);
VPSSMgr* vp_spth = newVPSSMgr(vpss_ptr, &phase, spDataNodeList);
vpss_ptr->setVPSSMgr(vp_spth);
spth = vp_spth->SpeciesThermoMgr();
th->setSpeciesThermo(spth);
th->setSpeciesThermo(vp_spth->SpeciesThermoMgr());
}
size_t k = 0;
size_t nsp = spDataNodeList.size();
if (ssConvention == cSS_CONVENTION_SLAVE) {
if (nsp > 0) {
@ -472,15 +466,17 @@ bool importPhase(XML_Node& phase, ThermoPhase* th,
+ int2str(nsp));
}
}
for (size_t i = 0; i < nsp; i++) {
XML_Node* s = spDataNodeList[i];
for (size_t k = 0; k < nsp; k++) {
XML_Node* s = spDataNodeList[k];
AssertTrace(s != 0);
bool ok = installSpecies(k, *s, *th, spth, spRuleList[i],
&phase, vp_spth, spfactory);
if (ok) {
th->saveSpeciesData(k, s);
++k;
if (spRuleList[k]) {
th->ignoreUndefinedElements();
}
th->addSpecies(newSpecies(*s));
if (vpss_ptr) {
vpss_ptr->createInstallPDSS(k, *s, &phase);
}
th->saveSpeciesData(k, s);
}
if (ssConvention == cSS_CONVENTION_SLAVE) {
@ -572,65 +568,14 @@ bool installSpecies(size_t k, const XML_Node& s, thermo_t& th,
VPSSMgr* vpss_ptr,
SpeciesThermoFactory* factory)
{
std::string xname = s.name();
if (xname != "species") {
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);
// 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()) {
ecomp[m] = fpValueCheck(es);
}
}
// 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.
doublereal chrg = 0.0;
if (s.hasChild("charge")) {
chrg = getFloat(s, "charge");
}
// get the species size, if any. (This is used by surface
// phases to represent how many sites a species occupies.)
doublereal sz = 1.0;
if (s.hasChild("size")) {
sz = getFloat(s, "size");
}
if (vpss_ptr) {
th.addUniqueSpecies(s["name"], &ecomp[0], chrg, sz);
VPStandardStateTP* vp_ptr = dynamic_cast<VPStandardStateTP*>(&th);
warn_deprecated("installSpecies", "Use newSpecies and addSpecies. For"
" VPStandardStateTP phases, call createInstallPDSS as well."
" To be removed after Cantera 2.2.");
th.addSpecies(newSpecies(s));
VPStandardStateTP* vp_ptr = dynamic_cast<VPStandardStateTP*>(&th);
if (vp_ptr) {
vp_ptr->createInstallPDSS(k, s, phaseNode_ptr);
} else {
shared_ptr<Species> sp(new Species(s["name"], comp_map, chrg, sz));
sp->thermo.reset(newSpeciesThermoInterpType(s.child("thermo")));
// Read gas-phase transport data, if provided
if (s.hasChild("transport")) {
sp->transport = newTransportData(s.child("transport"));
sp->transport->validate(*sp);
}
th.addSpecies(sp);
}
return true;
}

View file

@ -260,6 +260,13 @@ void VPStandardStateTP::setVPSSMgr(VPSSMgr* vp_ptr)
m_VPSS_ptr = vp_ptr;
}
bool VPStandardStateTP::addSpecies(shared_ptr<Species> spec)
{
// Specifically skip ThermoPhase::addSpecies since the Species object
// doesn't have an associated SpeciesThermoInterpType object
return Phase::addSpecies(spec);
}
void VPStandardStateTP::setTemperature(const doublereal temp)
{
setState_TP(temp, m_Pcurrent);