Phase& Phase::operator=(const Phase& right) { // Check for self assignment. if (this == &right) { return *this; } // Handle our own data m_kk = right.m_kk; m_ndim = right.m_ndim; m_undefinedElementBehavior = right.m_undefinedElementBehavior; m_temp = right.m_temp; m_dens = right.m_dens; m_mmw = right.m_mmw; m_ym = right.m_ym; m_y = right.m_y; m_molwts = right.m_molwts; m_rmolwts = right.m_rmolwts; m_stateNum = -1; m_speciesNames = right.m_speciesNames; m_speciesComp = right.m_speciesComp; m_speciesCharge = right.m_speciesCharge; m_speciesSize = right.m_speciesSize; m_mm = right.m_mm; m_atomicWeights = right.m_atomicWeights; m_atomicNumbers = right.m_atomicNumbers; m_elementNames = right.m_elementNames; m_entropy298 = right.m_entropy298; m_elem_type = right.m_elem_type; // This is a little complicated. -> Because we delete m_xml in the // destructor, we own m_xml completely, and we need to have our own // individual copies of the XML data tree in each object if (m_xml) { XML_Node* rroot = &m_xml->root(); delete rroot; m_xml = 0; } if (right.m_xml) { XML_Node *rroot = &right.m_xml->root(); XML_Node *root_xml = new XML_Node(); rroot->copy(root_xml); m_xml = findXMLPhase(root_xml, right.m_xml->id()); if (!m_xml) { throw CanteraError("Phase::operator=()", "Confused: Couldn't find original phase " + right.m_xml->id()); } if (&m_xml->root() != root_xml) { throw CanteraError("Phase::operator=()", "confused: root changed"); } } m_id = right.m_id; m_name = right.m_name; return *this; }
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"); } }
/* * Import a phase specification. * Here we read an XML description of the phase. * We import descriptions of the elements that make up the * species in a phase. * We import information about the species, including their * reference state thermodynamic polynomials. We then freeze * the state of the species, and finally call initThermoXML(phase, id) * a member function of the ThermoPhase object to "finish" * the description. * * * @param phase 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 th Pointer to the ThermoPhase object which will * handle the thermodynamics for this phase. * We initialize part of the Thermophase object * here, especially for those objects which are * part of the Cantera Kernel. */ 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(). */ XML_Node &phaseNode_XML = th->xml(); phaseNode_XML.clear(); phase.copy(&phaseNode_XML); // 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. if (phase.hasChild("thermo")) { const XML_Node& eos = phase.child("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. ***************************************************************/ th->addElementsFromXML(phase); /*************************************************************** * Add the species. * * Species definitions may be imported from multiple * sources. For each one, a speciesArray element must be * present. ***************************************************************/ XML_Node* db = 0; vector<XML_Node*> sparrays; phase.getChildren("speciesArray", sparrays); int jsp, nspa = static_cast<int>(sparrays.size()); if (nspa == 0) { 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(nspa,0); // loop over the speciesArray elements for (jsp = 0; jsp < nspa; 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; } } string fname, idstr; // 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. 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); // If the phase has a species thermo manager already installed, // delete it since we are adding new species. delete &th->speciesThermo(); // 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 { vp_spth = newVPSSMgr(vpss_ptr, &phase, spDataNodeList); vpss_ptr->setVPSSMgr(vp_spth); spth = vp_spth->SpeciesThermoMgr(); th->setSpeciesThermo(spth); } int k = 0; int nsp = spDataNodeList.size(); for (int 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; } } // done adding species. th->freezeSpecies(); // Perform any required subclass-specific initialization. th->initThermo(); // Perform any required subclass-specific initialization // that requires the XML phase object string id = ""; th->initThermoXML(phase, id); return true; }