diff --git a/interfaces/cython/cantera/_cantera.pxd b/interfaces/cython/cantera/_cantera.pxd index 08a656698..932a67eca 100644 --- a/interfaces/cython/cantera/_cantera.pxd +++ b/interfaces/cython/cantera/_cantera.pxd @@ -1,5 +1,6 @@ from libcpp.vector cimport vector from libcpp.string cimport string +from libcpp.map cimport map as stdmap from libcpp cimport bool as cbool from cpython cimport bool as pybool @@ -84,10 +85,12 @@ cdef extern from "cantera/thermo/ThermoPhase.h" namespace "Cantera": # composition void setMassFractionsByName(string) except + + void setMassFractionsByName(stdmap[string,double]&) except + double massFraction(size_t) except + double massFraction(string) except + void setMoleFractionsByName(string) except + + void setMoleFractionsByName(stdmap[string,double]&) except + void getMoleFractions(double*) except + double moleFraction(size_t) except + double moleFraction(string) except + diff --git a/interfaces/cython/cantera/test/test_thermo.py b/interfaces/cython/cantera/test/test_thermo.py index 9811c0966..31b0c038e 100644 --- a/interfaces/cython/cantera/test/test_thermo.py +++ b/interfaces/cython/cantera/test/test_thermo.py @@ -83,6 +83,27 @@ class TestThermoPhase(utilities.CanteraTest): self.phase.X = 'H2:1e-1.4' self.assertArrayNear(X0, self.phase.X) + def test_setCompositionDict(self): + self.phase.X = {'H2':1.0, 'O2':3.0} + X = self.phase.X + self.assertNear(X[0], 0.25) + self.assertNear(X[3], 0.75) + + self.phase.Y = {'H2':1.0, 'O2':3.0} + Y = self.phase.Y + self.assertNear(Y[0], 0.25) + self.assertNear(Y[3], 0.75) + + @unittest.expectedFailure + def test_setCompositionDict_bad1(self): + # Non-existent species should raise an exception + with self.assertRaises(Exception): + self.phase.X = {'H2':1.0, 'HCl':3.0} + + def test_setCompositionDict_bad2(self): + with self.assertRaises(Exception): + self.phase.Y = {'H2':1.0, 'O2':'xx'} + def test_report(self): report = self.phase.report() self.assertTrue(self.phase.name in report) diff --git a/interfaces/cython/cantera/thermo.pyx b/interfaces/cython/cantera/thermo.pyx index 8f07bc5fa..f5616c558 100644 --- a/interfaces/cython/cantera/thermo.pyx +++ b/interfaces/cython/cantera/thermo.pyx @@ -2,6 +2,16 @@ cdef enum Thermasis: mass_basis = 0 molar_basis = 1 + +cdef stdmap[string,double] comp_map(dict X) except *: + cdef stdmap[string,double] m + cdef str species + cdef float val + for species,value in X.items(): + m[stringify(species)] = value + return m + + cdef class ThermoPhase(_SolutionBase): """ A phase with an equation of state. @@ -255,10 +265,11 @@ cdef class ThermoPhase(_SolutionBase): property Y: """ - Get/Set the species mass fractions. Can be set as either an array or - as a string. Always returns an array:: + Get/Set the species mass fractions. Can be set as an array, as a dict, + or as a string. Always returns an array:: >>> phase.Y = [0.1, 0, 0, 0.4, 0, 0, 0, 0, 0.5] + >>> phase.Y = {'H2':0.1, 'O2':0.4, 'AR':0.5} >>> phase.Y = 'H2:0.1, O2:0.4, AR:0.5' >>> phase.Y array([0.1, 0, 0, 0.4, 0, 0, 0, 0, 0.5]) @@ -268,25 +279,29 @@ cdef class ThermoPhase(_SolutionBase): def __set__(self, Y): if isinstance(Y, (str, unicode)): self.thermo.setMassFractionsByName(stringify(Y)) + elif isinstance(Y, dict): + self.thermo.setMassFractionsByName(comp_map(Y)) else: self._setArray1(thermo_setMassFractions, Y) property X: """ - Get/Set the species mole fractions. Can be set as either an array or - as a string. Always returns an array:: + Get/Set the species mole fractions. Can be set as an array, as a dict, + or as a string. Always returns an array:: >>> phase.X = [0.1, 0, 0, 0.4, 0, 0, 0, 0, 0.5] + >>> phase.X = {'H2':0.1, 'O2':0.4, 'AR':0.5} >>> phase.X = 'H2:0.1, O2:0.4, AR:0.5' >>> phase.X array([0.1, 0, 0, 0.4, 0, 0, 0, 0, 0.5]) - """ def __get__(self): return self._getArray1(thermo_getMoleFractions) def __set__(self, X): if isinstance(X, (str, unicode)): self.thermo.setMoleFractionsByName(stringify(X)) + elif isinstance(X, dict): + self.thermo.setMoleFractionsByName(comp_map(X)) else: self._setArray1(thermo_setMoleFractions, X)