void ThermoPhase::getdlnActCoeffdlnN_numderiv(const size_t ld, doublereal* const dlnActCoeffdlnN) { double deltaMoles_j = 0.0; double pres = pressure(); // Evaluate the current base activity coefficients if necessary vector_fp ActCoeff_Base(m_kk); getActivityCoefficients(ActCoeff_Base.data()); vector_fp Xmol_Base(m_kk); getMoleFractions(Xmol_Base.data()); // Make copies of ActCoeff and Xmol_ for use in taking differences vector_fp ActCoeff(m_kk); vector_fp Xmol(m_kk); double v_totalMoles = 1.0; double TMoles_base = v_totalMoles; // Loop over the columns species to be deltad for (size_t j = 0; j < m_kk; j++) { // Calculate a value for the delta moles of species j // -> Note Xmol_[] and Tmoles are always positive or zero quantities. // -> experience has shown that you always need to make the deltas // greater than needed to change the other mole fractions in order // to capture some effects. double moles_j_base = v_totalMoles * Xmol_Base[j]; deltaMoles_j = 1.0E-7 * moles_j_base + v_totalMoles * 1.0E-13 + 1.0E-150; // Now, update the total moles in the phase and all of the mole // fractions based on this. v_totalMoles = TMoles_base + deltaMoles_j; for (size_t k = 0; k < m_kk; k++) { Xmol[k] = Xmol_Base[k] * TMoles_base / v_totalMoles; } Xmol[j] = (moles_j_base + deltaMoles_j) / v_totalMoles; // Go get new values for the activity coefficients. // -> Note this calls setState_PX(); setState_PX(pres, Xmol.data()); getActivityCoefficients(ActCoeff.data()); // Calculate the column of the matrix double* const lnActCoeffCol = dlnActCoeffdlnN + ld * j; for (size_t k = 0; k < m_kk; k++) { lnActCoeffCol[k] = (2*moles_j_base + deltaMoles_j) *(ActCoeff[k] - ActCoeff_Base[k]) / ((ActCoeff[k] + ActCoeff_Base[k]) * deltaMoles_j); } // Revert to the base case Xmol_, v_totalMoles v_totalMoles = TMoles_base; Xmol = Xmol_Base; } setState_PX(pres, Xmol_Base.data()); }
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(); }