void VPSSMgr_ConstVol::initThermoXML(XML_Node& phaseNode, std::string id) { VPSSMgr::initThermoXML(phaseNode, id); XML_Node& speciesList = phaseNode.child("speciesArray"); XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"], &phaseNode.root()); const vector<string>&sss = m_vptp_ptr->speciesNames(); for (int k = 0; k < m_kk; k++) { const XML_Node* s = speciesDB->findByAttr("name", sss[k]); if (!s) { throw CanteraError("VPSSMgr_ConstVol::initThermoXML", "no species Node for species " + sss[k]); } const XML_Node *ss = s->findByName("standardState"); if (!ss) { throw CanteraError("VPSSMgr_ConstVol::initThermoXML", "no standardState Node for species " + s->name()); } std::string model = (*ss)["model"]; if (model != "constant_incompressible" && model != "constantVolume") { throw CanteraError("VPSSMgr_ConstVol::initThermoXML", "standardState model for species isn't constant_incompressible: " + s->name()); } m_Vss[k] = getFloat(*ss, "molarVolume", "toSI"); } }
void PDSS_IonsFromNeutral::constructPDSSFile(VPStandardStateTP* tp, size_t spindex, const std::string& inputFile, const std::string& id) { warn_deprecated("PDSS_IonsFromNeutral::constructPDSSFile", "To be removed after Cantera 2.3."); if (inputFile.size() == 0) { throw CanteraError("PDSS_IonsFromNeutral::constructPDSSFile", "input file is null"); } std::string path = findInputFile(inputFile); ifstream fin(path); if (!fin) { throw CanteraError("PDSS_IonsFromNeutral::constructPDSSFile","could not open " +path+" for reading."); } // The phase object automatically constructs an XML object. Use this object // to store information. XML_Node fxml; fxml.build(fin); XML_Node* fxml_phase = findXMLPhase(&fxml, id); if (!fxml_phase) { throw CanteraError("PDSS_IonsFromNeutral::constructPDSSFile", "ERROR: Can not find phase named " + id + " in file named " + inputFile); } XML_Node& speciesList = fxml_phase->child("speciesArray"); XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"], &fxml_phase->root()); const XML_Node* s = speciesDB->findByAttr("name", tp->speciesName(spindex)); constructPDSSXML(tp, spindex, *s, *fxml_phase, id); }
void VPSSMgr_Water_HKFT::initThermoXML(XML_Node& phaseNode, const std::string& id) { VPSSMgr::initThermoXML(phaseNode, id); XML_Node& speciesList = phaseNode.child("speciesArray"); XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"], &phaseNode.root()); m_waterSS->setState_TP(300., OneAtm); m_Vss[0] = (m_waterSS->density()) / m_vptp_ptr->molecularWeight(0); for (size_t k = 1; k < m_kk; k++) { string name = m_vptp_ptr->speciesName(k); const XML_Node* s = speciesDB->findByAttr("name", name); if (!s) { throw CanteraError("VPSSMgr_Water_HKFT::initThermoXML", "No species Node for species " + name); } const XML_Node* ss = s->findByName("standardState"); if (!ss) { throw CanteraError("VPSSMgr_Water_HKFT::initThermoXML", "No standardState Node for species " + name); } std::string model = lowercase(ss->attrib("model")); if (model != "hkft") { throw CanteraError("VPSSMgr_Water_HKFT::initThermoXML", "Standard state model for a solute species isn't " "the HKFT standard state model: " + name); } } }
void installElements(Phase& th, const XML_Node& phaseNode) { // get the declared element names if (!phaseNode.hasChild("elementArray")) { throw CanteraError("installElements", "phase XML node doesn't have \"elementArray\" XML Node"); } XML_Node& elements = phaseNode.child("elementArray"); vector<string> enames; getStringArray(elements, enames); // // element database defaults to elements.xml string element_database = "elements.xml"; if (elements.hasAttrib("datasrc")) { element_database = elements["datasrc"]; } XML_Node* doc = get_XML_File(element_database); XML_Node* dbe = &doc->child("elementData"); XML_Node& root = phaseNode.root(); XML_Node* local_db = 0; if (root.hasChild("elementData")) { local_db = &root.child("elementData"); } for (size_t i = 0; i < enames.size(); i++) { // Find the element data XML_Node* e = 0; if (local_db) { e = local_db->findByAttr("name",enames[i]); } if (!e) { e = dbe->findByAttr("name",enames[i]); } if (!e) { throw CanteraError("addElementsFromXML","no data for element " +enames[i]); } // Add the element doublereal weight = 0.0; if (e->hasAttrib("atomicWt")) { weight = fpValue(e->attrib("atomicWt")); } int anum = 0; if (e->hasAttrib("atomicNumber")) { anum = intValue(e->attrib("atomicNumber")); } string symbol = e->attrib("name"); doublereal entropy298 = ENTROPY298_UNKNOWN; if (e->hasChild("entropy298")) { XML_Node& e298Node = e->child("entropy298"); if (e298Node.hasAttrib("value")) { entropy298 = fpValueCheck(e298Node["value"]); } } th.addElement(symbol, weight, anum, entropy298); } }
void Phase::addElementsFromXML(const XML_Node& phase) { // get the declared element names if (! phase.hasChild("elementArray")) { throw CanteraError("Elements::addElementsFromXML", "phase xml node doesn't have \"elementArray\" XML Node"); } XML_Node& elements = phase.child("elementArray"); vector<string> enames; ctml::getStringArray(elements, enames); // // element database defaults to elements.xml string element_database = "elements.xml"; if (elements.hasAttrib("datasrc")) { element_database = elements["datasrc"]; } XML_Node* doc = get_XML_File(element_database); XML_Node* dbe = &doc->child("ctml/elementData"); XML_Node& root = phase.root(); XML_Node* local_db = 0; if (root.hasChild("ctml")) { if (root.child("ctml").hasChild("elementData")) { local_db = &root.child("ctml/elementData"); } } int nel = static_cast<int>(enames.size()); int i; string enm; XML_Node* e = 0; for (i = 0; i < nel; i++) { e = 0; if (local_db) { //writelog("looking in local database."); e = local_db->findByAttr("name",enames[i]); //if (!e) writelog(enames[i]+" not found."); } if (!e) { e = dbe->findByAttr("name",enames[i]); } if (e) { addUniqueElement(*e); } else { throw CanteraError("addElementsFromXML","no data for element " +enames[i]); } } }
void VPSSMgr_Water_ConstVol::initThermoXML(XML_Node& phaseNode, const std::string& id) { VPSSMgr::initThermoXML(phaseNode, id); XML_Node& speciesList = phaseNode.child("speciesArray"); XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"], &phaseNode.root()); const vector<string>&sss = m_vptp_ptr->speciesNames(); if (!m_waterSS) { throw CanteraError("VPSSMgr_Water_ConstVol::initThermoXML", "bad dynamic cast"); } m_waterSS->setState_TP(300., OneAtm); m_Vss[0] = (m_waterSS->density()) / m_vptp_ptr->molecularWeight(0); for (size_t k = 1; k < m_kk; k++) { const XML_Node* s = speciesDB->findByAttr("name", sss[k]); if (!s) { throw CanteraError("VPSSMgr_Water_ConstVol::initThermoXML", "no species Node for species " + sss[k]); } const XML_Node* ss = s->findByName("standardState"); if (!ss) { std::string sName = s->operator[]("name"); throw CanteraError("VPSSMgr_Water_ConstVol::initThermoXML", "no standardState Node for species " + sName); } std::string model = (*ss)["model"]; if (model != "constant_incompressible") { std::string sName = s->operator[]("name"); throw CanteraError("VPSSMgr_Water_ConstVol::initThermoXML", "standardState model for species isn't " "constant_incompressible: " + sName); } m_Vss[k] = ctml::getFloat(*ss, "molarVolume", "toSI"); } }
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_); }
/* * * This routine is a precursor to constructPDSSXML(XML_Node*) * routine, which does most of the work. * * @param vptp_ptr Pointer to the Variable pressure %ThermoPhase object * This object must have already been malloced. * * @param spindex Species index within the phase * * @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 PDSS_IonsFromNeutral::constructPDSSFile(VPStandardStateTP* tp, size_t spindex, const std::string& inputFile, const std::string& id) { if (inputFile.size() == 0) { throw CanteraError("PDSS_IonsFromNeutral::constructPDSSFile", "input file is null"); } std::string path = findInputFile(inputFile); ifstream fin(path.c_str()); if (!fin) { throw CanteraError("PDSS_IonsFromNeutral::constructPDSSFile","could not open " +path+" for reading."); } /* * The phase object automatically constructs an XML object. * Use this object to store information. */ XML_Node* fxml = new XML_Node(); fxml->build(fin); XML_Node* fxml_phase = findXMLPhase(fxml, id); if (!fxml_phase) { throw CanteraError("PDSS_IonsFromNeutral::constructPDSSFile", "ERROR: Can not find phase named " + id + " in file named " + inputFile); } XML_Node& speciesList = fxml_phase->child("speciesArray"); XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"], &(fxml_phase->root())); const vector<string>&sss = tp->speciesNames(); const XML_Node* s = speciesDB->findByAttr("name", sss[spindex]); constructPDSSXML(tp, spindex, *s, *fxml_phase, id); delete fxml; }
size_t Phase::addElement(const std::string& symbol, doublereal weight, int atomic_number, doublereal entropy298, int elem_type) { // Look up the atomic weight if not given if (weight == 0.0) { try { weight = getElementWeight(symbol); } catch (CanteraError&) { // assume this is just a custom element with zero atomic weight } } else if (weight == -12345.0) { weight = getElementWeight(symbol); } // Try to look up the standard entropy if not given. Fail silently. if (entropy298 == ENTROPY298_UNKNOWN) { try { XML_Node* db = get_XML_File("elements.xml"); XML_Node* elnode = db->findByAttr("name", symbol); if (elnode && elnode->hasChild("entropy298")) { entropy298 = fpValueCheck(elnode->child("entropy298")["value"]); } } catch (CanteraError&) { } } // Check for duplicates auto iter = find(m_elementNames.begin(), m_elementNames.end(), symbol); if (iter != m_elementNames.end()) { size_t m = iter - m_elementNames.begin(); if (m_atomicWeights[m] != weight) { throw CanteraError("Phase::addElement", "Duplicate elements ({}) have different weights", symbol); } else { // Ignore attempt to add duplicate element with the same weight return m; } } // Add the new element m_atomicWeights.push_back(weight); m_elementNames.push_back(symbol); m_atomicNumbers.push_back(atomic_number); m_entropy298.push_back(entropy298); if (symbol == "E") { m_elem_type.push_back(CT_ELEM_TYPE_ELECTRONCHARGE); } else { m_elem_type.push_back(elem_type); } m_mm++; // Update species compositions if (m_kk) { vector_fp old(m_speciesComp); m_speciesComp.resize(m_kk*m_mm, 0.0); for (size_t k = 0; k < m_kk; k++) { size_t m_old = m_mm - 1; for (size_t m = 0; m < m_old; m++) { m_speciesComp[k * m_mm + m] = old[k * (m_old) + m]; } m_speciesComp[k * (m_mm) + (m_mm-1)] = 0.0; } } return m_mm-1; }
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_); }