void GasTransport::getMixDiffCoeffsMole(doublereal* const d) { update_T(); update_C(); // update the binary diffusion coefficients if necessary if (!m_bindiff_ok) { updateDiff_T(); } doublereal p = m_thermo->pressure(); if (m_nsp == 1) { d[0] = m_bdiff(0,0) / p; } else { for (size_t k = 0; k < m_nsp; k++) { double sum2 = 0.0; for (size_t j = 0; j < m_nsp; j++) { if (j != k) { sum2 += m_molefracs[j] / m_bdiff(j,k); } } if (sum2 <= 0.0) { d[k] = m_bdiff(k,k) / p; } else { d[k] = (1 - m_molefracs[k]) / (p * sum2); } } } }
void GasTransport::getMixDiffCoeffsMass(doublereal* const d) { update_T(); update_C(); // update the binary diffusion coefficients if necessary if (!m_bindiff_ok) { updateDiff_T(); } doublereal mmw = m_thermo->meanMolecularWeight(); doublereal p = m_thermo->pressure(); if (m_nsp == 1) { d[0] = m_bdiff(0,0) / p; } else { for (size_t k=0; k<m_nsp; k++) { double sum1 = 0.0; double sum2 = 0.0; for (size_t i=0; i<m_nsp; i++) { if (i==k) { continue; } sum1 += m_molefracs[i] / m_bdiff(k,i); sum2 += m_molefracs[i] * m_mw[i] / m_bdiff(k,i); } sum1 *= p; sum2 *= p * m_molefracs[k] / (mmw - m_mw[k]*m_molefracs[k]); d[k] = 1.0 / (sum1 + sum2); } } }
void AqueousTransport::getMixDiffCoeffs(doublereal* const d) { update_T(); update_C(); // update the binary diffusion coefficients if necessary if (!m_bindiff_ok) { updateDiff_T(); } size_t k, j; doublereal mmw = m_thermo->meanMolecularWeight(); doublereal sumxw = 0.0, sum2; doublereal p = m_press; if (m_nsp == 1) { d[0] = m_bdiff(0,0) / p; } else { for (k = 0; k < m_nsp; k++) { sumxw += m_molefracs[k] * m_mw[k]; } for (k = 0; k < m_nsp; k++) { sum2 = 0.0; for (j = 0; j < m_nsp; j++) { if (j != k) { sum2 += m_molefracs[j] / m_bdiff(j,k); } } if (sum2 <= 0.0) { d[k] = m_bdiff(k,k) / p; } else { d[k] = (sumxw - m_molefracs[k] * m_mw[k])/(p * mmw * sum2); } } } }
/* * Returns the simple diffusion coefficients input into the model. Nothing fancy here. */ void SimpleTransport::getMixDiffCoeffs(doublereal* const d) { update_T(); update_C(); // update the binary diffusion coefficients if necessary if (!m_diff_temp_ok) { updateDiff_T(); } for (size_t k = 0; k < m_nsp; k++) { d[k] = m_diffSpecies[k]; } }
/* * * d[ld*j + i] = rp * m_bdiff(i,j); * * units of m**2 / s * * @param ld offset of rows in the storage * @param d output vector of diffusion coefficients */ void MixTransport::getBinaryDiffCoeffs(const int ld, doublereal* const d) { update_T(); // if necessary, evaluate the binary diffusion coefficents from the polynomial fits if (!m_bindiff_ok) updateDiff_T(); if (ld < m_nsp) { throw CanteraError(" MixTransport::getBinaryDiffCoeffs()", "ld is too small"); } doublereal rp = 1.0/pressure_ig(); for (int i = 0; i < m_nsp; i++) for (int j = 0; j < m_nsp; j++) { d[ld*j + i] = rp * m_bdiff(i,j); } }
void AqueousTransport::getBinaryDiffCoeffs(const size_t ld, doublereal* const d) { update_T(); // if necessary, evaluate the binary diffusion coefficients // from the polynomial fits if (!m_bindiff_ok) { updateDiff_T(); } doublereal pres = m_thermo->pressure(); doublereal rp = 1.0/pres; for (size_t i = 0; i < m_nsp; i++) for (size_t j = 0; j < m_nsp; j++) { d[ld*j + i] = rp * m_bdiff(i,j); } }
//================================================================================================ void SimpleTransport::getBinaryDiffCoeffs(size_t ld, doublereal* d) { double bdiff; update_T(); // if necessary, evaluate the species diffusion coefficients // from the polynomial fits if (!m_diff_temp_ok) { updateDiff_T(); } for (size_t i = 0; i < m_nsp; i++) { for (size_t j = 0; j < m_nsp; j++) { bdiff = 0.5 * (m_diffSpecies[i] + m_diffSpecies[j]); d[i*m_nsp+j] = bdiff; } } }
void ApproxMixTransport::getMixDiffCoeffs(double* const d) { update_T(); update_C(); // update the binary diffusion coefficients if necessary if (!m_bindiff_ok) { updateDiff_T(); } double mmw = m_thermo->meanMolecularWeight(); double sumxw = 0.0, sum2; double p = m_thermo->pressure(); if (m_nsp == 1) { d[0] = m_bdiff(0,0) / p; } else { for (size_t k = 0; k < m_nsp; k++) { sumxw += m_molefracs[k] * m_mw[k]; } for (size_t k = 0; k < m_nsp; k++) { sum2 = 0.0; if (m_molefracs[k] >= _threshold) { for (size_t j = 0; j < m_nsp; j++) { if (j != k) { sum2 += m_molefracs[j] / m_bdiff(j,k); } } } else { for (size_t j : _kMajor) { if (j != k) { sum2 += m_molefracs[j] / m_bdiff(j,k); } } } if (sum2 <= 0.0) { d[k] = m_bdiff(k,k) / p; } else { d[k] = (sumxw - m_molefracs[k] * m_mw[k])/(p * mmw * sum2); } } } }
void LiquidTransport::getBinaryDiffCoeffs(size_t ld, doublereal* d) { if (ld != m_nsp) { throw CanteraError("LiquidTransport::getBinaryDiffCoeffs", "First argument does not correspond to number of species in model.\nDiff Coeff matrix may be misdimensioned"); } update_T(); // if necessary, evaluate the binary diffusion coefficients // from the polynomial fits if (!m_diff_temp_ok) { updateDiff_T(); } for (size_t i = 0; i < m_nsp; i++) { for (size_t j = 0; j < m_nsp; j++) { d[ld*j + i] = 1.0 / m_bdiff(i,j); } } }
void LiquidTransport::stefan_maxwell_solve() { doublereal tmp; m_B.resize(m_nsp, m_nDim, 0.0); m_A.resize(m_nsp, m_nsp, 0.0); //! grab a local copy of the molecular weights const vector_fp& M = m_thermo->molecularWeights(); //! grad a local copy of the ion molar volume (inverse total ion concentration) const doublereal vol = m_thermo->molarVolume(); /* * Update the temperature, concentrations and diffusion coefficients in the mixture. */ update_T(); update_C(); if (!m_diff_temp_ok) { updateDiff_T(); } double T = m_thermo->temperature(); update_Grad_lnAC(); m_thermo->getActivityCoefficients(DATA_PTR(m_actCoeff)); /* * Calculate the electrochemical potential gradient. This is the * driving force for relative diffusional transport. * * Here we calculate * * X_i * (grad (mu_i) + S_i grad T - M_i / dens * grad P * * This is Eqn. 13-1 p. 318 Newman. The original equation is from * Hershfeld, Curtis, and Bird. * * S_i is the partial molar entropy of species i. This term will cancel * out a lot of the grad T terms in grad (mu_i), therefore simplifying * the expression. * * Ok I think there may be many ways to do this. One way is to do it via basis * functions, at the nodes, as a function of the variables in the problem. * * For calculation of molality based thermo systems, we current get * the molar based values. This may change. * * Note, we have broken the symmetry of the matrix here, due to * considerations involving species concentrations going to zero. */ for (size_t a = 0; a < m_nDim; a++) { for (size_t i = 0; i < m_nsp; i++) { m_Grad_mu[a*m_nsp + i] = m_chargeSpecies[i] * Faraday * m_Grad_V[a] + GasConstant * T * m_Grad_lnAC[a*m_nsp+i]; } } if (m_thermo->activityConvention() == cAC_CONVENTION_MOLALITY) { int iSolvent = 0; double mwSolvent = m_thermo->molecularWeight(iSolvent); double mnaught = mwSolvent/ 1000.; double lnmnaught = log(mnaught); for (size_t a = 0; a < m_nDim; a++) { for (size_t i = 1; i < m_nsp; i++) { m_Grad_mu[a*m_nsp + i] -= m_molefracs[i] * GasConstant * m_Grad_T[a] * lnmnaught; } } } /* * Just for Note, m_A(i,j) refers to the ith row and jth column. * They are still fortran ordered, so that i varies fastest. */ double condSum1; const doublereal invRT = 1.0 / (GasConstant * T); switch (m_nDim) { case 1: /* 1-D approximation */ m_B(0,0) = 0.0; //equation for the reference velocity for (size_t j = 0; j < m_nsp; j++) { if (m_velocityBasis == VB_MOLEAVG) { m_A(0,j) = m_molefracs_tran[j]; } else if (m_velocityBasis == VB_MASSAVG) { m_A(0,j) = m_massfracs_tran[j]; } else if ((m_velocityBasis >= 0) && (m_velocityBasis < static_cast<int>(m_nsp))) { // use species number m_velocityBasis as reference velocity if (m_velocityBasis == static_cast<int>(j)) { m_A(0,j) = 1.0; } else { m_A(0,j) = 0.0; } } else { throw CanteraError("LiquidTransport::stefan_maxwell_solve", "Unknown reference velocity provided."); } } for (size_t i = 1; i < m_nsp; i++) { m_B(i,0) = m_Grad_mu[i] * invRT; m_A(i,i) = 0.0; for (size_t j = 0; j < m_nsp; j++) { if (j != i) { tmp = m_molefracs_tran[j] * m_bdiff(i,j); m_A(i,i) -= tmp; m_A(i,j) = tmp; } } } //! invert and solve the system Ax = b. Answer is in m_B solve(m_A, m_B); condSum1 = 0; for (size_t i = 0; i < m_nsp; i++) { condSum1 -= Faraday*m_chargeSpecies[i]*m_B(i,0)*m_molefracs_tran[i]/vol; } break; case 2: /* 2-D approximation */ m_B(0,0) = 0.0; m_B(0,1) = 0.0; //equation for the reference velocity for (size_t j = 0; j < m_nsp; j++) { if (m_velocityBasis == VB_MOLEAVG) { m_A(0,j) = m_molefracs_tran[j]; } else if (m_velocityBasis == VB_MASSAVG) { m_A(0,j) = m_massfracs_tran[j]; } else if ((m_velocityBasis >= 0) && (m_velocityBasis < static_cast<int>(m_nsp))) { // use species number m_velocityBasis as reference velocity if (m_velocityBasis == static_cast<int>(j)) { m_A(0,j) = 1.0; } else { m_A(0,j) = 0.0; } } else { throw CanteraError("LiquidTransport::stefan_maxwell_solve", "Unknown reference velocity provided."); } } for (size_t i = 1; i < m_nsp; i++) { m_B(i,0) = m_Grad_mu[i] * invRT; m_B(i,1) = m_Grad_mu[m_nsp + i] * invRT; m_A(i,i) = 0.0; for (size_t j = 0; j < m_nsp; j++) { if (j != i) { tmp = m_molefracs_tran[j] * m_bdiff(i,j); m_A(i,i) -= tmp; m_A(i,j) = tmp; } } } //! invert and solve the system Ax = b. Answer is in m_B solve(m_A, m_B); break; case 3: /* 3-D approximation */ m_B(0,0) = 0.0; m_B(0,1) = 0.0; m_B(0,2) = 0.0; //equation for the reference velocity for (size_t j = 0; j < m_nsp; j++) { if (m_velocityBasis == VB_MOLEAVG) { m_A(0,j) = m_molefracs_tran[j]; } else if (m_velocityBasis == VB_MASSAVG) { m_A(0,j) = m_massfracs_tran[j]; } else if ((m_velocityBasis >= 0) && (m_velocityBasis < static_cast<int>(m_nsp))) { // use species number m_velocityBasis as reference velocity if (m_velocityBasis == static_cast<int>(j)) { m_A(0,j) = 1.0; } else { m_A(0,j) = 0.0; } } else { throw CanteraError("LiquidTransport::stefan_maxwell_solve", "Unknown reference velocity provided."); } } for (size_t i = 1; i < m_nsp; i++) { m_B(i,0) = m_Grad_mu[i] * invRT; m_B(i,1) = m_Grad_mu[m_nsp + i] * invRT; m_B(i,2) = m_Grad_mu[2*m_nsp + i] * invRT; m_A(i,i) = 0.0; for (size_t j = 0; j < m_nsp; j++) { if (j != i) { tmp = m_molefracs_tran[j] * m_bdiff(i,j); m_A(i,i) -= tmp; m_A(i,j) = tmp; } } } //! invert and solve the system Ax = b. Answer is in m_B solve(m_A, m_B); break; default: printf("unimplemented\n"); throw CanteraError("routine", "not done"); break; } for (size_t a = 0; a < m_nDim; a++) { for (size_t j = 0; j < m_nsp; j++) { m_Vdiff(j,a) = m_B(j,a); m_flux(j,a) = concTot_ * M[j] * m_molefracs_tran[j] * m_B(j,a); } } }