void SurfPhase:: setCoveragesByName(std::string cov) { int kk = nSpecies(); int k; compositionMap cc; for (k = 0; k < kk; k++) { cc[speciesName(k)] = -1.0; } parseCompString(cov, cc); doublereal c; vector_fp cv(kk, 0.0); bool ifound = false; for (k = 0; k < kk; k++) { c = cc[speciesName(k)]; if (c > 0.0) { ifound = true; cv[k] = c; } } if (!ifound) { throw CanteraError("SurfPhase::setCoveragesByName", "Input coverages are all zero or negative"); } setCoverages(DATA_PTR(cv)); }
void ThermoPhase::modifySpecies(size_t k, shared_ptr<Species> spec) { Phase::modifySpecies(k, spec); if (speciesName(k) != spec->name) { throw CanteraError("ThermoPhase::modifySpecies", "New species '{}' does not match existing species '{}' at index {}", spec->name, speciesName(k), k); } spec->thermo->validate(spec->name); m_spthermo->modifySpecies(k, spec->thermo); }
/** * Get the mole fractions by name. */ void Phase::getMoleFractionsByName(compositionMap& x) const { x.clear(); int kk = nSpecies(); for (int k = 0; k < kk; k++) { x[speciesName(k)] = State::moleFraction(k); } }
void Phase::modifySpecies(size_t k, shared_ptr<Species> spec) { if (speciesName(k) != spec->name) { throw CanteraError("Phase::modifySpecies", "New species name '{}' does not match existing name '{}'", spec->name, speciesName(k)); } const shared_ptr<Species>& old = m_species[spec->name]; if (spec->composition != old->composition) { throw CanteraError("Phase::modifySpecies", "New composition for '{}' does not match existing composition", spec->name); } m_species[spec->name] = spec; invalidateCache(); }
void ThermoPhase::reportCSV(std::ofstream& csvFile) const { int tabS = 15; int tabM = 30; csvFile.precision(8); vector_fp X(nSpecies()); getMoleFractions(&X[0]); std::vector<std::string> pNames; std::vector<vector_fp> data; getCsvReportData(pNames, data); csvFile << setw(tabS) << "Species,"; for (size_t i = 0; i < pNames.size(); i++) { csvFile << setw(tabM) << pNames[i] << ","; } csvFile << endl; for (size_t k = 0; k < nSpecies(); k++) { csvFile << setw(tabS) << speciesName(k) + ","; if (X[k] > SmallNumber) { for (size_t i = 0; i < pNames.size(); i++) { csvFile << setw(tabM) << data[i][k] << ","; } csvFile << endl; } else { for (size_t i = 0; i < pNames.size(); i++) { csvFile << setw(tabM) << 0 << ","; } csvFile << endl; } } }
void Phase::setMassFractionsByName(const std::string& y) { compositionMap yy; int kk = nSpecies(); for (int k = 0; k < kk; k++) { yy[speciesName(k)] = -1.0; } parseCompString(y, yy); setMassFractionsByName(yy); }
/* * setMolalitiesByNames() * * Set the molalities of the solutes by name */ void MolalityVPSSTP::setMolalitiesByName(const std::string& x) { compositionMap xx; for (size_t k = 0; k < nSpecies(); k++) { xx[speciesName(k)] = -1.0; } parseCompString(x, xx); setMolalitiesByName(xx); }
void Phase::setMassFractionsByName(const compositionMap& yMap) { size_t kk = nSpecies(); vector_fp mf(kk, 0.0); for (size_t k = 0; k < kk; k++) { mf[k] = std::max(getValue(yMap, speciesName(k), 0.0), 0.0); } setMassFractions(&mf[0]); }
/* * The Cl- species is special in the sense that its single ion * molality-based activity coefficient is used in the specification * of the pH scale for single ions. Therefore, we need to know * what species index Cl- is. If the species isn't in the species * list then this routine returns -1, and we can't use the NBS * pH scale. * * Right now we use a restrictive interpretation. The species * must be named "Cl-". It must consist of exactly one Cl and one E * atom. */ size_t MolalityVPSSTP::findCLMIndex() const { size_t indexCLM = npos; size_t eCl = npos; size_t eE = npos; size_t ne = nElements(); string sn; for (size_t e = 0; e < ne; e++) { sn = elementName(e); if (sn == "Cl" || sn == "CL") { eCl = e; break; } } // We have failed if we can't find the Cl element index if (eCl == npos) { return npos; } for (size_t e = 0; e < ne; e++) { sn = elementName(e); if (sn == "E" || sn == "e") { eE = e; break; } } // We have failed if we can't find the E element index if (eE == npos) { return npos; } for (size_t k = 1; k < m_kk; k++) { doublereal nCl = nAtoms(k, eCl); if (nCl != 1.0) { continue; } doublereal nE = nAtoms(k, eE); if (nE != 1.0) { continue; } for (size_t e = 0; e < ne; e++) { if (e != eE && e != eCl) { doublereal nA = nAtoms(k, e); if (nA != 0.0) { continue; } } } sn = speciesName(k); if (sn != "Cl-" && sn != "CL-") { continue; } indexCLM = k; break; } return indexCLM; }
void Phase::setMoleFractionsByName(compositionMap& xMap) { int kk = nSpecies(); doublereal x; vector_fp mf(kk, 0.0); for (int k = 0; k < kk; k++) { x = xMap[speciesName(k)]; if (x > 0.0) mf[k] = x; } setMoleFractions(&mf[0]); }
void Phase::setMoleFractionsByName(const std::string& x) { size_t kk = nSpecies(); compositionMap xx; for (size_t k = 0; k < kk; k++) { xx[speciesName(k)] = -1.0; } parseCompString(x, xx); setMoleFractionsByName(xx); }
void Phase::setMassFractionsByName(compositionMap& yMap) { int kk = nSpecies(); doublereal y; vector_fp mf(kk, 0.0); for (int k = 0; k < kk; k++) { y = yMap[speciesName(k)]; if (y > 0.0) mf[k] = y; } setMassFractions(&mf[0]); }
compositionMap Phase::getMassFractionsByName(double threshold) const { compositionMap comp; for (size_t k = 0; k < m_kk; k++) { double x = massFraction(k); if (x > threshold) { comp[speciesName(k)] = x; } } return comp; }
void Phase::getMoleFractionsByName(compositionMap& x) const { warn_deprecated("void Phase::getMoleFractionsByName(compositionMap&)", "To be removed after Cantera 2.2. Use" " 'compositionMap getMoleFractionsByName(double threshold)'" " instead"); x.clear(); size_t kk = nSpecies(); for (size_t k = 0; k < kk; k++) { x[speciesName(k)] = Phase::moleFraction(k); } }
void Phase::setMoleFractionsByName(const std::string& x) { compositionMap xx; int kk = nSpecies(); for (int k = 0; k < kk; k++) { xx[speciesName(k)] = -1.0; } parseCompString(x, xx); setMoleFractionsByName(xx); //int kk = nSpecies(); //vector_fp mf(kk); //for (int k = 0; k < kk; k++) { // mf[k] = xx[speciesName(k)]; //} //setMoleFractions(mf.begin()); }
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 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_); }
std::string Phase::speciesSPName(int k) const { return m_name + ":" + speciesName(k); }
void RedlichKisterVPSSTP::readXMLBinarySpecies(XML_Node& xmLBinarySpecies) { std::string xname = xmLBinarySpecies.name(); if (xname != "binaryNeutralSpeciesParameters") { throw CanteraError("RedlichKisterVPSSTP::readXMLBinarySpecies", "Incorrect name for processing this routine: " + xname); } size_t Npoly = 0; vector_fp hParams, sParams; std::string iName = xmLBinarySpecies.attrib("speciesA"); if (iName == "") { throw CanteraError("RedlichKisterVPSSTP::readXMLBinarySpecies", "no speciesA attrib"); } std::string jName = xmLBinarySpecies.attrib("speciesB"); if (jName == "") { throw CanteraError("RedlichKisterVPSSTP::readXMLBinarySpecies", "no speciesB attrib"); } /* * Find the index of the species in the current phase. It's not * an error to not find the species. This means that the interaction doesn't occur for the current * implementation of the phase. */ size_t iSpecies = speciesIndex(iName); if (iSpecies == npos) { return; } string ispName = speciesName(iSpecies); if (charge(iSpecies) != 0) { throw CanteraError("RedlichKisterVPSSTP::readXMLBinarySpecies", "speciesA charge problem"); } size_t jSpecies = speciesIndex(jName); if (jSpecies == npos) { return; } std::string jspName = speciesName(jSpecies); if (charge(jSpecies) != 0) { throw CanteraError("RedlichKisterVPSSTP::readXMLBinarySpecies", "speciesB charge problem"); } /* * Ok we have found a valid interaction */ numBinaryInteractions_++; size_t iSpot = numBinaryInteractions_ - 1; m_pSpecies_A_ij.resize(numBinaryInteractions_); m_pSpecies_B_ij.resize(numBinaryInteractions_); m_pSpecies_A_ij[iSpot] = iSpecies; m_pSpecies_B_ij[iSpot] = jSpecies; for (size_t iChild = 0; iChild < xmLBinarySpecies.nChildren(); iChild++) { XML_Node& xmlChild = xmLBinarySpecies.child(iChild); string nodeName = lowercase(xmlChild.name()); /* * Process the binary species interaction child elements */ if (nodeName == "excessenthalpy") { /* * Get the string containing all of the values */ getFloatArray(xmlChild, hParams, true, "toSI", "excessEnthalpy"); Npoly = std::max(hParams.size(), Npoly); } if (nodeName == "excessentropy") { /* * Get the string containing all of the values */ getFloatArray(xmlChild, sParams, true, "toSI", "excessEntropy"); Npoly = std::max(sParams.size(), Npoly); } } hParams.resize(Npoly, 0.0); sParams.resize(Npoly, 0.0); m_HE_m_ij.push_back(hParams); m_SE_m_ij.push_back(sParams); m_N_ij.push_back(Npoly); resizeNumInteractions(numBinaryInteractions_); }
/* * Format a summary of the mixture state for output. */ void MolalityVPSSTP::reportCSV(std::ofstream& csvFile) const { csvFile.precision(3); int tabS = 15; int tabM = 30; int tabL = 40; try { if (name() != "") { csvFile << "\n"+name()+"\n\n"; } csvFile << setw(tabL) << "temperature (K) =" << setw(tabS) << temperature() << endl; csvFile << setw(tabL) << "pressure (Pa) =" << setw(tabS) << pressure() << endl; csvFile << setw(tabL) << "density (kg/m^3) =" << setw(tabS) << density() << endl; csvFile << setw(tabL) << "mean mol. weight (amu) =" << setw(tabS) << meanMolecularWeight() << endl; csvFile << setw(tabL) << "potential (V) =" << setw(tabS) << electricPotential() << endl; csvFile << endl; csvFile << setw(tabL) << "enthalpy (J/kg) = " << setw(tabS) << enthalpy_mass() << setw(tabL) << "enthalpy (J/kmol) = " << setw(tabS) << enthalpy_mole() << endl; csvFile << setw(tabL) << "internal E (J/kg) = " << setw(tabS) << intEnergy_mass() << setw(tabL) << "internal E (J/kmol) = " << setw(tabS) << intEnergy_mole() << endl; csvFile << setw(tabL) << "entropy (J/kg) = " << setw(tabS) << entropy_mass() << setw(tabL) << "entropy (J/kmol) = " << setw(tabS) << entropy_mole() << endl; csvFile << setw(tabL) << "Gibbs (J/kg) = " << setw(tabS) << gibbs_mass() << setw(tabL) << "Gibbs (J/kmol) = " << setw(tabS) << gibbs_mole() << endl; csvFile << setw(tabL) << "heat capacity c_p (J/K/kg) = " << setw(tabS) << cp_mass() << setw(tabL) << "heat capacity c_p (J/K/kmol) = " << setw(tabS) << cp_mole() << endl; csvFile << setw(tabL) << "heat capacity c_v (J/K/kg) = " << setw(tabS) << cv_mass() << setw(tabL) << "heat capacity c_v (J/K/kmol) = " << setw(tabS) << cv_mole() << endl; csvFile.precision(8); vector<std::string> pNames; vector<vector_fp> data; vector_fp temp(nSpecies()); getMoleFractions(&temp[0]); pNames.push_back("X"); data.push_back(temp); try { getMolalities(&temp[0]); pNames.push_back("Molal"); data.push_back(temp); } catch (CanteraError& err) { err.save(); } try { getChemPotentials(&temp[0]); pNames.push_back("Chem. Pot. (J/kmol)"); data.push_back(temp); } catch (CanteraError& err) { err.save(); } try { getStandardChemPotentials(&temp[0]); pNames.push_back("Chem. Pot. SS (J/kmol)"); data.push_back(temp); } catch (CanteraError& err) { err.save(); } try { getMolalityActivityCoefficients(&temp[0]); pNames.push_back("Molal Act. Coeff."); data.push_back(temp); } catch (CanteraError& err) { err.save(); } try { getActivities(&temp[0]); pNames.push_back("Molal Activity"); data.push_back(temp); size_t iHp = speciesIndex("H+"); if (iHp != npos) { double pH = -log(temp[iHp]) / log(10.0); csvFile << setw(tabL) << "pH = " << setw(tabS) << pH << endl; } } catch (CanteraError& err) { err.save(); } try { getPartialMolarEnthalpies(&temp[0]); pNames.push_back("Part. Mol Enthalpy (J/kmol)"); data.push_back(temp); } catch (CanteraError& err) { err.save(); } try { getPartialMolarEntropies(&temp[0]); pNames.push_back("Part. Mol. Entropy (J/K/kmol)"); data.push_back(temp); } catch (CanteraError& err) { err.save(); } try { getPartialMolarIntEnergies(&temp[0]); pNames.push_back("Part. Mol. Energy (J/kmol)"); data.push_back(temp); } catch (CanteraError& err) { err.save(); } try { getPartialMolarCp(&temp[0]); pNames.push_back("Part. Mol. Cp (J/K/kmol"); data.push_back(temp); } catch (CanteraError& err) { err.save(); } try { getPartialMolarVolumes(&temp[0]); pNames.push_back("Part. Mol. Cv (J/K/kmol)"); data.push_back(temp); } catch (CanteraError& err) { err.save(); } csvFile << endl << setw(tabS) << "Species,"; for (size_t i = 0; i < pNames.size(); i++) { csvFile << setw(tabM) << pNames[i] << ","; } csvFile << endl; /* csvFile.fill('-'); csvFile << setw(tabS+(tabM+1)*pNames.size()) << "-\n"; csvFile.fill(' '); */ for (size_t k = 0; k < nSpecies(); k++) { csvFile << setw(tabS) << speciesName(k) + ","; if (data[0][k] > SmallNumber) { for (size_t i = 0; i < pNames.size(); i++) { csvFile << setw(tabM) << data[i][k] << ","; } csvFile << endl; } else { for (size_t i = 0; i < pNames.size(); i++) { csvFile << setw(tabM) << 0 << ","; } csvFile << endl; } } } catch (CanteraError& err) { err.save(); } }
/** * Format a summary of the mixture state for output. */ std::string MolalityVPSSTP::report(bool show_thermo) const { char p[800]; string s = ""; try { if (name() != "") { sprintf(p, " \n %s:\n", name().c_str()); s += p; } sprintf(p, " \n temperature %12.6g K\n", temperature()); s += p; sprintf(p, " pressure %12.6g Pa\n", pressure()); s += p; sprintf(p, " density %12.6g kg/m^3\n", density()); s += p; sprintf(p, " mean mol. weight %12.6g amu\n", meanMolecularWeight()); s += p; doublereal phi = electricPotential(); sprintf(p, " potential %12.6g V\n", phi); s += p; size_t kk = nSpecies(); vector_fp x(kk); vector_fp molal(kk); vector_fp mu(kk); vector_fp muss(kk); vector_fp acMolal(kk); vector_fp actMolal(kk); getMoleFractions(&x[0]); getMolalities(&molal[0]); getChemPotentials(&mu[0]); getStandardChemPotentials(&muss[0]); getMolalityActivityCoefficients(&acMolal[0]); getActivities(&actMolal[0]); size_t iHp = speciesIndex("H+"); if (iHp != npos) { double pH = -log(actMolal[iHp]) / log(10.0); sprintf(p, " pH %12.4g \n", pH); s += p; } if (show_thermo) { sprintf(p, " \n"); s += p; sprintf(p, " 1 kg 1 kmol\n"); s += p; sprintf(p, " ----------- ------------\n"); s += p; sprintf(p, " enthalpy %12.6g %12.4g J\n", enthalpy_mass(), enthalpy_mole()); s += p; sprintf(p, " internal energy %12.6g %12.4g J\n", intEnergy_mass(), intEnergy_mole()); s += p; sprintf(p, " entropy %12.6g %12.4g J/K\n", entropy_mass(), entropy_mole()); s += p; sprintf(p, " Gibbs function %12.6g %12.4g J\n", gibbs_mass(), gibbs_mole()); s += p; sprintf(p, " heat capacity c_p %12.6g %12.4g J/K\n", cp_mass(), cp_mole()); s += p; try { sprintf(p, " heat capacity c_v %12.6g %12.4g J/K\n", cv_mass(), cv_mole()); s += p; } catch (CanteraError& err) { err.save(); sprintf(p, " heat capacity c_v <not implemented> \n"); s += p; } } sprintf(p, " \n"); s += p; if (show_thermo) { sprintf(p, " X " " Molalities Chem.Pot. ChemPotSS ActCoeffMolal\n"); s += p; sprintf(p, " " " (J/kmol) (J/kmol) \n"); s += p; sprintf(p, " ------------- " " ------------ ------------ ------------ ------------\n"); s += p; for (size_t k = 0; k < kk; k++) { if (x[k] > SmallNumber) { sprintf(p, "%18s %12.6g %12.6g %12.6g %12.6g %12.6g\n", speciesName(k).c_str(), x[k], molal[k], mu[k], muss[k], acMolal[k]); } else { sprintf(p, "%18s %12.6g %12.6g N/A %12.6g %12.6g \n", speciesName(k).c_str(), x[k], molal[k], muss[k], acMolal[k]); } s += p; } } else { sprintf(p, " X" "Molalities\n"); s += p; sprintf(p, " -------------" " ------------\n"); s += p; for (size_t k = 0; k < kk; k++) { sprintf(p, "%18s %12.6g %12.6g\n", speciesName(k).c_str(), x[k], molal[k]); s += p; } } } catch (CanteraError& err) { err.save(); } return s; }
std::string Phase::speciesSPName(int k) const { std::string sn = speciesName(k); return m_name + ":" + sn; }
std::string ThermoPhase::report(bool show_thermo, doublereal threshold) const { fmt::MemoryWriter b; try { if (name() != "") { b.write("\n {}:\n", name()); } b.write("\n"); b.write(" temperature {:12.6g} K\n", temperature()); b.write(" pressure {:12.6g} Pa\n", pressure()); b.write(" density {:12.6g} kg/m^3\n", density()); b.write(" mean mol. weight {:12.6g} amu\n", meanMolecularWeight()); doublereal phi = electricPotential(); if (phi != 0.0) { b.write(" potential {:12.6g} V\n", phi); } if (show_thermo) { b.write("\n"); b.write(" 1 kg 1 kmol\n"); b.write(" ----------- ------------\n"); b.write(" enthalpy {:12.5g} {:12.4g} J\n", enthalpy_mass(), enthalpy_mole()); b.write(" internal energy {:12.5g} {:12.4g} J\n", intEnergy_mass(), intEnergy_mole()); b.write(" entropy {:12.5g} {:12.4g} J/K\n", entropy_mass(), entropy_mole()); b.write(" Gibbs function {:12.5g} {:12.4g} J\n", gibbs_mass(), gibbs_mole()); b.write(" heat capacity c_p {:12.5g} {:12.4g} J/K\n", cp_mass(), cp_mole()); try { b.write(" heat capacity c_v {:12.5g} {:12.4g} J/K\n", cv_mass(), cv_mole()); } catch (NotImplementedError&) { b.write(" heat capacity c_v <not implemented> \n"); } } vector_fp x(m_kk); vector_fp y(m_kk); vector_fp mu(m_kk); getMoleFractions(&x[0]); getMassFractions(&y[0]); getChemPotentials(&mu[0]); int nMinor = 0; doublereal xMinor = 0.0; doublereal yMinor = 0.0; b.write("\n"); if (show_thermo) { b.write(" X " " Y Chem. Pot. / RT\n"); b.write(" ------------- " "------------ ------------\n"); for (size_t k = 0; k < m_kk; k++) { if (abs(x[k]) >= threshold) { if (abs(x[k]) > SmallNumber) { b.write("{:>18s} {:12.6g} {:12.6g} {:12.6g}\n", speciesName(k), x[k], y[k], mu[k]/RT()); } else { b.write("{:>18s} {:12.6g} {:12.6g}\n", speciesName(k), x[k], y[k]); } } else { nMinor++; xMinor += x[k]; yMinor += y[k]; } } } else { b.write(" X Y\n"); b.write(" ------------- ------------\n"); for (size_t k = 0; k < m_kk; k++) { if (abs(x[k]) >= threshold) { b.write("{:>18s} {:12.6g} {:12.6g}\n", speciesName(k), x[k], y[k]); } else { nMinor++; xMinor += x[k]; yMinor += y[k]; } } } if (nMinor) { b.write(" [{:+5d} minor] {:12.6g} {:12.6g}\n", nMinor, xMinor, yMinor); } } catch (CanteraError& err) { return b.str() + err.what(); } return b.str(); }
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_); }
void MixedSolventElectrolyte::readXMLBinarySpecies(XML_Node& xmLBinarySpecies) { string xname = xmLBinarySpecies.name(); if (xname != "binaryNeutralSpeciesParameters") { throw CanteraError("MixedSolventElectrolyte::readXMLBinarySpecies", "Incorrect name for processing this routine: " + xname); } 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]; } } }
void MolalityVPSSTP::setMolalitiesByName(const compositionMap& mMap) { // HKM -> Might need to be more complicated here, setting neutrals so that // the existing mole fractions are preserved. // Get a vector of mole fractions vector_fp mf(m_kk, 0.0); getMoleFractions(mf.data()); double xmolSmin = std::max(mf[m_indexSolvent], m_xmolSolventMIN); for (size_t k = 0; k < m_kk; k++) { double mol_k = getValue(mMap, speciesName(k), 0.0); if (mol_k > 0) { mf[k] = mol_k * m_Mnaught * xmolSmin; } } // check charge neutrality size_t largePos = npos; double cPos = 0.0; size_t largeNeg = npos; double cNeg = 0.0; double sum = 0.0; for (size_t k = 0; k < m_kk; k++) { double ch = charge(k); if (mf[k] > 0.0) { if (ch > 0.0 && ch * mf[k] > cPos) { largePos = k; cPos = ch * mf[k]; } if (ch < 0.0 && fabs(ch) * mf[k] > cNeg) { largeNeg = k; cNeg = fabs(ch) * mf[k]; } } sum += mf[k] * ch; } if (sum != 0.0) { if (sum > 0.0) { if (cPos > sum) { mf[largePos] -= sum / charge(largePos); } else { throw CanteraError("MolalityVPSSTP:setMolalitiesbyName", "unbalanced charges"); } } else { if (cNeg > (-sum)) { mf[largeNeg] -= (-sum) / fabs(charge(largeNeg)); } else { throw CanteraError("MolalityVPSSTP:setMolalitiesbyName", "unbalanced charges"); } } } sum = 0.0; for (size_t k = 0; k < m_kk; k++) { sum += mf[k]; } sum = 1.0/sum; for (size_t k = 0; k < m_kk; k++) { mf[k] *= sum; } setMoleFractions(mf.data()); // After we formally set the mole fractions, we calculate the molalities // again and store it in this object. calcMolalities(); }
std::string MolalityVPSSTP::report(bool show_thermo, doublereal threshold) const { fmt::MemoryWriter b; try { if (name() != "") { b.write("\n {}:\n", name()); } b.write("\n"); b.write(" temperature {:12.6g} K\n", temperature()); b.write(" pressure {:12.6g} Pa\n", pressure()); b.write(" density {:12.6g} kg/m^3\n", density()); b.write(" mean mol. weight {:12.6g} amu\n", meanMolecularWeight()); doublereal phi = electricPotential(); b.write(" potential {:12.6g} V\n", phi); vector_fp x(m_kk); vector_fp molal(m_kk); vector_fp mu(m_kk); vector_fp muss(m_kk); vector_fp acMolal(m_kk); vector_fp actMolal(m_kk); getMoleFractions(&x[0]); getMolalities(&molal[0]); getChemPotentials(&mu[0]); getStandardChemPotentials(&muss[0]); getMolalityActivityCoefficients(&acMolal[0]); getActivities(&actMolal[0]); size_t iHp = speciesIndex("H+"); if (iHp != npos) { double pH = -log(actMolal[iHp]) / log(10.0); b.write(" pH {:12.4g}\n", pH); } if (show_thermo) { b.write("\n"); b.write(" 1 kg 1 kmol\n"); b.write(" ----------- ------------\n"); b.write(" enthalpy {:12.6g} {:12.4g} J\n", enthalpy_mass(), enthalpy_mole()); b.write(" internal energy {:12.6g} {:12.4g} J\n", intEnergy_mass(), intEnergy_mole()); b.write(" entropy {:12.6g} {:12.4g} J/K\n", entropy_mass(), entropy_mole()); b.write(" Gibbs function {:12.6g} {:12.4g} J\n", gibbs_mass(), gibbs_mole()); b.write(" heat capacity c_p {:12.6g} {:12.4g} J/K\n", cp_mass(), cp_mole()); try { b.write(" heat capacity c_v {:12.6g} {:12.4g} J/K\n", cv_mass(), cv_mole()); } catch (NotImplementedError& e) { b.write(" heat capacity c_v <not implemented>\n"); } } b.write("\n"); int nMinor = 0; doublereal xMinor = 0.0; if (show_thermo) { b.write(" X " " Molalities Chem.Pot. ChemPotSS ActCoeffMolal\n"); b.write(" " " (J/kmol) (J/kmol)\n"); b.write(" ------------- " " ------------ ------------ ------------ ------------\n"); for (size_t k = 0; k < m_kk; k++) { if (x[k] > threshold) { if (x[k] > SmallNumber) { b.write("{:>18s} {:12.6g} {:12.6g} {:12.6g} {:12.6g} {:12.6g}\n", speciesName(k), x[k], molal[k], mu[k], muss[k], acMolal[k]); } else { b.write("{:>18s} {:12.6g} {:12.6g} N/A {:12.6g} {:12.6g}\n", speciesName(k), x[k], molal[k], muss[k], acMolal[k]); } } else { nMinor++; xMinor += x[k]; } } } else { b.write(" X" "Molalities\n"); b.write(" -------------" " ------------\n"); for (size_t k = 0; k < m_kk; k++) { if (x[k] > threshold) { b.write("{:>18s} {:12.6g} {:12.6g}\n", speciesName(k), x[k], molal[k]); } else { nMinor++; xMinor += x[k]; } } } if (nMinor) { b.write(" [{:+5d} minor] {:12.6g}\n", nMinor, xMinor); } } catch (CanteraError& err) { return b.str() + err.what(); } return b.str(); }
/* * setMolalitiesByName() * * This routine sets the molalities by name * HKM -> Might need to be more complicated here, setting * neutrals so that the existing mole fractions are * preserved. */ void MolalityVPSSTP::setMolalitiesByName(compositionMap& mMap) { size_t kk = nSpecies(); doublereal x; /* * Get a vector of mole fractions */ vector_fp mf(kk, 0.0); getMoleFractions(DATA_PTR(mf)); double xmolS = mf[m_indexSolvent]; double xmolSmin = std::max(xmolS, m_xmolSolventMIN); compositionMap::iterator p; for (size_t k = 0; k < kk; k++) { p = mMap.find(speciesName(k)); if (p != mMap.end()) { x = mMap[speciesName(k)]; if (x > 0.0) { mf[k] = x * m_Mnaught * xmolSmin; } } } /* * check charge neutrality */ size_t largePos = npos; double cPos = 0.0; size_t largeNeg = npos; double cNeg = 0.0; double sum = 0.0; for (size_t k = 0; k < kk; k++) { double ch = charge(k); if (mf[k] > 0.0) { if (ch > 0.0) { if (ch * mf[k] > cPos) { largePos = k; cPos = ch * mf[k]; } } if (ch < 0.0) { if (fabs(ch) * mf[k] > cNeg) { largeNeg = k; cNeg = fabs(ch) * mf[k]; } } } sum += mf[k] * ch; } if (sum != 0.0) { if (sum > 0.0) { if (cPos > sum) { mf[largePos] -= sum / charge(largePos); } else { throw CanteraError("MolalityVPSSTP:setMolalitiesbyName", "unbalanced charges"); } } else { if (cNeg > (-sum)) { mf[largeNeg] -= (-sum) / fabs(charge(largeNeg)); } else { throw CanteraError("MolalityVPSSTP:setMolalitiesbyName", "unbalanced charges"); } } } sum = 0.0; for (size_t k = 0; k < kk; k++) { sum += mf[k]; } sum = 1.0/sum; for (size_t k = 0; k < kk; k++) { mf[k] *= sum; } setMoleFractions(DATA_PTR(mf)); /* * After we formally set the mole fractions, we * calculate the molalities again and store it in * this object. */ calcMolalities(); }