From e911aa1309e9bafd8130ff430d5ad5a31e50d73a Mon Sep 17 00:00:00 2001 From: Harry Moffat Date: Sun, 6 Jun 2010 02:57:02 +0000 Subject: [PATCH] Implementing the expanded species name idea, where we can guarantee a unique name, when dealing with a bunch of phases. Working on the LatticePhase --- Cantera/src/thermo/Constituents.h | 7 ++- Cantera/src/thermo/LatticePhase.cpp | 93 ++++++++++++++++++++++++++++- Cantera/src/thermo/LatticePhase.h | 41 +++++++++++++ Cantera/src/thermo/Phase.cpp | 43 +++++++++++-- Cantera/src/thermo/Phase.h | 74 +++++++++++++++++++++++ Cantera/src/thermo/WaterSSTP.cpp | 6 +- 6 files changed, 253 insertions(+), 11 deletions(-) diff --git a/Cantera/src/thermo/Constituents.h b/Cantera/src/thermo/Constituents.h index 22028b964..be134749f 100644 --- a/Cantera/src/thermo/Constituents.h +++ b/Cantera/src/thermo/Constituents.h @@ -280,12 +280,13 @@ namespace Cantera { doublereal charge = 0.0, doublereal size = 1.0); - //! Returns the index of a species named 'name' within the ThermoPhase + //! Returns the index of a species named 'name' within the Constituents object /*! - * The first species added will have index 0, and the last one index nSpecies() - 1. + * The first species in the phase will have an index 0, and the last one in the + * phase will have an index of nSpecies() - 1. * * @param name String name of the species - * @return Returns the index of the species. If the name is not found + * @return Returns the index of the species. If the name is not found, * the value of -1 is returned. */ int speciesIndex(std::string name) const; diff --git a/Cantera/src/thermo/LatticePhase.cpp b/Cantera/src/thermo/LatticePhase.cpp index 00942edfb..1a93923c4 100644 --- a/Cantera/src/thermo/LatticePhase.cpp +++ b/Cantera/src/thermo/LatticePhase.cpp @@ -23,8 +23,10 @@ #include "mix_defs.h" #include "LatticePhase.h" #include "SpeciesThermo.h" +#include "ThermoFactory.h" #include +#include namespace Cantera { @@ -70,7 +72,27 @@ namespace Cantera { // Destructor LatticePhase::~LatticePhase() { } + + + // Full constructor for a lattice phase + /* + * @param inputFile String name of the input file + * @param id string id of the phase name + */ + LatticePhase::LatticePhase(std::string inputFile, std::string id) { + constructPhaseFile(inputFile, id); + } + // Full constructor for a water phase + /* + * @param phaseRef XML node referencing the lattice phase. + * @param id string id of the phase name + */ + LatticePhase::LatticePhase(XML_Node& phaseRef, std::string id) { + constructPhaseXML(phaseRef, id); + } + + // Duplication function /* * This virtual function is used to create a duplicate of the @@ -84,6 +106,75 @@ namespace Cantera { return (ThermoPhase *) igp; } + /* + * @param infile XML file containing the description of the + * phase + * + * @param id Optional parameter identifying the name of the + * phase. If none is given, the first XML + * phase element will be used. + */ + void LatticePhase::constructPhaseXML(XML_Node& phaseNode, std::string idTarget) { + std::string idattrib = phaseNode.id(); + if (idTarget != idattrib) { + throw CanteraError("LatticePhase::constructPhaseXML","ids don't match"); + } + + /* + * Call the Cantera importPhase() function. This will import + * all of the species into the phase. This will also handle + * all of the solvent and solute standard states. + */ + bool m_ok = importPhase(phaseNode, this); + if (!m_ok) { + throw CanteraError("LatticePhase::constructPhaseXML","importPhase failed "); + } + } + + /* + * constructPhaseFile + * + * + * This routine is a precursor to constructPhaseXML(XML_Node*) + * routine, which does most of the work. + * + * @param inputFile XML file containing the description of the + * phase + * + * @param id Optional parameter identifying the name of the + * phase. If none is given, the first XML + * phase element will be used. + */ + void LatticePhase::constructPhaseFile(std::string inputFile, std::string id) { + + if (inputFile.size() == 0) { + throw CanteraError("LatticePhase::constructPhaseFile", + "input file is null"); + } + std::string path = findInputFile(inputFile); + std::ifstream fin(path.c_str()); + if (!fin) { + throw CanteraError("LatticePhase::constructPhaseFile","could not open " + +path+" for reading."); + } + /* + * The phase object automatically constructs an XML object. + * Use this object to store information. + */ + XML_Node &phaseNode_XML = xml(); + XML_Node *fxml = new XML_Node(); + fxml->build(fin); + XML_Node *fxml_phase = findXMLPhase(fxml, id); + if (!fxml_phase) { + throw CanteraError("LatticePhase::constructPhaseFile", + "ERROR: Can not find phase named " + + id + " in file named " + inputFile); + } + fxml_phase->copy(&phaseNode_XML); + constructPhaseXML(*fxml_phase, id); + delete fxml; + } + doublereal LatticePhase:: enthalpy_mole() const { @@ -247,7 +338,7 @@ namespace Cantera { } void LatticePhase::setParametersFromXML(const XML_Node& eosdata) { - eosdata._require("model","Lattice"); + eosdata._require("model", "Lattice"); m_molar_density = getFloat(eosdata, "site_density", "toSI"); m_vacancy = getChildValue(eosdata, "vacancy_species"); } diff --git a/Cantera/src/thermo/LatticePhase.h b/Cantera/src/thermo/LatticePhase.h index 111848b09..093caece3 100644 --- a/Cantera/src/thermo/LatticePhase.h +++ b/Cantera/src/thermo/LatticePhase.h @@ -274,6 +274,20 @@ namespace Cantera { */ LatticePhase& operator=(const LatticePhase& right); + //! Full constructor for a lattice phase + /*! + * @param inputFile String name of the input file + * @param id string id of the phase name + */ + LatticePhase(std::string inputFile, std::string id = ""); + + //! Full constructor for a water phase + /*! + * @param phaseRef XML node referencing the lattice phase. + * @param id string id of the phase name + */ + LatticePhase(XML_Node& phaseRef, std::string id = ""); + //! Destructor virtual ~LatticePhase(); @@ -287,6 +301,31 @@ namespace Cantera { */ ThermoPhase *duplMyselfAsThermoPhase() const; + /* + * @param infile XML file containing the description of the + * phase + * + * @param id Optional parameter identifying the name of the + * phase. If none is given, the first XML + * phase element will be used. + */ + void constructPhaseXML(XML_Node& phaseNode, std::string idTarget); + + /* + * constructPhaseFile + * + * + * This routine is a precursor to constructPhaseXML(XML_Node*) + * routine, which does most of the work. + * + * @param inputFile XML file containing the description of the + * phase + * + * @param id Optional parameter identifying the name of the + * phase. If none is given, the first XML + * phase element will be used. + */ + void constructPhaseFile(std::string inputFile, std::string id); //! Equation of state flag. Returns the value cLattice virtual int eosType() const { return cLattice; } @@ -814,6 +853,8 @@ namespace Cantera { //! Molar density of the lattice solid /*! + * Currently, this does not change as a function of T, P or composition + * * units are kmol m-3 */ doublereal m_molar_density; diff --git a/Cantera/src/thermo/Phase.cpp b/Cantera/src/thermo/Phase.cpp index 423aa8c24..8367ceb9d 100644 --- a/Cantera/src/thermo/Phase.cpp +++ b/Cantera/src/thermo/Phase.cpp @@ -137,6 +137,41 @@ namespace Cantera { m_index = m; } + // Returns the index of a species named 'name' within the Phase object + /* + * The first species in the phase will have an index 0, and the last one in the + * phase will have an index of nSpecies() - 1. + * + * + * A species name may be referred to via three methods: + * + * - "speciesName" + * - "PhaseId:speciesName" + * - "phaseName:speciesName" + * . + * + * The first two methods of naming may not yield a unique species within + * complicated assemblies of Cantera Phases. + * + * @param nameStr String name of the species. It may also be the phase name + * species name combination, separated by a colon. + * @return Returns the index of the species. If the name is not found, + * the value of -1 is returned. + */ + int Phase::speciesIndex(std::string nameStr) const { + std::string pn; + std::string sn = parseSpeciesName(nameStr, pn); + if (pn == "" || pn == m_name || pn == m_id) { + return Constituents::speciesIndex(sn); + } + return -1; + } + + std::string Phase::speciesSPName(int k) const { + std::string sn = Constituents::speciesName(k); + return(m_name + ":" + sn); + } + void Phase::saveState(vector_fp& state) const { state.resize(nSpecies() + 2); saveState(state.size(),&(state[0])); @@ -315,8 +350,8 @@ namespace Cantera { return State::moleFraction(k); } - doublereal Phase::moleFraction(std::string name) const { - int iloc = speciesIndex(name); + doublereal Phase::moleFraction(std::string nameSpec) const { + int iloc = speciesIndex(nameSpec); if (iloc >= 0) return State::moleFraction(iloc); else return 0.0; } @@ -325,8 +360,8 @@ namespace Cantera { return State::massFraction(k); } - doublereal Phase::massFraction(std::string name) const { - int iloc = speciesIndex(name); + doublereal Phase::massFraction(std::string nameSpec) const { + int iloc = speciesIndex(nameSpec); if (iloc >= 0) return massFractions()[iloc]; else return 0.0; } diff --git a/Cantera/src/thermo/Phase.h b/Cantera/src/thermo/Phase.h index 60c5ec06a..d6de40b1a 100644 --- a/Cantera/src/thermo/Phase.h +++ b/Cantera/src/thermo/Phase.h @@ -138,6 +138,37 @@ namespace Cantera { * vector, which is in general of length (2 + nSpecies()). The first * two entries of the state vector is temperature and density. * + * The class Phase contains two strings that identify a phase. + * The string id() is the value of the ID attribute of the XML phase node + * that is used to initialize a phase when it is read it. + * The id() field will stay that way even if the name is changed. + * The name field is also set to the value of the ID attribute of + * the XML phase node. + * + * However, the name field may be changed to another value during the course of a calculation. + * For example, if a phase is located in two places, but has the same + * constituitive input, the id's of the two phases will be the same, + * but the names of the two phases may be different. + * + * The name of a phase can be the same as the id of that same phase. + * Actually, this is the default and normal condition to have the name and + * the id for each phase to be the same. However, it is expected that + * it's an error to have two phases in a single problem with the same name. + * or the same id (or the name from one phase being the same as the id + * of another phase). + * Thus, it is expected that there is a 1-1 correspondence between + * names and unique phases within a Cantera problem. + * + * A species name may be referred to via three methods: + * + * - "speciesName" + * - "PhaseId:speciesName" + * - "phaseName:speciesName" + * . + * + * The first two methods of naming may not yield a unique species within + * complicated assemblies of Cantera Phases. + * * * @todo * Make the concept of saving state vectors more general, so that @@ -237,6 +268,39 @@ namespace Cantera { */ void setIndex(int m); + //! Returns the index of a species named 'name' within the Phase object + /*! + * The first species in the phase will have an index 0, and the last one in the + * phase will have an index of nSpecies() - 1. + * + * A species name may be referred to via three methods: + * + * - "speciesName" + * - "PhaseId:speciesName" + * - "phaseName:speciesName" + * . + * + * The first two methods of naming may not yield a unique species within + * complicated assemblies of Cantera phases. The last method is guarranteed + * to be unique within a collection of Cantera phases. + * + * @param name String name of the species. It may also be the phase name + * species name combination, separated by a colon. + * @return Returns the index of the species. If the name is not found, + * the value of -1 is returned. + */ + int speciesIndex(std::string name) const; + + //! Returns the expanded species name of a species, including the phase name + /*! + * Returns the expanded phase name species name string. + * This is guarranteed to be unique within a Cantera problem. + * + * @param k Species index within the phase + * @return Returns the "phaseName:speciesName" string + */ + std::string speciesSPName(int k) const; + //! Save the current internal state of the phase /*! * Write to vector 'state' the current internal state. @@ -530,12 +594,22 @@ namespace Cantera { //! ID of the phase. /*! * This is the value of the ID attribute of the XML phase node. + * The field will stay that way even if the name is changed. */ std::string m_id; //! Name of the phase. /*! * Initially, this is the value of the ID attribute of the XML phase node. + * + * It may be changed to another value during the course of a calculation. + * for example, if a phase is located in two places, but has the same + * constituitive input, the id's of the two phases will be the same, + * but the names of the two phases may be different. + * + * The name can be the same as the id, within a phase. However, besides + * that case, it is expected that there is a 1-1 correspondence between + * names and unique phases within a Cantera problem. */ std::string m_name; }; diff --git a/Cantera/src/thermo/WaterSSTP.cpp b/Cantera/src/thermo/WaterSSTP.cpp index 0d3f0ac93..5727ea3de 100644 --- a/Cantera/src/thermo/WaterSSTP.cpp +++ b/Cantera/src/thermo/WaterSSTP.cpp @@ -162,13 +162,13 @@ namespace Cantera { void WaterSSTP::constructPhaseFile(std::string inputFile, std::string id) { if (inputFile.size() == 0) { - throw CanteraError("WaterTp::initThermo", + throw CanteraError("WaterSSTP::constructPhaseFile", "input file is null"); } std::string path = findInputFile(inputFile); std::ifstream fin(path.c_str()); if (!fin) { - throw CanteraError("WaterSSTP::initThermo","could not open " + throw CanteraError("WaterSSTP::constructPhaseFile","could not open " +path+" for reading."); } /* @@ -180,7 +180,7 @@ namespace Cantera { fxml->build(fin); XML_Node *fxml_phase = findXMLPhase(fxml, id); if (!fxml_phase) { - throw CanteraError("WaterSSTP::initThermo", + throw CanteraError("WaterSSTP::constructPhaseFile", "ERROR: Can not find phase named " + id + " in file named " + inputFile); }