diff --git a/include/cantera/thermo/Phase.h b/include/cantera/thermo/Phase.h index c9ed00cee..34dc06a70 100644 --- a/include/cantera/thermo/Phase.h +++ b/include/cantera/thermo/Phase.h @@ -541,12 +541,16 @@ public: //! Elemental mole fraction of element m /*! * The elemental mole fraction \f$Z_{\mathrm{mole},m}\f$ of element \f$m\f$ - * is defined as + * is the number of atoms of element *m* divided by the total number of + * atoms. It is defined as: + * * \f[ - * Z_{\mathrm{mole},m} = \sum_k \frac{a_{m,k}}{\sum_j a_{j,k}} X_k + * Z_{\mathrm{mole},m} = \frac{\sum_k a_{m,k} X_k} + * {\sum_k \sum_j a_{j,k} X_k} * \f] * with \f$a_{m,k}\f$ being the number of atoms of element \f$m\f$ in - * species \f$k\f$and \f$X_k\f$ the mole fraction of species \f$k\f$. + * species \f$k\f$, \f$\sum_j\f$ being a sum over all elements, and + * \f$X_k\f$ being the mole fraction of species \f$k\f$. * * @param[in] m Index of the element within the phase. If m is outside the * valid range, an exception will be thrown. diff --git a/interfaces/cython/cantera/test/test_thermo.py b/interfaces/cython/cantera/test/test_thermo.py index 37702a178..e2a79c978 100644 --- a/interfaces/cython/cantera/test/test_thermo.py +++ b/interfaces/cython/cantera/test/test_thermo.py @@ -65,8 +65,8 @@ class TestThermoPhase(utilities.CanteraTest): mO = self.phase.element_index('O') self.assertEqual(Zo, self.phase.elemental_mole_fraction(mO)) - self.assertNear(Zo, 0.5/3 + 0.5) - self.assertNear(Zh, 0.5*2/3) + self.assertNear(Zo, (0.5 + 1) / (0.5*3 + 0.5*2)) + self.assertNear(Zh, (2*0.5) / (0.5*3 + 0.5*2)) self.assertEqual(Zar, 0.0) with self.assertRaises(ValueError): @@ -74,6 +74,22 @@ class TestThermoPhase(utilities.CanteraTest): with self.assertRaises(ValueError): self.phase.elemental_mole_fraction(5) + def test_elemental_mass_mole_fraction(self): + # expected relationship between elmental mass and mole fractions + comps = ['H2O:0.5, O2:0.5', 'H2:0.1, O2:0.4, H2O2:0.3, AR:0.2', + 'O2:0.1, H2:0.9'] + for comp in comps: + self.phase.X = comp + + denom = sum(self.phase.elemental_mole_fraction(i) + * self.phase.atomic_weight(i) + for i in range(self.phase.n_elements)) + + for i in range(self.phase.n_elements): + self.assertNear(self.phase.elemental_mass_fraction(i), + self.phase.elemental_mole_fraction(i) + * self.phase.atomic_weight(i) / denom) + def test_weights(self): atomic_weights = self.phase.atomic_weights molecular_weights = self.phase.molecular_weights diff --git a/interfaces/cython/cantera/thermo.pyx b/interfaces/cython/cantera/thermo.pyx index e379eb310..ed31db70f 100644 --- a/interfaces/cython/cantera/thermo.pyx +++ b/interfaces/cython/cantera/thermo.pyx @@ -542,13 +542,15 @@ cdef class ThermoPhase(_SolutionBase): def elemental_mole_fraction(self, m): r""" Get the elemental mole fraction :math:`Z_{\mathrm{mole},m}` of element - :math:`m` as defined by: + :math:`m` (the number of atoms of element m divided by the total number + of atoms) as defined by: - .. math:: Z_{\mathrm{mole},m} = \sum_k \frac{a_{m,k}}{\sum_j a_{j,k}} X_k + .. math:: Z_{\mathrm{mole},m} = \frac{\sum_k a_{m,k} X_k} + {\sum_k \sum_j a_{j,k} X_k} with :math:`a_{m,k}` being the number of atoms of element :math:`m` in - species :math:`k` and :math:`X_k` the mole fraction of species - :math:`k`. + species :math:`k`, :math:`\sum_j` being a sum over all elements, and + :math:`X_k` being the mole fraction of species :math:`k`. :param m: Base element, may be specified by name or by index. diff --git a/src/thermo/Phase.cpp b/src/thermo/Phase.cpp index 9ff1e6711..c7f220665 100644 --- a/src/thermo/Phase.cpp +++ b/src/thermo/Phase.cpp @@ -643,15 +643,19 @@ doublereal Phase::elementalMassFraction(const size_t m) const doublereal Phase::elementalMoleFraction(const size_t m) const { checkElementIndex(m); - doublereal Z_n = 0.0; - for (size_t k = 0; k != m_kk; ++k) { - double nTotalAtoms = 0; - for (size_t l = 0; l != m_mm; ++l) { - nTotalAtoms += nAtoms(k, l); + double denom = 0; + for (size_t k = 0; k < m_kk; k++) { + double atoms = 0; + for (size_t j = 0; j < nElements(); j++) { + atoms += nAtoms(k, j); } - Z_n += nAtoms(k, m) / nTotalAtoms * moleFraction(k); + denom += atoms * moleFraction(k); } - return Z_n; + doublereal numerator = 0.0; + for (size_t k = 0; k != m_kk; ++k) { + numerator += nAtoms(k, m) * moleFraction(k); + } + return numerator / denom; } doublereal Phase::molarDensity() const