/* * getMolalities(): * We calculate the vector of molalities of the species * in the phase * \f[ * m_i = (n_i) / (1000 * M_o * n_{o,p}) * \f] * where * - \f$ M_o \f$ is the molecular weight of the solvent * - \f$ n_o \f$ is the mole fraction of the solvent * - \f$ n_i \f$ is the mole fraction of the solute. * - \f$ n_{o,p} = max (n_{o, min}, n_o) \f$ * - \f$ n_{o,min} \f$ = minimum mole fraction of solvent allowed * in the denominator. */ void MolalityVPSSTP::getMolalities(doublereal* const molal) const { calcMolalities(); for (size_t k = 0; k < m_kk; k++) { molal[k] = m_molalities[k]; } }
/* * 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 IdealMolalSoln::getPartialMolarEntropies(doublereal* sbar) const { getEntropy_R(sbar); calcMolalities(); if (IMS_typeCutoff_ == 0) { for (size_t k = 1; k < m_kk; k++) { doublereal mm = std::max(SmallNumber, m_molalities[k]); sbar[k] -= GasConstant * log(mm); } double xmolSolvent = moleFraction(0); sbar[0] -= (GasConstant * (xmolSolvent - 1.0) / xmolSolvent); } else { // Update the activity coefficients, This also update the internally // stored molalities. s_updateIMS_lnMolalityActCoeff(); // First we will add in the obvious dependence on the T term out front // of the log activity term doublereal mm; for (size_t k = 1; k < m_kk; k++) { mm = std::max(SmallNumber, m_molalities[k]); sbar[k] -= GasConstant * (log(mm) + IMS_lnActCoeffMolal_[k]); } double xmolSolvent = moleFraction(0); mm = std::max(SmallNumber, xmolSolvent); sbar[0] -= GasConstant *(log(mm) + IMS_lnActCoeffMolal_[0]); } }
void IdealMolalSoln::getActivities(doublereal* ac) const { _updateStandardStateThermo(); // Update the molality array, m_molalities(). This requires an update due to // mole fractions if (IMS_typeCutoff_ == 0) { calcMolalities(); for (size_t k = 0; k < m_kk; k++) { ac[k] = m_molalities[k]; } double xmolSolvent = moleFraction(0); // Limit the activity coefficient to be finite as the solvent mole // fraction goes to zero. xmolSolvent = std::max(m_xmolSolventMIN, xmolSolvent); ac[0] = exp((xmolSolvent - 1.0)/xmolSolvent); } else { s_updateIMS_lnMolalityActCoeff(); // Now calculate the array of activities. for (size_t k = 1; k < m_kk; k++) { ac[k] = m_molalities[k] * exp(IMS_lnActCoeffMolal_[k]); } double xmolSolvent = moleFraction(0); ac[0] = exp(IMS_lnActCoeffMolal_[0]) * xmolSolvent; } }
void IdealMolalSoln::getChemPotentials(doublereal* mu) const { // First get the standard chemical potentials. This requires updates of // standard state as a function of T and P These are defined at unit // molality. getStandardChemPotentials(mu); // Update the molality array, m_molalities(). This requires an update due to // mole fractions calcMolalities(); // get the solvent mole fraction double xmolSolvent = moleFraction(0); if (IMS_typeCutoff_ == 0 || xmolSolvent > 3.* IMS_X_o_cutoff_/2.0) { for (size_t k = 1; k < m_kk; k++) { double xx = std::max(m_molalities[k], SmallNumber); mu[k] += RT() * log(xx); } // Do the solvent // -> see my notes double xx = std::max(xmolSolvent, SmallNumber); mu[0] += (RT() * (xmolSolvent - 1.0) / xx); } else { // Update the activity coefficients. This also updates the internal // molality array. s_updateIMS_lnMolalityActCoeff(); for (size_t k = 1; k < m_kk; k++) { double xx = std::max(m_molalities[k], SmallNumber); mu[k] += RT() * (log(xx) + IMS_lnActCoeffMolal_[k]); } double xx = std::max(xmolSolvent, SmallNumber); mu[0] += RT() * (log(xx) + IMS_lnActCoeffMolal_[0]); } }
/* * 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 IdealMolalSoln::s_updateIMS_lnMolalityActCoeff() const { // Calculate the molalities. Currently, the molalities may not be current // with respect to the contents of the State objects' data. calcMolalities(); double xmolSolvent = moleFraction(0); double xx = std::max(m_xmolSolventMIN, xmolSolvent); if (IMS_typeCutoff_ == 0) { for (size_t k = 1; k < m_kk; k++) { IMS_lnActCoeffMolal_[k]= 0.0; } IMS_lnActCoeffMolal_[0] = - log(xx) + (xx - 1.0)/xx; return; } else if (IMS_typeCutoff_ == 1) { if (xmolSolvent > 3.0 * IMS_X_o_cutoff_/2.0) { for (size_t k = 1; k < m_kk; k++) { IMS_lnActCoeffMolal_[k]= 0.0; } IMS_lnActCoeffMolal_[0] = - log(xx) + (xx - 1.0)/xx; return; } else if (xmolSolvent < IMS_X_o_cutoff_/2.0) { double tmp = log(xx * IMS_gamma_k_min_); for (size_t k = 1; k < m_kk; k++) { IMS_lnActCoeffMolal_[k]= tmp; } IMS_lnActCoeffMolal_[0] = log(IMS_gamma_o_min_); return; } else { // If we are in the middle region, calculate the connecting polynomials double xminus = xmolSolvent - IMS_X_o_cutoff_/2.0; double xminus2 = xminus * xminus; double xminus3 = xminus2 * xminus; double x_o_cut2 = IMS_X_o_cutoff_ * IMS_X_o_cutoff_; double x_o_cut3 = x_o_cut2 * IMS_X_o_cutoff_; double h2 = 3.5 * xminus2 / IMS_X_o_cutoff_ - 2.0 * xminus3 / x_o_cut2; double h2_prime = 7.0 * xminus / IMS_X_o_cutoff_ - 6.0 * xminus2 / x_o_cut2; double h1 = (1.0 - 3.0 * xminus2 / x_o_cut2 + 2.0 * xminus3/ x_o_cut3); double h1_prime = (- 6.0 * xminus / x_o_cut2 + 6.0 * xminus2/ x_o_cut3); double h1_g = h1 / IMS_gamma_o_min_; double h1_g_prime = h1_prime / IMS_gamma_o_min_; double alpha = 1.0 / (exp(1.0) * IMS_gamma_k_min_); double h1_f = h1 * alpha; double h1_f_prime = h1_prime * alpha; double f = h2 + h1_f; double f_prime = h2_prime + h1_f_prime; double g = h2 + h1_g; double g_prime = h2_prime + h1_g_prime; double tmp = (xmolSolvent/ g * g_prime + (1.0-xmolSolvent) / f * f_prime); double lngammak = -1.0 - log(f) + tmp * xmolSolvent; double lngammao =-log(g) - tmp * (1.0-xmolSolvent); tmp = log(xmolSolvent) + lngammak; for (size_t k = 1; k < m_kk; k++) { IMS_lnActCoeffMolal_[k]= tmp; } IMS_lnActCoeffMolal_[0] = lngammao; } } else if (IMS_typeCutoff_ == 2) { // Exponentials - trial 2 if (xmolSolvent > IMS_X_o_cutoff_) { for (size_t k = 1; k < m_kk; k++) { IMS_lnActCoeffMolal_[k]= 0.0; } IMS_lnActCoeffMolal_[0] = - log(xx) + (xx - 1.0)/xx; return; } else { double xoverc = xmolSolvent/IMS_cCut_; double eterm = std::exp(-xoverc); double fptmp = IMS_bfCut_ - IMS_afCut_ / IMS_cCut_ - IMS_bfCut_*xoverc + 2.0*IMS_dfCut_*xmolSolvent - IMS_dfCut_*xmolSolvent*xoverc; double f_prime = 1.0 + eterm*fptmp; double f = xmolSolvent + IMS_efCut_ + eterm * (IMS_afCut_ + xmolSolvent * (IMS_bfCut_ + IMS_dfCut_*xmolSolvent)); double gptmp = IMS_bgCut_ - IMS_agCut_ / IMS_cCut_ - IMS_bgCut_*xoverc + 2.0*IMS_dgCut_*xmolSolvent - IMS_dgCut_*xmolSolvent*xoverc; double g_prime = 1.0 + eterm*gptmp; double g = xmolSolvent + IMS_egCut_ + eterm * (IMS_agCut_ + xmolSolvent * (IMS_bgCut_ + IMS_dgCut_*xmolSolvent)); double tmp = (xmolSolvent / g * g_prime + (1.0 - xmolSolvent) / f * f_prime); double lngammak = -1.0 - log(f) + tmp * xmolSolvent; double lngammao =-log(g) - tmp * (1.0-xmolSolvent); tmp = log(xx) + lngammak; for (size_t k = 1; k < m_kk; k++) { IMS_lnActCoeffMolal_[k]= tmp; } IMS_lnActCoeffMolal_[0] = lngammao; } } }
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(); }