doublereal MolarityIonicVPSSTP::err(const std::string& msg) const { throw CanteraError("MolarityIonicVPSSTP","Base class method " +msg+" called. Equation of state type: "+int2str(eosType())); return 0; }
PDSS* VPSSMgr_General::returnPDSS_ptr(size_t k, const XML_Node& speciesNode, const XML_Node* const phaseNode_ptr, bool& doST) { PDSS* kPDSS = 0; doST = true; GeneralSpeciesThermo* genSpthermo = dynamic_cast<GeneralSpeciesThermo*>(m_spthermo); const XML_Node* const ss = speciesNode.findByName("standardState"); if (!ss) { VPSSMgr::installSTSpecies(k, speciesNode, phaseNode_ptr); kPDSS = new PDSS_IdealGas(m_vptp_ptr, k, speciesNode, *phaseNode_ptr, true); return kPDSS; } std::string model = (*ss)["model"]; if (model == "constant_incompressible") { VPSSMgr::installSTSpecies(k, speciesNode, phaseNode_ptr); kPDSS = new PDSS_ConstVol(m_vptp_ptr, k, speciesNode, *phaseNode_ptr, true); if (!kPDSS) { throw CanteraError("VPSSMgr_General::returnPDSS_ptr", "new PDSS_ConstVol failed"); } } else if (model == "waterIAPWS" || model == "waterPDSS") { // VPSSMgr::installSTSpecies(k, speciesNode, phaseNode_ptr); kPDSS = new PDSS_Water(m_vptp_ptr, 0); if (!genSpthermo) { throw CanteraError("VPSSMgr_General::returnPDSS_ptr", "failed dynamic cast"); } genSpthermo->installPDSShandler(k, kPDSS, this); m_useTmpRefStateStorage = false; } else if (model == "HKFT") { doST = false; kPDSS = new PDSS_HKFT(m_vptp_ptr, k, speciesNode, *phaseNode_ptr, true); if (!genSpthermo) { throw CanteraError("VPSSMgr_General::returnPDSS_ptr", "failed dynamic cast"); } genSpthermo->installPDSShandler(k, kPDSS, this); } else if (model == "IonFromNeutral") { if (!genSpthermo) { throw CanteraError("VPSSMgr_General::returnPDSS_ptr", "failed dynamic cast"); } doST = false; kPDSS = new PDSS_IonsFromNeutral(m_vptp_ptr, k, speciesNode, *phaseNode_ptr, true); if (!kPDSS) { throw CanteraError("VPSSMgr_General::returnPDSS_ptr", "new PDSS_IonsFromNeutral failed"); } genSpthermo->installPDSShandler(k, kPDSS, this); } else if (model == "constant" || model == "temperature_polynomial" || model == "density_temperature_polynomial") { VPSSMgr::installSTSpecies(k, speciesNode, phaseNode_ptr); kPDSS = new PDSS_SSVol(m_vptp_ptr, k, speciesNode, *phaseNode_ptr, true); if (!kPDSS) { throw CanteraError("VPSSMgr_General::returnPDSS_ptr", "new PDSS_SSVol failed"); } } else { throw CanteraError("VPSSMgr_General::returnPDSS_ptr", "unknown standard state formulation: " + model); } return kPDSS; }
void vcs_VolPhase::resize(const size_t phaseNum, const size_t nspecies, const size_t numElem, const char* const phaseName, const double molesInert) { AssertThrowMsg(nspecies > 0, "vcs_VolPhase::resize", "nspecies Error"); setTotalMolesInert(molesInert); m_phi = 0.0; m_phiVarIndex = npos; if (phaseNum == VP_ID_) { if (strcmp(PhaseName.c_str(), phaseName)) { throw CanteraError("vcs_VolPhase::resize", "Strings are different: " + PhaseName + " " + phaseName + " :unknown situation"); } } else { VP_ID_ = phaseNum; if (!phaseName) { std::stringstream sstmp; sstmp << "Phase_" << VP_ID_; PhaseName = sstmp.str(); } else { PhaseName = phaseName; } } if (nspecies > 1) { m_singleSpecies = false; } else { m_singleSpecies = true; } if (m_numSpecies == nspecies && numElem == m_numElemConstraints) { return; } m_numSpecies = nspecies; if (nspecies > 1) { m_singleSpecies = false; } IndSpecies.resize(nspecies, npos); if (ListSpeciesPtr.size() >= m_numSpecies) { for (size_t i = 0; i < m_numSpecies; i++) { if (ListSpeciesPtr[i]) { delete ListSpeciesPtr[i]; ListSpeciesPtr[i] = 0; } } } ListSpeciesPtr.resize(nspecies, 0); for (size_t i = 0; i < nspecies; i++) { ListSpeciesPtr[i] = new vcs_SpeciesProperties(phaseNum, i, this); } Xmol_.resize(nspecies, 0.0); creationMoleNumbers_.resize(nspecies, 0.0); creationGlobalRxnNumbers_.resize(nspecies, npos); for (size_t i = 0; i < nspecies; i++) { Xmol_[i] = 1.0/nspecies; creationMoleNumbers_[i] = 1.0/nspecies; if (IndSpecies[i] >= m_numElemConstraints) { creationGlobalRxnNumbers_[i] = IndSpecies[i] - m_numElemConstraints; } else { creationGlobalRxnNumbers_[i] = npos; } } SS0ChemicalPotential.resize(nspecies, -1.0); StarChemicalPotential.resize(nspecies, -1.0); StarMolarVol.resize(nspecies, -1.0); PartialMolarVol.resize(nspecies, -1.0); ActCoeff.resize(nspecies, 1.0); np_dLnActCoeffdMolNumber.resize(nspecies, nspecies, 0.0); m_speciesUnknownType.resize(nspecies, VCS_SPECIES_TYPE_MOLNUM); m_UpToDate = false; m_vcsStateStatus = VCS_STATECALC_OLD; m_UpToDate_AC = false; m_UpToDate_VolStar = false; m_UpToDate_VolPM = false; m_UpToDate_GStar = false; m_UpToDate_G0 = false; elemResize(numElem); }
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); }
doublereal Domain1D::initialValue(size_t n, size_t j) { throw CanteraError("Domain1D::initialValue", "base class method called!"); return 0.0; }
/* * initThermoXML() (virtual from ThermoPhase) * Import and initialize a ThermoPhase object * * @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 MixedSolventElectrolyte::initThermoXML(XML_Node& phaseNode, const std::string& id) { string subname = "MixedSolventElectrolyte::initThermoXML"; 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: * <thermo model="MixedSolventElectrolyte" /> */ if (!phaseNode.hasChild("thermo")) { throw CanteraError(subname, "no thermo XML node"); } XML_Node& thermoNode = phaseNode.child("thermo"); string mStringa = thermoNode.attrib("model"); string mString = lowercase(mStringa); if (mString != "MixedSolventElectrolyte") { throw CanteraError(subname, "Unknown thermo model: " + mStringa); } /* * 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; string mStringa = acNode.attrib("model"); string mString = lowercase(mStringa); if (mString != "margules") { 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(); string nodeName = lowercase(stemp); /* * 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 (nodeName == "binaryneutralspeciesparameters") { readXMLBinarySpecies(xmlACChild); } } } /* * Go down the chain */ MolarityIonicVPSSTP::initThermoXML(phaseNode, id); }
void MargulesVPSSTP::readXMLBinarySpecies(XML_Node& xmLBinarySpecies) { string xname = xmLBinarySpecies.name(); if (xname != "binaryNeutralSpeciesParameters") { throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies", "Incorrect name for processing this routine: " + xname); } string aName = xmLBinarySpecies.attrib("speciesA"); if (aName == "") { throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies", "no speciesA attrib"); } string bName = xmLBinarySpecies.attrib("speciesB"); if (bName == "") { throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies", "no speciesB attrib"); } vector_fp vParams; double h0 = 0.0; double h1 = 0.0; double s0 = 0.0; double s1 = 0.0; double vh0 = 0.0; double vh1 = 0.0; double vs0 = 0.0; double vs1 = 0.0; for (size_t iChild = 0; iChild < xmLBinarySpecies.nChildren(); iChild++) { XML_Node& xmlChild = xmLBinarySpecies.child(iChild); string nodeName = toLowerCopy(xmlChild.name()); // Process the binary species interaction parameters. // They are in subblocks labeled: // excessEnthalpy // excessEntropy // excessVolume_Enthalpy // excessVolume_Entropy // Other blocks are currently ignored. // @TODO determine a policy about ignoring blocks that should or shouldn't be there. if (nodeName == "excessenthalpy") { // Get the string containing all of the values getFloatArray(xmlChild, vParams, true, "toSI", "excessEnthalpy"); if (vParams.size() != 2) { throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies" "excessEnthalpy for {} : {}: wrong number of params found." " Need 2", aName, bName); } h0 = vParams[0]; h1 = vParams[1]; } else if (nodeName == "excessentropy") { // Get the string containing all of the values getFloatArray(xmlChild, vParams, true, "toSI", "excessEntropy"); if (vParams.size() != 2) { throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies" "excessEntropy for {} : {}: wrong number of params found." " Need 2", aName, bName); } s0 = vParams[0]; s1 = vParams[1]; } else if (nodeName == "excessvolume_enthalpy") { // Get the string containing all of the values getFloatArray(xmlChild, vParams, true, "toSI", "excessVolume_Enthalpy"); if (vParams.size() != 2) { throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies" "excessVolume_Enthalpy for {} : {}: wrong number of params" " found. Need 2", aName, bName); } vh0 = vParams[0]; vh1 = vParams[1]; } else if (nodeName == "excessvolume_entropy") { // Get the string containing all of the values getFloatArray(xmlChild, vParams, true, "toSI", "excessVolume_Entropy"); if (vParams.size() != 2) { throw CanteraError("MargulesVPSSTP::readXMLBinarySpecies" "excessVolume_Entropy for {} : {}: wrong number of params" " found. Need 2", aName, bName); } vs0 = vParams[0]; vs1 = vParams[1]; } } addBinaryInteraction(aName, bName, h0, h1, s0, s1, vh0, vh1, vs0, vs1); }
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; }
bool Phase::addSpecies(shared_ptr<Species> spec) { if (m_species.find(toLowerCopy(spec->name)) != m_species.end()) { throw CanteraError("Phase::addSpecies", "Phase '{}' already contains a species named '{}'.", m_name, spec->name); } vector_fp comp(nElements()); for (const auto& elem : spec->composition) { size_t m = elementIndex(elem.first); if (m == npos) { // Element doesn't exist in this phase switch (m_undefinedElementBehavior) { case UndefElement::ignore: return false; case UndefElement::add: addElement(elem.first); comp.resize(nElements()); m = elementIndex(elem.first); break; case UndefElement::error: default: throw CanteraError("Phase::addSpecies", "Species '{}' contains an undefined element '{}'.", spec->name, elem.first); } } comp[m] = elem.second; } m_speciesNames.push_back(spec->name); m_species[toLowerCopy(spec->name)] = spec; m_speciesIndices[toLowerCopy(spec->name)] = m_kk; m_speciesCharge.push_back(spec->charge); size_t ne = nElements(); double wt = 0.0; const vector_fp& aw = atomicWeights(); if (spec->charge != 0.0) { size_t eindex = elementIndex("E"); if (eindex != npos) { doublereal ecomp = comp[eindex]; if (fabs(spec->charge + ecomp) > 0.001) { if (ecomp != 0.0) { throw CanteraError("Phase::addSpecies", "Input charge and element E compositions differ " "for species " + spec->name); } else { // Just fix up the element E composition based on the input // species charge comp[eindex] = -spec->charge; } } } else { addElement("E", 0.000545, 0, 0.0, CT_ELEM_TYPE_ELECTRONCHARGE); ne = nElements(); eindex = elementIndex("E"); comp.resize(ne); comp[ne - 1] = - spec->charge; } } for (size_t m = 0; m < ne; m++) { m_speciesComp.push_back(comp[m]); wt += comp[m] * aw[m]; } // Some surface phases may define species representing empty sites // that have zero molecular weight. Give them a very small molecular // weight to avoid dividing by zero. wt = std::max(wt, Tiny); m_molwts.push_back(wt); m_rmolwts.push_back(1.0/wt); m_kk++; // Ensure that the Phase has a valid mass fraction vector that sums to // one. We will assume that species 0 has a mass fraction of 1.0 and mass // fraction of all other species is 0.0. if (m_kk == 1) { m_y.push_back(1.0); m_ym.push_back(m_rmolwts[0]); m_mmw = 1.0 / m_ym[0]; } else { m_y.push_back(0.0); m_ym.push_back(0.0); } invalidateCache(); return true; }
/* * Calculate the constant volume heat capacity * in mks units of J kmol-1 K-1 */ doublereal PDSS_IonsFromNeutral::cv_mole() const { throw CanteraError("PDSS_IonsFromNeutral::cv_mole()", "unimplemented"); return 0.0; }
/// critical density doublereal PDSS_IonsFromNeutral::critDensity() const { throw CanteraError("PDSS_IonsFromNeutral::critDensity()", "unimplemented"); return (0.0); }
/*! * This is called if a 'Shomate' node is found in the XML input. * * @param nodes vector of 1 or 2 'Shomate' XML_Nodes, each defining the * coefficients for a temperature range */ static SpeciesThermoInterpType* newShomateThermoFromXML( vector<XML_Node*>& nodes) { bool dualRange = false; if (nodes.size() == 2) { dualRange = true; } double tmin0 = fpValue(nodes[0]->attrib("Tmin")); double tmax0 = fpValue(nodes[0]->attrib("Tmax")); doublereal p0 = OneAtm; if (nodes[0]->hasAttrib("P0")) { p0 = fpValue(nodes[0]->attrib("P0")); } if (nodes[0]->hasAttrib("Pref")) { p0 = fpValue(nodes[0]->attrib("Pref")); } p0 = OneAtm; double tmin1 = tmax0; double tmax1 = tmin1 + 0.0001; if (dualRange) { tmin1 = fpValue(nodes[1]->attrib("Tmin")); tmax1 = fpValue(nodes[1]->attrib("Tmax")); } vector_fp c0, c1; doublereal tmin, tmid, tmax; if (fabs(tmax0 - tmin1) < 0.01) { tmin = tmin0; tmid = tmax0; tmax = tmax1; getFloatArray(nodes[0]->child("floatArray"), c0, false); if (dualRange) { getFloatArray(nodes[1]->child("floatArray"), c1, false); } else { if(c0.size() != 7) { throw CanteraError("installShomateThermoFromXML", "Shomate thermo requires 7 coefficients in float array."); } c1.resize(7,0.0); copy(c0.begin(), c0.begin()+7, c1.begin()); } } else if (fabs(tmax1 - tmin0) < 0.01) { tmin = tmin1; tmid = tmax1; tmax = tmax0; getFloatArray(nodes[1]->child("floatArray"), c0, false); getFloatArray(nodes[0]->child("floatArray"), c1, false); } else { throw CanteraError("installShomateThermoFromXML", "non-continuous temperature ranges."); } if(c0.size() != 7 || c1.size() != 7) { throw CanteraError("installShomateThermoFromXML", "Shomate thermo requires 7 coefficients in float array."); } vector_fp c(15); c[0] = tmid; copy(c0.begin(), c0.begin()+7, c.begin() + 1); copy(c1.begin(), c1.begin()+7, c.begin() + 8); return newSpeciesThermoInterpType(SHOMATE, tmin, tmax, p0, &c[0]); }
void VCS_SOLVE::vcs_nondim_TP() { if (m_unitsState == VCS_DIMENSIONAL_G) { m_unitsState = VCS_NONDIMENSIONAL_G; double tf = 1.0 / vcs_nondimMult_TP(m_VCS_UnitsFormat, m_temperature); for (size_t i = 0; i < m_numSpeciesTot; ++i) { /* * Modify the standard state and total chemical potential data, * FF(I), to make it dimensionless, i.e., mu / RT. * Thus, we may divide it by the temperature. */ m_SSfeSpecies[i] *= tf; m_deltaGRxn_new[i] *= tf; m_deltaGRxn_old[i] *= tf; m_feSpecies_old[i] *= tf; } m_Faraday_dim = vcs_nondim_Farad(m_VCS_UnitsFormat, m_temperature); /* * Scale the total moles if necessary: * First find out the total moles */ double tmole_orig = vcs_tmoles(); /* * Then add in the total moles of elements that are goals. Either one * or the other is specified here. */ double esum = 0.0; for (size_t i = 0; i < m_numElemConstraints; ++i) { if (m_elType[i] == VCS_ELEM_TYPE_ABSPOS) { esum += fabs(m_elemAbundancesGoal[i]); } } tmole_orig += esum; /* * Ok now test out the bounds on the total moles that this program can * handle. These are a bit arbitrary. However, it would seem that any * reasonable input would be between these two numbers below. */ if (tmole_orig < 1.0E-200 || tmole_orig > 1.0E200) { throw CanteraError("VCS_SOLVE::vcs_nondim_TP", "Total input moles ," + fp2str(tmole_orig) + "is outside the range handled by vcs.\n"); } // Determine the scale of the problem if (tmole_orig > 1.0E4) { m_totalMoleScale = tmole_orig / 1.0E4; } else if (tmole_orig < 1.0E-4) { m_totalMoleScale = tmole_orig / 1.0E-4; } else { m_totalMoleScale = 1.0; } if (m_totalMoleScale != 1.0) { if (m_VCS_UnitsFormat == VCS_UNITS_MKS) { if (DEBUG_MODE_ENABLED && m_debug_print_lvl >= 2) { plogf(" --- vcs_nondim_TP() called: USING A MOLE SCALE OF %g until further notice", m_totalMoleScale); plogendl(); } for (size_t i = 0; i < m_numSpeciesTot; ++i) { if (m_speciesUnknownType[i] != VCS_SPECIES_TYPE_INTERFACIALVOLTAGE) { m_molNumSpecies_old[i] *= (1.0 / m_totalMoleScale); } } for (size_t i = 0; i < m_numElemConstraints; ++i) { m_elemAbundancesGoal[i] *= (1.0 / m_totalMoleScale); } for (size_t iph = 0; iph < m_numPhases; iph++) { TPhInertMoles[iph] *= (1.0 / m_totalMoleScale); if (TPhInertMoles[iph] != 0.0) { vcs_VolPhase* vphase = m_VolPhaseList[iph]; vphase->setTotalMolesInert(TPhInertMoles[iph]); } } } vcs_tmoles(); } } }
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); }
void ConstDensityThermo::setToEquilState(const doublereal* lambda_RT) { throw CanteraError("setToEquilState","not yet impl."); }
// critical density doublereal PDSS_IdealGas::critDensity() const { throw CanteraError("PDSS_IdealGas::critDensity()", "unimplemented"); return (0.0); }
doublereal MixedSolventElectrolyte::err(const std::string& msg) const { throw CanteraError("MixedSolventElectrolyte","Base class method " +msg+" called. Equation of state type: "+int2str(eosType())); return 0; }
// saturation pressure doublereal PDSS_IdealGas::satPressure(doublereal t) { throw CanteraError("PDSS_IdealGas::satPressure()", "unimplemented"); /*NOTREACHED*/ return (0.0); }
/* * Process an XML node called "binaryNeutralSpeciesParameters" * This node contains all of the parameters necessary to describe * the Margules Interaction for a single binary interaction * This function reads the XML file and writes the coefficients * it finds to an internal data structures. */ void MixedSolventElectrolyte::readXMLBinarySpecies(XML_Node& xmLBinarySpecies) { string xname = xmLBinarySpecies.name(); if (xname != "binaryNeutralSpeciesParameters") { throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies", "Incorrect name for processing this routine: " + xname); } double* charge = DATA_PTR(m_speciesCharge); string stemp; size_t nParamsFound; vector_fp vParams; string iName = xmLBinarySpecies.attrib("speciesA"); if (iName == "") { throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies", "no speciesA attrib"); } string jName = xmLBinarySpecies.attrib("speciesB"); if (jName == "") { throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies", "no speciesB attrib"); } /* * Find the index of the species in the current phase. It's not * an error to not find the species */ size_t iSpecies = speciesIndex(iName); if (iSpecies == npos) { return; } string ispName = speciesName(iSpecies); if (charge[iSpecies] != 0) { throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies", "speciesA charge problem"); } size_t jSpecies = speciesIndex(jName); if (jSpecies == npos) { return; } string jspName = speciesName(jSpecies); if (charge[jSpecies] != 0) { throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies", "speciesB charge problem"); } resizeNumInteractions(numBinaryInteractions_ + 1); size_t iSpot = numBinaryInteractions_ - 1; m_pSpecies_A_ij[iSpot] = iSpecies; m_pSpecies_B_ij[iSpot] = jSpecies; size_t num = xmLBinarySpecies.nChildren(); for (size_t iChild = 0; iChild < num; iChild++) { XML_Node& xmlChild = xmLBinarySpecies.child(iChild); stemp = xmlChild.name(); string nodeName = lowercase(stemp); /* * Process the binary species interaction child elements */ if (nodeName == "excessenthalpy") { /* * Get the string containing all of the values */ ctml::getFloatArray(xmlChild, vParams, true, "toSI", "excessEnthalpy"); nParamsFound = vParams.size(); if (nParamsFound != 2) { throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies::excessEnthalpy for " + ispName + "::" + jspName, "wrong number of params found"); } m_HE_b_ij[iSpot] = vParams[0]; m_HE_c_ij[iSpot] = vParams[1]; } if (nodeName == "excessentropy") { /* * Get the string containing all of the values */ ctml::getFloatArray(xmlChild, vParams, true, "toSI", "excessEntropy"); nParamsFound = vParams.size(); if (nParamsFound != 2) { throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies::excessEntropy for " + ispName + "::" + jspName, "wrong number of params found"); } m_SE_b_ij[iSpot] = vParams[0]; m_SE_c_ij[iSpot] = vParams[1]; } if (nodeName == "excessvolume_enthalpy") { /* * Get the string containing all of the values */ ctml::getFloatArray(xmlChild, vParams, true, "toSI", "excessVolume_Enthalpy"); nParamsFound = vParams.size(); if (nParamsFound != 2) { throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies::excessVolume_Enthalpy for " + ispName + "::" + jspName, "wrong number of params found"); } m_VHE_b_ij[iSpot] = vParams[0]; m_VHE_c_ij[iSpot] = vParams[1]; } if (nodeName == "excessvolume_entropy") { /* * Get the string containing all of the values */ ctml::getFloatArray(xmlChild, vParams, true, "toSI", "excessVolume_Entropy"); nParamsFound = vParams.size(); if (nParamsFound != 2) { throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies::excessVolume_Entropy for " + ispName + "::" + jspName, "wrong number of params found"); } m_VSE_b_ij[iSpot] = vParams[0]; m_VSE_c_ij[iSpot] = vParams[1]; } } }
/* * * @param file Pointer to the file * @param debug Turn on debug printing * * @ingroup inputfiles */ void ct2ctml(const char* file, const int debug) { #ifdef HAS_NO_PYTHON /* * Section to bomb out if python is not * present in the computation environment. */ string ppath = file; throw CanteraError("ct2ctml", "python cti to ctml conversion requested for file, " + ppath + ", but not available in this computational environment"); #endif time_t aclock; time( &aclock ); int ia = static_cast<int>(aclock); string path = tmpDir()+"/.cttmp"+int2str(ia)+".pyw"; ofstream f(path.c_str()); if (!f) { throw CanteraError("ct2ctml","cannot open "+path+" for writing."); } f << "from ctml_writer import *\n" << "import sys, os, os.path\n" << "file = \"" << file << "\"\n" << "base = os.path.basename(file)\n" << "root, ext = os.path.splitext(base)\n" << "dataset(root)\n" << "execfile(file)\n" << "write()\n"; f.close(); string logfile = tmpDir()+"/ct2ctml.log"; #ifdef _WIN32 string cmd = pypath() + " " + "\"" + path + "\"" + "> " + logfile + " 2>&1"; #else string cmd = "sleep " + sleep() + "; " + "\"" + pypath() + "\"" + " " + "\"" + path + "\"" + " &> " + logfile; #endif #ifdef DEBUG_PATHS writelog("ct2ctml: executing the command " + cmd + "\n"); #endif if (debug > 0) { writelog("ct2ctml: executing the command " + cmd + "\n"); writelog("ct2ctml: the Python command is: " + pypath() + "\n"); } int ierr = 0; try { ierr = system(cmd.c_str()); } catch (...) { ierr = -10; if (debug > 0) { writelog("ct2ctml: command execution failed.\n"); } } /* * This next section may seem a bit weird. However, it is in * response to an issue that arises when running cantera with * cygwin, using cygwin's python intepreter. Basically, the * xml file is written to the local directory by the last * system command. Then, the xml file is read immediately * after by an ifstream() c++ command. Unfortunately, it seems * that the directory info is not being synched fast enough so * that the ifstream() read fails, even though the file is * actually there. Putting in a sleep system call here fixes * this problem. Also, having the xml file pre-existing fixes * the problem as well. There may be more direct ways to fix * this bug; however, I am not aware of them. * HKM -> During the solaris port, I found the same thing. * It probably has to do with NFS syncing problems. * 3/3/06 */ #ifndef _WIN32 string sss = sleep(); if (debug > 0) { writelog("sleeping for " + sss + " secs+\n"); } cmd = "sleep " + sss; try { ierr = system(cmd.c_str()); } catch (...) { ierr = -10; writelog("ct2ctml: command execution failed.\n"); } #else // This command works on windows machines if Windows.h and Winbase.h are included // Sleep(5000); #endif // show the contents of the log file on the screen try { char ch=0; string s = ""; ifstream ferr("ct2ctml.log"); if (ferr) { while (!ferr.eof()) { ferr.get(ch); s += ch; if (ch == '\n') { writelog(s); s = ""; } } ferr.close(); } else { if (debug > 0) { writelog("cannot open ct2ctml.log for reading.\n"); } } } catch (...) { writelog("ct2ctml: caught something \n");; } if (ierr != 0) { string msg = cmd; writelog("ct2ctml: throw cantera error \n");; throw CanteraError("ct2ctml", "could not convert input file to CTML.\n " "Command line was: \n" + msg); } // if the conversion succeeded and DEBUG_PATHS is not defined, // then clean up by deleting the temporary Python file. #ifndef DEBUG_PATHS //#ifdef _WIN32 //cmd = "cmd /C rm " + path; if (debug == 0) remove(path.c_str()); else { writelog("ct2ctml: retaining temporary file "+path+"\n"); } #else if (debug > 0) { writelog("ct2ctml: retaining temporary file "+path+"\n"); } #endif }
/*! * @param spDataNodeList Output vector of pointer to XML_Nodes which contain * the species XML_Nodes for the species in the current phase. * @param spNamesList Output Vector of strings, which contain the names * of the species in the phase * @param spRuleList Output Vector of ints, which contain the value of * sprule for each species in the phase * @param spArray_names Vector of pointers to the XML_Nodes which contains * the names of the species in the phase * @param spArray_dbases Input vector of pointers to species data bases. We * search each data base for the required species * names * @param sprule Input vector of sprule values */ static void formSpeciesXMLNodeList(std::vector<XML_Node*> &spDataNodeList, std::vector<std::string> &spNamesList, vector_int &spRuleList, const std::vector<XML_Node*> spArray_names, const std::vector<XML_Node*> spArray_dbases, const vector_int sprule) { // used to check that each species is declared only once std::map<std::string, bool> declared; for (size_t jsp = 0; jsp < spArray_dbases.size(); jsp++) { const XML_Node& speciesArray = *spArray_names[jsp]; // Get the top XML for the database const XML_Node* db = spArray_dbases[jsp]; // Get the array of species name strings and then count them std::vector<std::string> spnames; getStringArray(speciesArray, spnames); size_t nsp = spnames.size(); // if 'all' is specified as the one and only species in the // spArray_names field, then add all species defined in the // corresponding database to the phase if (nsp == 1 && spnames[0] == "all") { std::vector<XML_Node*> allsp = db->getChildren("species"); nsp = allsp.size(); spnames.resize(nsp); for (size_t nn = 0; nn < nsp; nn++) { string stemp = (*allsp[nn])["name"]; if (!declared[stemp] || sprule[jsp] < 10) { declared[stemp] = true; spNamesList.push_back(stemp); spDataNodeList.push_back(allsp[nn]); spRuleList.push_back(sprule[jsp]); } } } else if (nsp == 1 && spnames[0] == "unique") { std::vector<XML_Node*> allsp = db->getChildren("species"); nsp = allsp.size(); spnames.resize(nsp); for (size_t nn = 0; nn < nsp; nn++) { string stemp = (*allsp[nn])["name"]; if (!declared[stemp]) { declared[stemp] = true; spNamesList.push_back(stemp); spDataNodeList.push_back(allsp[nn]); spRuleList.push_back(sprule[jsp]); } } } else { std::map<std::string, XML_Node*> speciesNodes; for (size_t k = 0; k < db->nChildren(); k++) { XML_Node& child = db->child(k); speciesNodes[child["name"]] = &child; } for (size_t k = 0; k < nsp; k++) { string stemp = spnames[k]; if (!declared[stemp] || sprule[jsp] < 10) { declared[stemp] = true; // Find the species in the database by name. auto iter = speciesNodes.find(stemp); if (iter == speciesNodes.end()) { throw CanteraError("importPhase","no data for species, \"" + stemp + "\""); } spNamesList.push_back(stemp); spDataNodeList.push_back(iter->second); spRuleList.push_back(sprule[jsp]); } } } } }
void ck2cti(const std::string& in_file, const std::string& thermo_file, const std::string& transport_file, const std::string& id_tag) { string python_output; int python_exit_code; try { exec_stream_t python; python.set_wait_timeout(exec_stream_t::s_all, 1800000); // 30 minutes python.start(pypath(), "-i"); stringstream output_stream; ostream& pyin = python.in(); pyin << "if True:\n" << // Use this so that the rest is a single block " import sys\n" << " sys.stderr = sys.stdout\n" << " try:\n" << " from cantera import ck2cti\n" << " except ImportError:\n" << " print('sys.path: ' + repr(sys.path))\n" << " raise\n" " ck2cti.Parser().convertMech(r'" << in_file << "',"; if (thermo_file != "" && thermo_file != "-") { pyin << " thermoFile=r'" << thermo_file << "',"; } if (transport_file != "" && transport_file != "-") { pyin << " transportFile=r'" << transport_file << "',"; } pyin << " phaseName='" << id_tag << "',"; pyin << " permissive=True,"; pyin << " quiet=True)\n"; pyin << " sys.exit(0)\n\n"; pyin << "sys.exit(7)\n"; python.close_in(); std::string line; while (python.out().good()) { std::getline(python.out(), line); output_stream << line << std::endl;; } python.close(); python_exit_code = python.exit_code(); python_output = trimCopy(output_stream.str()); } catch (std::exception& err) { // Report failure to execute Python stringstream message; message << "Error executing python while converting input file:\n"; message << "Python command was: '" << pypath() << "'\n"; message << err.what() << std::endl; throw CanteraError("ct2ctml", message.str()); } if (python_exit_code != 0) { // Report a failure in the conversion process stringstream message; message << "Error converting input file \"" << in_file << "\" to CTI.\n"; message << "Python command was: '" << pypath() << "'\n"; message << "The exit code was: " << python_exit_code << "\n"; if (python_output.size() > 0) { message << "-------------- start of converter log --------------\n"; message << python_output << std::endl; message << "--------------- end of converter log ---------------"; } else { message << "The command did not produce any output." << endl; } throw CanteraError("ck2cti", message.str()); } if (python_output.size() > 0) { // Warn if there was any output from the conversion process stringstream message; message << "Warning: Unexpected output from CTI converter\n"; message << "-------------- start of converter log --------------\n"; message << python_output << std::endl; message << "--------------- end of converter log ---------------\n"; writelog(message.str()); } }
compositionMap parseCompString(const std::string& ss, const std::vector<std::string>& names) { compositionMap x; for (size_t k = 0; k < names.size(); k++) { x[names[k]] = 0.0; } size_t start = 0; size_t stop = 0; size_t left = 0; while (stop < ss.size()) { size_t colon = ss.find(':', left); if (colon == npos) { break; } size_t valstart = ss.find_first_not_of(" \t\n", colon+1); stop = ss.find_first_of(", ;\n\t", valstart); std::string name = ba::trim_copy(ss.substr(start, colon-start)); if (!names.empty() && x.find(name) == x.end()) { throw CanteraError("parseCompString", "unknown species '" + name + "'"); } double value; try { value = fpValueCheck(ss.substr(valstart, stop-valstart)); } catch (CanteraError&) { // If we have a key containing a colon, we expect this to fail. In // this case, take the current substring as part of the key and look // to the right of the next colon for the corresponding value. // Otherwise, this is an invalid composition string. std::string testname = ss.substr(start, stop-start); if (testname.find_first_of(" \n\t") != npos) { // Space, tab, and newline are never allowed in names throw; } else if (ss.substr(valstart, stop-valstart).find(':') != npos) { left = colon + 1; stop = 0; // Force another iteration of this loop continue; } else { throw; } } if (getValue(x, name, 0.0) != 0.0) { throw CanteraError("parseCompString", "Duplicate key: '" + name + "'."); } x[name] = value; start = ss.find_first_not_of(", ;\n\t", stop+1); left = start; } if (left != start) { throw CanteraError("parseCompString", "Unable to parse key-value pair:" "\n'{}'", ss.substr(start, stop)); } if (stop != npos && !ba::trim_copy(ss.substr(stop)).empty()) { throw CanteraError("parseCompString", "Found non-key:value data " "in composition string: '" + ss.substr(stop) + "'"); } return x; }
static std::string call_ctml_writer(const std::string& text, bool isfile) { std::string file, arg; if (isfile) { file = text; arg = "r'" + text + "'"; } else { file = "<string>"; arg = "text=r'''" + text + "'''"; } string python_output, error_output; int python_exit_code; try { exec_stream_t python; python.set_wait_timeout(exec_stream_t::s_all, 1800000); // 30 minutes stringstream output_stream, error_stream; python.start(pypath(), ""); ostream& pyin = python.in(); pyin << "from __future__ import print_function\n" "if True:\n" " import sys\n" " try:\n" " from cantera import ctml_writer\n" " except ImportError:\n" " print('sys.path: ' + repr(sys.path) + '\\n', file=sys.stderr)\n" " raise\n" " ctml_writer.convert("; pyin << arg << ", outName='STDOUT')\n"; pyin << " sys.exit(0)\n\n"; pyin << "sys.exit(7)\n"; python.close_in(); std::string line; while (python.out().good()) { std::getline(python.out(), line); output_stream << line << std::endl; } #ifdef _WIN32 // Sleeping for 1 ms prevents a (somewhat inexplicable) deadlock while // reading from the stream. Sleep(1); #endif while (python.err().good()) { std::getline(python.err(), line); error_stream << line << std::endl; } python.close(); python_exit_code = python.exit_code(); error_output = trimCopy(error_stream.str()); python_output = output_stream.str(); } catch (std::exception& err) { // Report failure to execute Python stringstream message; message << "Error executing python while converting input file:\n"; message << "Python command was: '" << pypath() << "'\n"; message << err.what() << std::endl; throw CanteraError("ct2ctml_string", message.str()); } if (python_exit_code != 0) { // Report a failure in the conversion process stringstream message; message << "Error converting input file \"" << file << "\" to CTML.\n"; message << "Python command was: '" << pypath() << "'\n"; message << "The exit code was: " << python_exit_code << "\n"; if (error_output.size() > 0) { message << "-------------- start of converter log --------------\n"; message << error_output << std::endl; message << "--------------- end of converter log ---------------"; } else { message << "The command did not produce any output." << endl; } throw CanteraError("ct2ctml_string", message.str()); } if (error_output.size() > 0) { // Warn if there was any output from the conversion process stringstream message; message << "Warning: Unexpected output from CTI converter\n"; message << "-------------- start of converter log --------------\n"; message << error_output << std::endl; message << "--------------- end of converter log ---------------\n"; writelog(message.str()); } return python_output; }
/* * @param m String message */ void Kinetics::err(std::string m) const { throw CanteraError("Kinetics::" + m, "The default Base class method was called, when " "the inherited class's method should " "have been called"); }
doublereal PDSS_IdealGas::pressure() const { throw CanteraError("PDSS_IdealGas::pressure()", "unimplemented"); }
doublereal VPStandardStateTP::err(std::string msg) const { throw CanteraError("VPStandardStateTP","Base class method " +msg+" called. Equation of state type: "+int2str(eosType())); return 0; }
/* * initThermoXML() (virtual from ThermoPhase) * * This gets called from importPhase(). It processes the XML file * after the species are set up. This is the main routine for * reading in activity coefficient parameters. * * @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 MineralEQ3::initThermoXML(XML_Node& phaseNode, std::string id) { /* * Find the Thermo XML node */ if (!phaseNode.hasChild("thermo")) { throw CanteraError("HMWSoln::initThermoXML", "no thermo XML node"); } std::vector<const XML_Node *> xspecies = speciesData(); const XML_Node *xsp = xspecies[0]; XML_Node *aStandardState = 0; if (xsp->hasChild("standardState")) { aStandardState = &xsp->child("standardState"); } else { throw CanteraError("MineralEQ3::initThermoXML", "no standard state mode"); } doublereal volVal = 0.0; string smodel = (*aStandardState)["model"]; if (smodel != "constantVolume") { throw CanteraError("MineralEQ3::initThermoXML", "wrong standard state mode"); } if (aStandardState->hasChild("V0_Pr_Tr")) { XML_Node& aV = aStandardState->child("V0_Pr_Tr"); string Aunits = ""; double Afactor = toSI("cm3/gmol"); if (aV.hasAttrib("units")) { Aunits = aV.attrib("units"); Afactor = toSI(Aunits); } volVal = ctml::getFloat(*aStandardState, "V0_Pr_Tr"); m_V0_pr_tr= volVal; volVal *= Afactor; m_speciesSize[0] = volVal; } else { throw CanteraError("MineralEQ3::initThermoXML", "wrong standard state mode"); } doublereal rho = molecularWeight(0) / volVal; setDensity(rho); const XML_Node &sThermo = xsp->child("thermo"); const XML_Node &MinEQ3node = sThermo.child("MinEQ3"); m_deltaG_formation_pr_tr = ctml::getFloatDefaultUnits(MinEQ3node, "DG0_f_Pr_Tr", "cal/gmol", "actEnergy"); m_deltaH_formation_pr_tr = ctml::getFloatDefaultUnits(MinEQ3node, "DH0_f_Pr_Tr", "cal/gmol", "actEnergy"); m_Entrop_pr_tr = ctml::getFloatDefaultUnits(MinEQ3node, "S0_Pr_Tr", "cal/gmol/K"); m_a = ctml::getFloatDefaultUnits(MinEQ3node, "a", "cal/gmol/K"); m_b = ctml::getFloatDefaultUnits(MinEQ3node, "b", "cal/gmol/K2"); m_c = ctml::getFloatDefaultUnits(MinEQ3node, "c", "cal-K/gmol"); convertDGFormation(); }
void vcs_VolPhase::setMolesFromVCS(const int stateCalc, const double* molesSpeciesVCS) { v_totalMoles = m_totalMolesInert; if (molesSpeciesVCS == 0) { AssertThrowMsg(m_owningSolverObject, "vcs_VolPhase::setMolesFromVCS", "shouldn't be here"); if (stateCalc == VCS_STATECALC_OLD) { molesSpeciesVCS = VCS_DATA_PTR(m_owningSolverObject->m_molNumSpecies_old); } else if (stateCalc == VCS_STATECALC_NEW) { molesSpeciesVCS = VCS_DATA_PTR(m_owningSolverObject->m_molNumSpecies_new); } else if (DEBUG_MODE_ENABLED) { throw CanteraError("vcs_VolPhase::setMolesFromVCS", "shouldn't be here"); } } else if (DEBUG_MODE_ENABLED && m_owningSolverObject) { if (stateCalc == VCS_STATECALC_OLD) { if (molesSpeciesVCS != VCS_DATA_PTR(m_owningSolverObject->m_molNumSpecies_old)) { throw CanteraError("vcs_VolPhase::setMolesFromVCS", "shouldn't be here"); } } else if (stateCalc == VCS_STATECALC_NEW) { if (molesSpeciesVCS != VCS_DATA_PTR(m_owningSolverObject->m_molNumSpecies_new)) { throw CanteraError("vcs_VolPhase::setMolesFromVCS", "shouldn't be here"); } } } for (size_t k = 0; k < m_numSpecies; k++) { if (m_speciesUnknownType[k] != VCS_SPECIES_TYPE_INTERFACIALVOLTAGE) { size_t kglob = IndSpecies[k]; v_totalMoles += std::max(0.0, molesSpeciesVCS[kglob]); } } if (v_totalMoles > 0.0) { for (size_t k = 0; k < m_numSpecies; k++) { if (m_speciesUnknownType[k] != VCS_SPECIES_TYPE_INTERFACIALVOLTAGE) { size_t kglob = IndSpecies[k]; double tmp = std::max(0.0, molesSpeciesVCS[kglob]); Xmol_[k] = tmp / v_totalMoles; } } m_existence = VCS_PHASE_EXIST_YES; } else { // This is where we will start to store a better approximation // for the mole fractions, when the phase doesn't exist. // This is currently unimplemented. m_existence = VCS_PHASE_EXIST_NO; } /* * Update the electric potential if it is a solution variable * in the equation system */ if (m_phiVarIndex != npos) { size_t kglob = IndSpecies[m_phiVarIndex]; if (m_numSpecies == 1) { Xmol_[m_phiVarIndex] = 1.0; } else { Xmol_[m_phiVarIndex] = 0.0; } double phi = molesSpeciesVCS[kglob]; setElectricPotential(phi); if (m_numSpecies == 1) { m_existence = VCS_PHASE_EXIST_YES; } } _updateMoleFractionDependencies(); if (m_totalMolesInert > 0.0) { m_existence = VCS_PHASE_EXIST_ALWAYS; } /* * If stateCalc is old and the total moles is positive, * then we have a valid state. If the phase went away, it would * be a valid starting point for F_k's. So, save the state. */ if (stateCalc == VCS_STATECALC_OLD) { if (v_totalMoles > 0.0) { creationMoleNumbers_ = Xmol_; } } /* * Set flags indicating we are up to date with the VCS state vector. */ m_UpToDate = true; m_vcsStateStatus = stateCalc; }
void MolarityIonicVPSSTP::calcPseudoBinaryMoleFractions() const { size_t k; size_t kCat; size_t kMax; doublereal sumCat; doublereal sumAnion; doublereal chP, chM; doublereal sum = 0.0; doublereal sumMax; switch (PBType_) { case PBTYPE_PASSTHROUGH: for (k = 0; k < m_kk; k++) { PBMoleFractions_[k] = moleFractions_[k]; } break; case PBTYPE_SINGLEANION: sumCat = 0.0; sumAnion = 0.0; for (k = 0; k < m_kk; k++) { moleFractionsTmp_[k] = moleFractions_[k]; } kMax = npos; sumMax = 0.0; for (k = 0; k < cationList_.size(); k++) { kCat = cationList_[k]; chP = m_speciesCharge[kCat]; if (moleFractions_[kCat] > sumMax) { kMax = k; sumMax = moleFractions_[kCat]; } sumCat += chP * moleFractions_[kCat]; } k = anionList_[0]; chM = m_speciesCharge[k]; sumAnion = moleFractions_[k] * chM; sum = sumCat - sumAnion; if (fabs(sum) > 1.0E-16) { moleFractionsTmp_[cationList_[kMax]] -= sum / m_speciesCharge[kMax]; sum = 0.0; for (k = 0; k < numCationSpecies_; k++) { sum += moleFractionsTmp_[k]; } for (k = 0; k < numCationSpecies_; k++) { moleFractionsTmp_[k]/= sum; } } for (k = 0; k < numCationSpecies_; k++) { PBMoleFractions_[k] = moleFractionsTmp_[cationList_[k]]; } for (k = 0; k < numPassThroughSpecies_; k++) { PBMoleFractions_[neutralPBindexStart + k] = moleFractions_[passThroughList_[k]]; } sum = std::max(0.0, PBMoleFractions_[0]); for (k = 1; k < numPBSpecies_; k++) { sum += PBMoleFractions_[k]; } for (k = 0; k < numPBSpecies_; k++) { PBMoleFractions_[k] /= sum; } break; case PBTYPE_SINGLECATION: throw CanteraError("eosType", "Unknown type"); break; case PBTYPE_MULTICATIONANION: throw CanteraError("eosType", "Unknown type"); break; default: throw CanteraError("eosType", "Unknown type"); break; } }