From 2ca603838d4596fd3fd9607418b5d3c84e3c0ab0 Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Sat, 18 Apr 2015 15:12:30 -0400 Subject: [PATCH] [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. --- include/cantera/thermo/Species.h | 4 + include/cantera/thermo/ThermoFactory.h | 4 +- include/cantera/thermo/VPStandardStateTP.h | 2 + src/thermo/Species.cpp | 27 +++++++ src/thermo/SpeciesThermoFactory.cpp | 8 +- src/thermo/ThermoFactory.cpp | 91 +++++----------------- src/thermo/VPStandardStateTP.cpp | 7 ++ 7 files changed, 67 insertions(+), 76 deletions(-) diff --git a/include/cantera/thermo/Species.h b/include/cantera/thermo/Species.h index 7664acd40..f2651211d 100644 --- a/include/cantera/thermo/Species.h +++ b/include/cantera/thermo/Species.h @@ -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 thermo; }; +//! Create a new Species object from a 'species' XML_Node. +shared_ptr newSpecies(const XML_Node& species_node); + } #endif diff --git a/include/cantera/thermo/ThermoFactory.h b/include/cantera/thermo/ThermoFactory.h index d83d70b77..faf341e22 100644 --- a/include/cantera/thermo/ThermoFactory.h +++ b/include/cantera/thermo/ThermoFactory.h @@ -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. */ diff --git a/include/cantera/thermo/VPStandardStateTP.h b/include/cantera/thermo/VPStandardStateTP.h index 2538cceaf..c5b0d4bce 100644 --- a/include/cantera/thermo/VPStandardStateTP.h +++ b/include/cantera/thermo/VPStandardStateTP.h @@ -491,6 +491,8 @@ public: */ virtual void initThermoXML(XML_Node& phaseNode, const std::string& id); + using Phase::addSpecies; + virtual bool addSpecies(shared_ptr spec); //! set the VPSS Mgr /*! diff --git a/src/thermo/Species.cpp b/src/thermo/Species.cpp index f69e9c124..99717ce98 100644 --- a/src/thermo/Species.cpp +++ b/src/thermo/Species.cpp @@ -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 #include +using namespace ctml; + namespace Cantera { Species::Species() @@ -55,4 +60,26 @@ Species& Species::operator=(const Species& other) return *this; } +shared_ptr newSpecies(const XML_Node& species_node) +{ + std::string name = species_node["name"]; + compositionMap comp = parseCompString(species_node.child("atomArray").value()); + shared_ptr 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; +} + } diff --git a/src/thermo/SpeciesThermoFactory.cpp b/src/thermo/SpeciesThermoFactory.cpp index aac531370..57d9c8252 100644 --- a/src/thermo/SpeciesThermoFactory.cpp +++ b/src/thermo/SpeciesThermoFactory.cpp @@ -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 + "'."); diff --git a/src/thermo/ThermoFactory.cpp b/src/thermo/ThermoFactory.cpp index 237c60ff3..cb6fe1206 100644 --- a/src/thermo/ThermoFactory.cpp +++ b/src/thermo/ThermoFactory.cpp @@ -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 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(&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(&th); + if (vp_ptr) { vp_ptr->createInstallPDSS(k, s, phaseNode_ptr); - } else { - shared_ptr 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; } diff --git a/src/thermo/VPStandardStateTP.cpp b/src/thermo/VPStandardStateTP.cpp index 40b816eb3..319975875 100644 --- a/src/thermo/VPStandardStateTP.cpp +++ b/src/thermo/VPStandardStateTP.cpp @@ -260,6 +260,13 @@ void VPStandardStateTP::setVPSSMgr(VPSSMgr* vp_ptr) m_VPSS_ptr = vp_ptr; } +bool VPStandardStateTP::addSpecies(shared_ptr 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);