void OutletRes1D:: init() { _init(1); // set bounds (dummy) const doublereal lower = -1.0; const doublereal upper = 1.0; setBounds(1, &lower, 1, &upper); // set tolerances const doublereal rtol = 1e-4; const doublereal atol = 1.e-4; setTolerances(1, &rtol, 1, &atol); if (m_flow_left) { m_flow = m_flow_left; } else if (m_flow_right) { m_flow = m_flow_right; } else { throw CanteraError("OutletRes1D::init","no flow!"); } m_nsp = m_flow->nComponents() - 4; m_yres.resize(m_nsp, 0.0); if (m_xstr != "") setMoleFractions(m_xstr); else m_yres[0] = 1.0; }
void Inlet1D::init() { _init(2); setBounds(0, -1e5, 1e5); // mdot setBounds(1, 200.0, 1e5); // T // if a flow domain is present on the left, then this must be a right inlet. // Note that an inlet object can only be a terminal object - it cannot have // flows on both the left and right if (m_flow_left) { m_ilr = RightInlet; m_flow = m_flow_left; } else if (m_flow_right) { m_ilr = LeftInlet; m_flow = m_flow_right; } else { throw CanteraError("Inlet1D::init","no flow!"); } // components = u, V, T, lambda, + mass fractions m_nsp = m_flow->nComponents() - 4; m_yin.resize(m_nsp, 0.0); if (m_xstr != "") { setMoleFractions(m_xstr); } else { m_yin[0] = 1.0; } }
void OutletRes1D:: init() { _init(1); // set bounds (dummy) setBounds(0, -1.0, 1.0); // set tolerances setSteadyTolerances(1e-4, 1e-4); setTransientTolerances(1e-4, 1e-4); if (m_flow_left) { m_flow = m_flow_left; } else if (m_flow_right) { m_flow = m_flow_right; } else { throw CanteraError("OutletRes1D::init","no flow!"); } m_nsp = m_flow->nComponents() - 4; m_yres.resize(m_nsp, 0.0); if (m_xstr != "") { setMoleFractions(m_xstr); } else { m_yres[0] = 1.0; } }
/* * setMolalities(): * We are supplied with the molalities of all of the * solute species. We then calculate the mole fractions of all * species and update the ThermoPhase object. * * m_i = (n_i) / (W_o/1000 * n_o_p) * * where M_o is the molecular weight of the solvent * n_o is the mole fraction of the solvent * n_i is the mole fraction of the solute. * n_o_p = max (n_o_min, n_o) * n_o_min = minimum mole fraction of solvent allowed * in the denominator. */ void MolalityVPSSTP::setMolalities(const doublereal* const molal) { double Lsum = 1.0 / m_Mnaught; for (size_t k = 1; k < m_kk; k++) { m_molalities[k] = molal[k]; Lsum += molal[k]; } double tmp = 1.0 / Lsum; m_molalities[m_indexSolvent] = tmp / m_Mnaught; double sum = m_molalities[m_indexSolvent]; for (size_t k = 1; k < m_kk; k++) { m_molalities[k] = tmp * molal[k]; sum += m_molalities[k]; } if (sum != 1.0) { tmp = 1.0 / sum; for (size_t k = 0; k < m_kk; k++) { m_molalities[k] *= tmp; } } setMoleFractions(DATA_PTR(m_molalities)); /* * Essentially we don't trust the input: We calculate * the molalities from the mole fractions that we * just obtained. */ calcMolalities(); }
void Phase::setMoleFractionsByName(const compositionMap& xMap) { size_t kk = nSpecies(); vector_fp mf(kk, 0.0); for (size_t k = 0; k < kk; k++) { mf[k] = std::max(getValue(xMap, speciesName(k), 0.0), 0.0); } setMoleFractions(&mf[0]); }
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 compositionMap& xMap) { vector_fp mf(m_kk, 0.0); for (const auto& sp : xMap) { try { mf[getValue(m_speciesIndices, sp.first)] = sp.second; } catch (std::out_of_range&) { throw CanteraError("Phase::setMoleFractionsByName", "Unknown species '{}'", sp.first); } } setMoleFractions(&mf[0]); }
void LatticeSolidPhase::setLatticeMoleFractionsByName(int nn, const std::string& x) { m_lattice[nn]->setMoleFractionsByName(x); size_t loc = 0; for (size_t n = 0; n < m_lattice.size(); n++) { size_t nsp = m_lattice[n]->nSpecies(); double ndens = m_lattice[n]->molarDensity(); for (size_t k = 0; k < nsp; k++) { m_x[loc] = ndens * m_lattice[n]->moleFraction(k); loc++; } } setMoleFractions(m_x.data()); }
void LatticeSolidPhase::setLatticeMoleFractions(int nn, string x) { m_lattice[nn]->setMoleFractionsByName(x); int n, k, loc=0, nsp; doublereal ndens; for (n = 0; n < m_nlattice; n++) { nsp = m_lattice[n]->nSpecies(); ndens = m_lattice[n]->molarDensity(); for (k = 0; k < nsp; k++) { m_x[loc] = ndens * m_lattice[n]->moleFraction(k); loc++; } } setMoleFractions(DATA_PTR(m_x)); }
void LatticeSolidPhase::initThermo() { m_kk = nSpecies(); m_mm = nElements(); m_x.resize(m_kk); int n, nsp, k, loc = 0; doublereal ndens; m_molar_density = 0.0; for (n = 0; n < m_nlattice; n++) { nsp = m_lattice[n]->nSpecies(); ndens = m_lattice[n]->molarDensity(); for (k = 0; k < nsp; k++) { m_x[loc] = ndens * m_lattice[n]->moleFraction(k); loc++; } m_molar_density += ndens; } setMoleFractions(DATA_PTR(m_x)); // const vector<string>& spnames = speciesNames(); // int n, k, kl, namesize; // int nl = m_sitedens.size(); // string s; // m_lattice.resize(m_kk,-1); // vector_fp conc(m_kk, 0.0); // compositionMap xx; // for (n = 0; n < nl; n++) { // for (k = 0; k < m_kk; k++) { // xx[speciesName(k)] = -1.0; // } // parseCompString(m_sp[n], xx); // for (k = 0; k < m_kk; k++) { // if (xx[speciesName(k)] != -1.0) { // conc[k] = m_sitedens[n]*xx[speciesName(k)]; // m_lattice[k] = n; // } // } // } // for (k = 0; k < m_kk; k++) { // if (m_lattice[k] == -1) { // throw CanteraError("LatticeSolidPhase::" // "setParametersFromXML","Species "+speciesName(k) // +" not a member of any lattice."); // } // } // setMoleFractions(DATA_PTR(conc)); }
void LatticeSolidPhase::initThermo() { initLengths(); size_t nsp, loc = 0; for (size_t n = 0; n < m_nlattice; n++) { nsp = m_lattice[n]->nSpecies(); lkstart_[n] = loc; for (size_t k = 0; k < nsp; k++) { m_x[loc] =m_lattice[n]->moleFraction(k) / (double) m_nlattice; loc++; } lkstart_[n+1] = loc; } setMoleFractions(DATA_PTR(m_x)); ThermoPhase::initThermo(); }
void LatticeSolidPhase::initThermo() { size_t kk = 0; size_t kstart = 0; lkstart_.resize(m_lattice.size() + 1); size_t loc = 0; for (size_t n = 0; n < m_lattice.size(); n++) { LatticePhase* lp = m_lattice[n]; vector_fp constArr(lp->nElements()); const vector_fp& aws = lp->atomicWeights(); for (size_t es = 0; es < lp->nElements(); es++) { addElement(lp->elementName(es), aws[es], lp->atomicNumber(es), lp->entropyElement298(es), lp->elementType(es)); } kstart = kk; for (size_t k = 0; k < lp->nSpecies(); k++) { addSpecies(lp->species(k)); kk++; } // Add in the lattice stoichiometry constraint if (n > 0) { string econ = fmt::format("LC_{}_{}", n, id()); size_t m = addElement(econ, 0.0, 0, 0.0, CT_ELEM_TYPE_LATTICERATIO); size_t mm = nElements(); size_t nsp0 = m_lattice[0]->nSpecies(); for (size_t k = 0; k < nsp0; k++) { m_speciesComp[k * mm + m] = -theta_[0]; } for (size_t k = 0; k < lp->nSpecies(); k++) { size_t ks = kstart + k; m_speciesComp[ks * mm + m] = theta_[n]; } } size_t nsp = m_lattice[n]->nSpecies(); lkstart_[n] = loc; for (size_t k = 0; k < nsp; k++) { m_x[loc] =m_lattice[n]->moleFraction(k) / (double) m_lattice.size(); loc++; } lkstart_[n+1] = loc; } setMoleFractions(m_x.data()); ThermoPhase::initThermo(); }
/* * @internal Initialize. This method is provided to allow * subclasses to perform any initialization required after all * species have been added. For example, it might be used to * resize internal work arrays that must have an entry for * each species. The base class implementation does nothing, * and subclasses that do not require initialization do not * need to overload this method. When importing a CTML phase * description, this method is called just prior to returning * from function importPhase. * * Inheriting objects should call this function * * @see importCTML.cpp */ void SingleSpeciesTP::initThermo() { /* * Check to make sure that there is one and only one species * in this phase. */ if (m_kk != 1) { err("singleSpeciesTP ERROR m_kk != 1"); } /* * Make sure the species mole fraction is equal to 1.0; */ double x = 1.0; setMoleFractions(&x); /* * Call the base class initThermo object. */ ThermoPhase::initThermo(); }
void Inlet1D:: init() { _init(2); // set bounds (mdot, T) const doublereal lower[2] = {-1.0e5, 200.0}; const doublereal upper[2] = {1.0e5, 1.e5}; setBounds(2, lower, 2, upper); // set tolerances vector_fp rtol(2, 1e-4); vector_fp atol(2, 1.e-5); setTolerances(2, DATA_PTR(rtol), 2, DATA_PTR(atol)); // if a flow domain is present on the left, then this must be // a right inlet. Note that an inlet object can only be a // terminal object - it cannot have flows on both the left and // right if (m_flow_left) { m_ilr = RightInlet; m_flow = m_flow_left; } else if (m_flow_right) { m_ilr = LeftInlet; m_flow = m_flow_right; } else { throw CanteraError("Inlet1D::init","no flow!"); } // components = u, V, T, lambda, + mass fractions m_nsp = m_flow->nComponents() - 4; m_yin.resize(m_nsp, 0.0); if (m_xstr != "") setMoleFractions(m_xstr); else m_yin[0] = 1.0; }
void Phase::setState_RX(doublereal rho, doublereal* x) { setMoleFractions(x); setDensity(rho); }
void Phase::setState_TX(doublereal t, doublereal* x) { setTemperature(t); setMoleFractions(x); }
void Phase::setState_TNX(doublereal t, doublereal n, const doublereal* x) { setMoleFractions(x); setTemperature(t); setMolarDensity(n); }
void Phase::setState_TRX(doublereal t, doublereal dens, const doublereal* x) { setMoleFractions(x); setTemperature(t); setDensity(dens); }
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(); }
/* * 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(); }
void ThermoPhase::setState_PX(doublereal p, doublereal* x) { setMoleFractions(x); setPressure(p); }
void ThermoPhase::setState_RPX(doublereal rho, doublereal p, const doublereal* x) { setMoleFractions(x); setState_RP(rho, p); }
void ThermoPhase::setState_TPX(doublereal t, doublereal p, const doublereal* x) { setMoleFractions(x); setState_TP(t,p); }
void vcs_VolPhase::_updateLnActCoeffJac() { double phaseTotalMoles = v_totalMoles; if (phaseTotalMoles < 1.0E-14) { phaseTotalMoles = 1.0; } /* * Evaluate the current base activity coefficients if necessary */ if (!m_UpToDate_AC) { _updateActCoeff(); } if (!TP_ptr) { return; } TP_ptr->getdlnActCoeffdlnN(m_numSpecies, &np_dLnActCoeffdMolNumber(0,0)); for (size_t j = 0; j < m_numSpecies; j++) { double moles_j_base = phaseTotalMoles * Xmol_[j]; double* const np_lnActCoeffCol = np_dLnActCoeffdMolNumber.ptrColumn(j); if (moles_j_base < 1.0E-200) { moles_j_base = 1.0E-7 * moles_j_base + 1.0E-13 * phaseTotalMoles + 1.0E-150; } for (size_t k = 0; k < m_numSpecies; k++) { np_lnActCoeffCol[k] = np_lnActCoeffCol[k] * phaseTotalMoles / moles_j_base; } } double deltaMoles_j = 0.0; // Make copies of ActCoeff and Xmol_ for use in taking differences std::vector<double> ActCoeff_Base(ActCoeff); std::vector<double> Xmol_Base(Xmol_); double TMoles_base = phaseTotalMoles; /* * Loop over the columns species to be deltad */ for (size_t j = 0; j < m_numSpecies; j++) { /* * Calculate a value for the delta moles of species j * -> Note Xmol_[] and Tmoles are always positive or zero * quantities. */ double moles_j_base = phaseTotalMoles * Xmol_Base[j]; deltaMoles_j = 1.0E-7 * moles_j_base + 1.0E-13 * phaseTotalMoles + 1.0E-150; /* * Now, update the total moles in the phase and all of the * mole fractions based on this. */ phaseTotalMoles = TMoles_base + deltaMoles_j; for (size_t k = 0; k < m_numSpecies; k++) { Xmol_[k] = Xmol_Base[k] * TMoles_base / phaseTotalMoles; } Xmol_[j] = (moles_j_base + deltaMoles_j) / phaseTotalMoles; /* * Go get new values for the activity coefficients. * -> Note this calls setState_PX(); */ _updateMoleFractionDependencies(); _updateActCoeff(); /* * Revert to the base case Xmol_, v_totalMoles */ v_totalMoles = TMoles_base; Xmol_ = Xmol_Base; } /* * Go get base values for the activity coefficients. * -> Note this calls setState_TPX() again; * -> Just wanted to make sure that cantera is in sync * with VolPhase after this call. */ setMoleFractions(VCS_DATA_PTR(Xmol_Base)); _updateMoleFractionDependencies(); _updateActCoeff(); }
void WaterSSTP::initThermoXML(XML_Node& phaseNode, const std::string& id) { /* * Do initializations that don't depend on knowing the XML file */ initThermo(); /* * Calculate the molecular weight. Note while there may * be a very good calculated weight in the steam table * class, using this weight may lead to codes exhibiting * mass loss issues. We need to grab the elemental * atomic weights used in the Element class and calculate * a consistent H2O molecular weight based on that. */ size_t nH = elementIndex("H"); if (nH == npos) { throw CanteraError("WaterSSTP::initThermo", "H not an element"); } double mw_H = atomicWeight(nH); size_t nO = elementIndex("O"); if (nO == npos) { throw CanteraError("WaterSSTP::initThermo", "O not an element"); } double mw_O = atomicWeight(nO); m_mw = 2.0 * mw_H + mw_O; setMolecularWeight(0,m_mw); double one = 1.0; setMoleFractions(&one); /* * Set the baseline */ doublereal T = 298.15; Phase::setDensity(7.0E-8); Phase::setTemperature(T); doublereal presLow = 1.0E-2; doublereal oneBar = 1.0E5; doublereal dd = m_sub.density(T, presLow, WATER_GAS, 7.0E-8); setDensity(dd); setTemperature(T); SW_Offset = 0.0; doublereal s = entropy_mole(); s -= GasConstant * log(oneBar/presLow); if (s != 188.835E3) { SW_Offset = 188.835E3 - s; } s = entropy_mole(); s -= GasConstant * log(oneBar/presLow); doublereal h = enthalpy_mole(); if (h != -241.826E6) { EW_Offset = -241.826E6 - h; } h = enthalpy_mole(); /* * Set the initial state of the system to 298.15 K and * 1 bar. */ setTemperature(298.15); double rho0 = m_sub.density(298.15, OneAtm, WATER_LIQUID); setDensity(rho0); m_waterProps.reset(new WaterProps(&m_sub)); /* * We have to do something with the thermo function here. */ delete m_spthermo; m_spthermo = 0; /* * Set the flag to say we are ready to calculate stuff */ m_ready = true; }