/********************************************************************* * Utility Functions *********************************************************************/ void MaskellSolidSolnPhase::initThermoXML(XML_Node& phaseNode, const std::string& id_) { if (id_.size() > 0 && phaseNode.id() != id_) { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "phasenode and Id are incompatible"); } /* * Check on the thermo field. Must have: * <thermo model="MaskellSolidSolution" /> */ if (phaseNode.hasChild("thermo")) { XML_Node& thNode = phaseNode.child("thermo"); std::string mString = thNode.attrib("model"); if (lowercase(mString) != "maskellsolidsolnphase") { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "Unknown thermo model: " + mString); } /* * Parse the enthalpy of mixing constant */ if (thNode.hasChild("h_mix")) { set_h_mix(fpValue(thNode.child("h_mix").value())); } else { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "Mixing enthalpy parameter not specified."); } if (thNode.hasChild("product_species")) { std::string product_species_name = thNode.child("product_species").value(); product_species_index = speciesIndex(product_species_name); if (product_species_index == static_cast<int>(npos)) { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "Species " + product_species_name + " not found."); } if (product_species_index == 0) { reactant_species_index = 1; } else { reactant_species_index = 0; } } } else { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "Unspecified thermo model"); } // Confirm that the phase only contains 2 species if (m_kk != 2) { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "MaskellSolidSolution model requires exactly 2 species."); } /* * Call the base initThermo, which handles setting the initial * state. */ VPStandardStateTP::initThermoXML(phaseNode, id_); }
void IdealMolalSoln::initThermoXML(XML_Node& phaseNode, const std::string& id_) { MolalityVPSSTP::initThermoXML(phaseNode, id_); if (id_.size() > 0 && phaseNode.id() != id_) { throw CanteraError("IdealMolalSoln::initThermo", "phasenode and Id are incompatible"); } // Find the Thermo XML node if (!phaseNode.hasChild("thermo")) { throw CanteraError("IdealMolalSoln::initThermo", "no thermo XML node"); } XML_Node& thermoNode = phaseNode.child("thermo"); // Possible change the form of the standard concentrations if (thermoNode.hasChild("standardConc")) { XML_Node& scNode = thermoNode.child("standardConc"); setStandardConcentrationModel(scNode["model"]); } if (thermoNode.hasChild("activityCoefficients")) { XML_Node& acNode = thermoNode.child("activityCoefficients"); std::string modelString = acNode.attrib("model"); if (modelString != "IdealMolalSoln") { throw CanteraError("IdealMolalSoln::initThermoXML", "unknown ActivityCoefficient model: " + modelString); } if (acNode.hasChild("idealMolalSolnCutoff")) { XML_Node& ccNode = acNode.child("idealMolalSolnCutoff"); modelString = ccNode.attrib("model"); if (modelString != "") { setCutoffModel(modelString); if (ccNode.hasChild("gamma_o_limit")) { IMS_gamma_o_min_ = getFloat(ccNode, "gamma_o_limit"); } if (ccNode.hasChild("gamma_k_limit")) { IMS_gamma_k_min_ = getFloat(ccNode, "gamma_k_limit"); } if (ccNode.hasChild("X_o_cutoff")) { IMS_X_o_cutoff_ = getFloat(ccNode, "X_o_cutoff"); } if (ccNode.hasChild("c_0_param")) { IMS_cCut_ = getFloat(ccNode, "c_0_param"); } if (ccNode.hasChild("slope_f_limit")) { IMS_slopefCut_ = getFloat(ccNode, "slope_f_limit"); } if (ccNode.hasChild("slope_g_limit")) { IMS_slopegCut_ = getFloat(ccNode, "slope_g_limit"); } } } else { setCutoffModel("none"); } } }
void MixedSolventElectrolyte::initThermoXML(XML_Node& phaseNode, const std::string& id_) { if ((int) id_.size() > 0 && phaseNode.id() != id_) { throw CanteraError("MixedSolventElectrolyte::initThermoXML", "phasenode and Id are incompatible"); } /* * Check on the thermo field. Must have: * <thermo model="MixedSolventElectrolyte" /> */ if (!phaseNode.hasChild("thermo")) { throw CanteraError("MixedSolventElectrolyte::initThermoXML", "no thermo XML node"); } XML_Node& thermoNode = phaseNode.child("thermo"); string mString = thermoNode.attrib("model"); if (lowercase(mString) != "mixedsolventelectrolyte") { throw CanteraError("MixedSolventElectrolyte::initThermoXML", "Unknown thermo model: " + mString); } /* * Go get all of the coefficients and factors in the * activityCoefficients XML block */ if (thermoNode.hasChild("activityCoefficients")) { XML_Node& acNode = thermoNode.child("activityCoefficients"); mString = acNode.attrib("model"); if (lowercase(mString) != "margules") { throw CanteraError("MixedSolventElectrolyte::initThermoXML", "Unknown activity coefficient model: " + mString); } for (size_t i = 0; i < acNode.nChildren(); i++) { XML_Node& xmlACChild = acNode.child(i); /* * Process a binary salt field, or any of the other XML fields * that make up the Pitzer Database. Entries will be ignored * if any of the species in the entry isn't in the solution. */ if (lowercase(xmlACChild.name()) == "binaryneutralspeciesparameters") { readXMLBinarySpecies(xmlACChild); } } } /* * Go down the chain */ MolarityIonicVPSSTP::initThermoXML(phaseNode, id_); }
void MargulesVPSSTP::initThermoXML(XML_Node& phaseNode, const std::string& id_) { if ((int) id_.size() > 0) { string idp = phaseNode.id(); if (idp != id_) { throw CanteraError("MargulesVPSSTP::initThermoXML", "phasenode and Id are incompatible"); } } // Find the Thermo XML node if (!phaseNode.hasChild("thermo")) { throw CanteraError("MargulesVPSSTP::initThermoXML", "no thermo XML node"); } XML_Node& thermoNode = phaseNode.child("thermo"); // Make sure that the thermo model is Margules if (!caseInsensitiveEquals(thermoNode["model"], "margules")) { throw CanteraError("MargulesVPSSTP::initThermoXML", "model name isn't Margules: " + thermoNode["model"]); } // Go get all of the coefficients and factors in the activityCoefficients // XML block if (thermoNode.hasChild("activityCoefficients")) { XML_Node& acNode = thermoNode.child("activityCoefficients"); if (!caseInsensitiveEquals(acNode["model"], "margules")) { throw CanteraError("MargulesVPSSTP::initThermoXML", "Unknown activity coefficient model: " + acNode["model"]); } for (size_t i = 0; i < acNode.nChildren(); i++) { XML_Node& xmlACChild = acNode.child(i); // Process a binary salt field, or any of the other XML fields that // make up the Pitzer Database. Entries will be ignored if any of // the species in the entry isn't in the solution. if (caseInsensitiveEquals(xmlACChild.name(), "binaryneutralspeciesparameters")) { readXMLBinarySpecies(xmlACChild); } } } // Go down the chain GibbsExcessVPSSTP::initThermoXML(phaseNode, id_); }
void Phase::setXMLdata(XML_Node& xmlPhase) { XML_Node* xroot = &xmlPhase.root(); XML_Node *root_xml = new XML_Node(); xroot->copy(root_xml); if (m_xml) { XML_Node *rOld = &m_xml->root(); delete rOld; m_xml = 0; } m_xml = findXMLPhase(root_xml, xmlPhase.id()); if (!m_xml) { throw CanteraError("Phase::setXMLdata()", "XML 'phase' node not found"); } if (&m_xml->root() != root_xml) { throw CanteraError("Phase::setXMLdata()", "Root XML node not found"); } }
void MaskellSolidSolnPhase::initThermoXML(XML_Node& phaseNode, const std::string& id_) { if (id_.size() > 0 && phaseNode.id() != id_) { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "phasenode and Id are incompatible"); } // Check on the thermo field. Must have: // <thermo model="MaskellSolidSolution" /> if (phaseNode.hasChild("thermo")) { XML_Node& thNode = phaseNode.child("thermo"); if (!ba::iequals(thNode["model"], "maskellsolidsolnphase")) { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "Unknown thermo model: " + thNode["model"]); } // Parse the enthalpy of mixing constant if (thNode.hasChild("h_mix")) { set_h_mix(fpValue(thNode.child("h_mix").value())); } else { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "Mixing enthalpy parameter not specified."); } if (thNode.hasChild("product_species")) { setProductSpecies(thNode.child("product_species").value()); } else { setProductSpecies(speciesName(0)); // default } } else { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "Unspecified thermo model"); } // Confirm that the phase only contains 2 species if (m_kk != 2) { throw CanteraError("MaskellSolidSolnPhase::initThermoXML", "MaskellSolidSolution model requires exactly 2 species."); } // Call the base initThermo, which handles setting the initial state. VPStandardStateTP::initThermoXML(phaseNode, id_); }
void RedlichKisterVPSSTP::initThermoXML(XML_Node& phaseNode, const std::string& id_) { if ((int) id_.size() > 0 && phaseNode.id() != id_) { throw CanteraError("RedlichKisterVPSSTP::initThermoXML", "phasenode and Id are incompatible"); } // Check on the thermo field. Must have: // <thermo model="Redlich-Kister" /> if (!phaseNode.hasChild("thermo")) { throw CanteraError("RedlichKisterVPSSTP::initThermoXML", "no thermo XML node"); } XML_Node& thermoNode = phaseNode.child("thermo"); std::string mString = thermoNode.attrib("model"); if (lowercase(mString) != "redlich-kister") { throw CanteraError("RedlichKisterVPSSTP::initThermoXML", "Unknown thermo model: " + mString + " - This object only knows \"Redlich-Kister\" "); } // Go get all of the coefficients and factors in the activityCoefficients // XML block if (thermoNode.hasChild("activityCoefficients")) { XML_Node& acNode = thermoNode.child("activityCoefficients"); mString = acNode.attrib("model"); if (lowercase(mString) != "redlich-kister") { throw CanteraError("RedlichKisterVPSSTP::initThermoXML", "Unknown activity coefficient model: " + mString); } for (size_t i = 0; i < acNode.nChildren(); i++) { XML_Node& xmlACChild = acNode.child(i); // Process a binary salt field, or any of the other XML fields that // make up the Pitzer Database. Entries will be ignored if any of // the species in the entry isn't in the solution. if (lowercase(xmlACChild.name()) == "binaryneutralspeciesparameters") { readXMLBinarySpecies(xmlACChild); } } } // Go down the chain GibbsExcessVPSSTP::initThermoXML(phaseNode, id_); }
void LatticePhase::initThermoXML(XML_Node& phaseNode, const std::string& id_) { if (!id_.empty() && id_ != phaseNode.id()) { throw CanteraError("LatticePhase::initThermoXML", "ids don't match"); } // Check on the thermo field. Must have: // <thermo model="Lattice" /> if (phaseNode.hasChild("thermo")) { XML_Node& thNode = phaseNode.child("thermo"); std::string mString = thNode.attrib("model"); if (lowercase(mString) != "lattice") { throw CanteraError("LatticePhase::initThermoXML", "Unknown thermo model: " + mString); } } else { throw CanteraError("LatticePhase::initThermoXML", "Unspecified thermo model"); } // Now go get the molar volumes. use the default if not found XML_Node& speciesList = phaseNode.child("speciesArray"); XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"], &phaseNode.root()); for (size_t k = 0; k < m_kk; k++) { m_speciesMolarVolume[k] = m_site_density; XML_Node* s = speciesDB->findByAttr("name", speciesName(k)); if (!s) { throw CanteraError(" LatticePhase::initThermoXML", "database problems"); } XML_Node* ss = s->findByName("standardState"); if (ss && ss->findByName("molarVolume")) { m_speciesMolarVolume[k] = getFloat(*ss, "molarVolume", "toSI"); } } // Call the base initThermo, which handles setting the initial state. ThermoPhase::initThermoXML(phaseNode, id_); }
void MolarityIonicVPSSTP::initThermoXML(XML_Node& phaseNode, const std::string& id) { if ((int) id.size() > 0 && phaseNode.id() != id) { throw CanteraError("MolarityIonicVPSSTP::initThermoXML", "phasenode and Id are incompatible"); } // Check on the thermo field. Must have one of: // <thermo model="MolarityIonicVPSS" /> // <thermo model="MolarityIonicVPSSTP" /> if (!phaseNode.hasChild("thermo")) { throw CanteraError("MolarityIonicVPSSTP::initThermoXML", "no thermo XML node"); } XML_Node& thermoNode = phaseNode.child("thermo"); std::string mStringa = thermoNode.attrib("model"); std::string mString = lowercase(mStringa); if (mString != "molarityionicvpss" && mString != "molarityionicvpsstp") { throw CanteraError("MolarityIonicVPSSTP::initThermoXML", "Unknown thermo model: " + mStringa + " - This object only knows \"MolarityIonicVPSSTP\" "); } // Go get all of the coefficients and factors in the activityCoefficients // XML block if (thermoNode.hasChild("activityCoefficients")) { XML_Node& acNode = thermoNode.child("activityCoefficients"); for (size_t i = 0; i < acNode.nChildren(); i++) { XML_Node& xmlACChild = acNode.child(i); // Process a binary interaction if (lowercase(xmlACChild.name()) == "binaryneutralspeciesparameters") { readXMLBinarySpecies(xmlACChild); } } } // Go down the chain GibbsExcessVPSSTP::initThermoXML(phaseNode, id); }
int buildSolutionFromXML(char* src, int ixml, char* id, int ith, int ikin) { try { XML_Node* root = 0; if (ixml > 0) { root = &XmlCabinet::item(ixml); } ThermoPhase& t = ThermoCabinet::item(ith); Kinetics& kin = KineticsCabinet::item(ikin); XML_Node* r = 0; if (root) { r = &root->root(); } XML_Node* x = get_XML_Node(src, r); if (!x) { return false; } importPhase(*x, &t); kin.addPhase(t); kin.init(); installReactionArrays(*x, kin, x->id()); t.setState_TP(300.0, OneAtm); if (r) { if (&x->root() != &r->root()) { delete &x->root(); } } else { delete &x->root(); } return 0; } catch (...) { return handleAllExceptions(-1, ERR); } }
void importPhase(XML_Node& phase, ThermoPhase* th) { // Check the the supplied XML node in fact represents a phase. if (phase.name() != "phase") { throw CanteraError("importPhase", "Current const XML_Node named, " + phase.name() + ", is not a phase element."); } // In this section of code, we get the reference to the phase XML tree // within the ThermoPhase object. Then, we clear it and fill it with the // current information that we are about to use to construct the object. We // will then be able to resurrect the information later by calling xml(). th->setXMLdata(phase); // set the id attribute of the phase to the 'id' attribute in the XML tree. th->setID(phase.id()); th->setName(phase.id()); // Number of spatial dimensions. Defaults to 3 (bulk phase) if (phase.hasAttrib("dim")) { int idim = intValue(phase["dim"]); if (idim < 1 || idim > 3) { throw CanteraError("importPhase", "phase, " + th->id() + ", has unphysical number of dimensions: " + phase["dim"]); } th->setNDim(idim); } else { th->setNDim(3); // default } // Set equation of state parameters. The parameters are specific to each // subclass of ThermoPhase, so this is done by method setParametersFromXML // in each subclass. const XML_Node& eos = phase.child("thermo"); if (phase.hasChild("thermo")) { th->setParametersFromXML(eos); } else { throw CanteraError("importPhase", " phase, " + th->id() + ", XML_Node does not have a \"thermo\" XML_Node"); } VPStandardStateTP* vpss_ptr = 0; int ssConvention = th->standardStateConvention(); if (ssConvention == cSS_CONVENTION_VPSS) { vpss_ptr = dynamic_cast <VPStandardStateTP*>(th); if (vpss_ptr == 0) { throw CanteraError("importPhase", "phase, " + th->id() + ", was VPSS, but dynamic cast failed"); } } // Add the elements. if (ssConvention != cSS_CONVENTION_SLAVE) { installElements(*th, phase); } // Add the species. // // Species definitions may be imported from multiple sources. For each one, // a speciesArray element must be present. vector<XML_Node*> sparrays = phase.getChildren("speciesArray"); if (ssConvention != cSS_CONVENTION_SLAVE && sparrays.empty()) { throw CanteraError("importPhase", "phase, " + th->id() + ", has zero \"speciesArray\" XML nodes.\n" + " There must be at least one speciesArray nodes " "with one or more species"); } vector<XML_Node*> dbases; vector_int sprule(sparrays.size(),0); // Default behavior when importing from CTI/XML is for undefined elements to // be treated as an error th->throwUndefinedElements(); // loop over the speciesArray elements for (size_t jsp = 0; jsp < sparrays.size(); jsp++) { const XML_Node& speciesArray = *sparrays[jsp]; // If the speciesArray element has a child element // // <skip element="undeclared"> // // then set sprule[jsp] to 1, so that any species with an undeclared // element will be quietly skipped when importing species. Additionally, // if the skip node has the following attribute: // // <skip species="duplicate"> // // then duplicate species names will not cause Cantera to throw an // exception. Instead, the duplicate entry will be discarded. if (speciesArray.hasChild("skip")) { const XML_Node& sk = speciesArray.child("skip"); string eskip = sk["element"]; if (eskip == "undeclared") { sprule[jsp] = 1; } string dskip = sk["species"]; if (dskip == "duplicate") { sprule[jsp] += 10; } } // Get a pointer to the node containing the species definitions for the // species declared in this speciesArray element. This may be in the // local file containing the phase element, or may be in another file. XML_Node* db = get_XML_Node(speciesArray["datasrc"], &phase.root()); if (db == 0) { throw CanteraError("importPhase()", " Can not find XML node for species database: " + speciesArray["datasrc"]); } // add this node to the list of species database nodes. dbases.push_back(db); } // Now, collect all the species names and all the XML_Node * pointers for // those species in a single vector. This is where we decide what species // are to be included in the phase. The logic is complicated enough that we // put it in a separate routine. std::vector<XML_Node*> spDataNodeList; std::vector<std::string> spNamesList; vector_int spRuleList; formSpeciesXMLNodeList(spDataNodeList, spNamesList, spRuleList, sparrays, dbases, sprule); size_t nsp = spDataNodeList.size(); if (ssConvention == cSS_CONVENTION_SLAVE && nsp > 0) { throw CanteraError("importPhase()", "For Slave standard states, " "number of species must be zero: {}", nsp); } for (size_t k = 0; k < nsp; k++) { XML_Node* s = spDataNodeList[k]; AssertTrace(s != 0); if (spRuleList[k]) { th->ignoreUndefinedElements(); } th->addSpecies(newSpecies(*s)); if (vpss_ptr) { const XML_Node* const ss = s->findByName("standardState"); std::string ss_model = (ss) ? ss->attrib("model") : "ideal-gas"; unique_ptr<PDSS> kPDSS(newPDSS(ss_model)); kPDSS->setParametersFromXML(*s); vpss_ptr->installPDSS(k, std::move(kPDSS)); } th->saveSpeciesData(k, s); } // Done adding species. Perform any required subclass-specific // initialization. th->initThermo(); // Perform any required subclass-specific initialization that requires the // XML phase object std::string id = ""; th->initThermoXML(phase, id); }
void MolarityIonicVPSSTP::initThermoXML(XML_Node& phaseNode, const std::string& id) { std::string subname = "MolarityIonicVPSSTP::initThermoXML"; std::string stemp; if ((int) id.size() > 0) { string idp = phaseNode.id(); if (idp != id) { throw CanteraError(subname, "phasenode and Id are incompatible"); } } /* * Check on the thermo field. Must have one of: * <thermo model="MolarityIonicVPSS" /> * <thermo model="MolarityIonicVPSSTP" /> */ if (!phaseNode.hasChild("thermo")) { throw CanteraError(subname, "no thermo XML node"); } XML_Node& thermoNode = phaseNode.child("thermo"); std::string mStringa = thermoNode.attrib("model"); std::string mString = lowercase(mStringa); if (mString != "molarityionicvpss" && mString != "molarityionicvpsstp") { throw CanteraError(subname.c_str(), "Unknown thermo model: " + mStringa + " - This object only knows \"MolarityIonicVPSSTP\" "); } /* * Go get all of the coefficients and factors in the * activityCoefficients XML block */ XML_Node* acNodePtr = 0; if (thermoNode.hasChild("activityCoefficients")) { XML_Node& acNode = thermoNode.child("activityCoefficients"); acNodePtr = &acNode; mStringa = acNode.attrib("model"); mString = lowercase(mStringa); // if (mString != "redlich-kister") { // throw CanteraError(subname.c_str(), // "Unknown activity coefficient model: " + mStringa); //} size_t n = acNodePtr->nChildren(); for (size_t i = 0; i < n; i++) { XML_Node& xmlACChild = acNodePtr->child(i); stemp = xmlACChild.name(); std::string nodeName = lowercase(stemp); /* * Process a binary interaction */ if (nodeName == "binaryneutralspeciesparameters") { readXMLBinarySpecies(xmlACChild); } } } /* * Go down the chain */ GibbsExcessVPSSTP::initThermoXML(phaseNode, id); }
bool importPhase(XML_Node& phase, ThermoPhase* th, SpeciesThermoFactory* spfactory) { // Check the the supplied XML node in fact represents a phase. if (phase.name() != "phase") { throw CanteraError("importPhase", "Current const XML_Node named, " + phase.name() + ", is not a phase element."); } /* * In this section of code, we get the reference to the * phase xml tree within the ThermoPhase object. Then, * we clear it and fill it with the current information that * we are about to use to construct the object. We will then * be able to resurrect the information later by calling xml(). */ th->setXMLdata(phase); // set the id attribute of the phase to the 'id' attribute in the XML tree. th->setID(phase.id()); th->setName(phase.id()); // Number of spatial dimensions. Defaults to 3 (bulk phase) if (phase.hasAttrib("dim")) { int idim = intValue(phase["dim"]); if (idim < 1 || idim > 3) throw CanteraError("importPhase", "phase, " + th->id() + ", has unphysical number of dimensions: " + phase["dim"]); th->setNDim(idim); } else { th->setNDim(3); // default } // Set equation of state parameters. The parameters are // specific to each subclass of ThermoPhase, so this is done // by method setParametersFromXML in each subclass. const XML_Node& eos = phase.child("thermo"); if (phase.hasChild("thermo")) { th->setParametersFromXML(eos); } else { throw CanteraError("importPhase", " phase, " + th->id() + ", XML_Node does not have a \"thermo\" XML_Node"); } VPStandardStateTP* vpss_ptr = 0; int ssConvention = th->standardStateConvention(); if (ssConvention == cSS_CONVENTION_VPSS) { vpss_ptr = dynamic_cast <VPStandardStateTP*>(th); if (vpss_ptr == 0) { throw CanteraError("importPhase", "phase, " + th->id() + ", was VPSS, but dynamic cast failed"); } } // if no species thermo factory was supplied, use the default one. if (!spfactory) { spfactory = SpeciesThermoFactory::factory(); } /*************************************************************** * Add the elements. ***************************************************************/ if (ssConvention != cSS_CONVENTION_SLAVE) { installElements(*th, phase); } /*************************************************************** * Add the species. * * Species definitions may be imported from multiple * sources. For each one, a speciesArray element must be * present. ***************************************************************/ vector<XML_Node*> sparrays; phase.getChildren("speciesArray", sparrays); if (ssConvention != cSS_CONVENTION_SLAVE) { if (sparrays.empty()) { throw CanteraError("importPhase", "phase, " + th->id() + ", has zero \"speciesArray\" XML nodes.\n" + " There must be at least one speciesArray nodes " "with one or more species"); } } vector<XML_Node*> dbases; vector_int sprule(sparrays.size(),0); // loop over the speciesArray elements for (size_t jsp = 0; jsp < sparrays.size(); jsp++) { const XML_Node& speciesArray = *sparrays[jsp]; // If the speciesArray element has a child element // // <skip element="undeclared"> // // then set sprule[jsp] to 1, so that any species with an undeclared // element will be quietly skipped when importing species. Additionally, // if the skip node has the following attribute: // // <skip species="duplicate"> // // then duplicate species names will not cause Cantera to throw an // exception. Instead, the duplicate entry will be discarded. if (speciesArray.hasChild("skip")) { const XML_Node& sk = speciesArray.child("skip"); string eskip = sk["element"]; if (eskip == "undeclared") { sprule[jsp] = 1; } string dskip = sk["species"]; if (dskip == "duplicate") { sprule[jsp] += 10; } } // Get a pointer to the node containing the species // definitions for the species declared in this // speciesArray element. This may be in the local file // containing the phase element, or may be in another // file. XML_Node* db = get_XML_Node(speciesArray["datasrc"], &phase.root()); if (db == 0) { throw CanteraError("importPhase()", " Can not find XML node for species database: " + speciesArray["datasrc"]); } // add this node to the list of species database nodes. dbases.push_back(db); } // Now, collect all the species names and all the XML_Node * pointers // for those species in a single vector. This is where we decide what // species are to be included in the phase. // The logic is complicated enough that we put it in a separate routine. std::vector<XML_Node*> spDataNodeList; std::vector<std::string> spNamesList; std::vector<int> spRuleList; formSpeciesXMLNodeList(spDataNodeList, spNamesList, spRuleList, sparrays, dbases, sprule); // Decide whether the the phase has a variable pressure ss or not SpeciesThermo* spth = 0; VPSSMgr* vp_spth = 0; if (ssConvention == cSS_CONVENTION_TEMPERATURE) { // Create a new species thermo manager. Function // 'newSpeciesThermoMgr' looks at the species in the database // to see what thermodynamic property parameterizations are // used, and selects a class that can handle the // parameterizations found. spth = newSpeciesThermoMgr(spDataNodeList); // install it in the phase object th->setSpeciesThermo(spth); } else if (ssConvention == cSS_CONVENTION_SLAVE) { /* * No species thermo manager for this type */ } else if (ssConvention == cSS_CONVENTION_VPSS) { vp_spth = newVPSSMgr(vpss_ptr, &phase, spDataNodeList); vpss_ptr->setVPSSMgr(vp_spth); spth = vp_spth->SpeciesThermoMgr(); th->setSpeciesThermo(spth); } else { throw CanteraError("importPhase()", "unknown convention"); } size_t k = 0; size_t nsp = spDataNodeList.size(); if (ssConvention == cSS_CONVENTION_SLAVE) { if (nsp > 0) { throw CanteraError("importPhase()", "For Slave standard states, number of species must be zero: " + int2str(nsp)); } } for (size_t i = 0; i < nsp; i++) { XML_Node* s = spDataNodeList[i]; AssertTrace(s != 0); bool ok = installSpecies(k, *s, *th, spth, spRuleList[i], &phase, vp_spth, spfactory); if (ok) { th->saveSpeciesData(k, s); ++k; } } if (ssConvention == cSS_CONVENTION_SLAVE) { th->installSlavePhases(&phase); } // Done adding species. Perform any required subclass-specific // initialization. th->initThermo(); // Perform any required subclass-specific initialization // that requires the XML phase object std::string id = ""; th->initThermoXML(phase, id); return true; }
void IdealSolidSolnPhase::initThermoXML(XML_Node& phaseNode, const std::string& id_) { if (id_.size() > 0 && phaseNode.id() != id_) { throw CanteraError("IdealSolidSolnPhase::initThermoXML", "phasenode and Id are incompatible"); } /* * Check on the thermo field. Must have: * <thermo model="IdealSolidSolution" /> */ if (phaseNode.hasChild("thermo")) { XML_Node& thNode = phaseNode.child("thermo"); string mString = thNode.attrib("model"); if (lowercase(mString) != "idealsolidsolution") { throw CanteraError("IdealSolidSolnPhase::initThermoXML", "Unknown thermo model: " + mString); } } else { throw CanteraError("IdealSolidSolnPhase::initThermoXML", "Unspecified thermo model"); } /* * Form of the standard concentrations. Must have one of: * * <standardConc model="unity" /> * <standardConc model="molar_volume" /> * <standardConc model="solvent_volume" /> */ if (phaseNode.hasChild("standardConc")) { XML_Node& scNode = phaseNode.child("standardConc"); string formStringa = scNode.attrib("model"); string formString = lowercase(formStringa); if (formString == "unity") { m_formGC = 0; } else if (formString == "molar_volume") { m_formGC = 1; } else if (formString == "solvent_volume") { m_formGC = 2; } else { throw CanteraError("IdealSolidSolnPhase::initThermoXML", "Unknown standardConc model: " + formStringa); } } else { throw CanteraError("IdealSolidSolnPhase::initThermoXML", "Unspecified standardConc model"); } /* * Initialize all of the lengths now that we know how many species * there are in the phase. */ initLengths(); /* * Now go get the molar volumes */ XML_Node& speciesList = phaseNode.child("speciesArray"); XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"], &phaseNode.root()); for (size_t k = 0; k < m_kk; k++) { XML_Node* s = speciesDB->findByAttr("name", speciesName(k)); XML_Node* ss = s->findByName("standardState"); m_speciesMolarVolume[k] = getFloat(*ss, "molarVolume", "toSI"); } /* * Call the base initThermo, which handles setting the initial * state. */ ThermoPhase::initThermoXML(phaseNode, id_); }
/* * Import, construct, and initialize a HMWSoln phase * specification from an XML tree into the current object. * * Most of the work is carried out by the cantera base * routine, importPhase(). That routine imports all of the * species and element data, including the standard states * of the species. * * Then, In this routine, we read the information * particular to the specification of the activity * coefficient model for the Pitzer parameterization. * * We also read information about the molar volumes of the * standard states if present in the XML file. * * @param phaseNode This object must be the phase node of a * complete XML tree * description of the phase, including all of the * species data. In other words while "phase" must * point to an XML phase object, it must have * sibling nodes "speciesData" that describe * the species in the phase. * @param id ID of the phase. If nonnull, a check is done * to see if phaseNode is pointing to the phase * with the correct id. */ void MargulesVPSSTP::constructPhaseXML(XML_Node& phaseNode, std::string id) { string stemp; if (id.size() > 0) { string idp = phaseNode.id(); if (idp != id) { throw CanteraError("MargulesVPSSTP::constructPhaseXML", "phasenode and Id are incompatible"); } } /* * Find the Thermo XML node */ if (!phaseNode.hasChild("thermo")) { throw CanteraError("MargulesVPSSTP::constructPhaseXML", "no thermo XML node"); } XML_Node& thermoNode = phaseNode.child("thermo"); /* * Possibly change the form of the standard concentrations */ /* * Get the Name of the Solvent: * <solvent> solventName </solvent> */ string solventName = ""; if (thermoNode.hasChild("solvent")) { XML_Node& scNode = thermoNode.child("solvent"); vector<string> nameSolventa; getStringArray(scNode, nameSolventa); int nsp = static_cast<int>(nameSolventa.size()); if (nsp != 1) { throw CanteraError("MargulesVPSSTP::constructPhaseXML", "badly formed solvent XML node"); } solventName = nameSolventa[0]; } /* * Determine the form of the Pitzer model, * We will use this information to size arrays below. */ if (thermoNode.hasChild("activityCoefficients")) { XML_Node& scNode = thermoNode.child("activityCoefficients"); stemp = scNode.attrib("model"); string formString = lowercase(stemp); if (formString != "") { if (formString == "margules" || formString == "default") { formMargules_ = 0; } else { throw CanteraError("MargulesVPSSTP::constructPhaseXML", "Unknown ActivityCoeff model: " + formString); } } /* * Determine the form of the temperature dependence * of the Pitzer activity coefficient model. */ stemp = scNode.attrib("TempModel"); formString = lowercase(stemp); if (formString != "") { if (formString == "constant" || formString == "default") { formTempModel_ = 0; } else { throw CanteraError("MargulesVPSSTP::constructPhaseXML", "Unknown Pitzer ActivityCoeff Temp model: " + formString); } } } /* * 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("MargulesVPSSTP::constructPhaseXML","importPhase failed "); } }