[Python] Allow setting composition using a dict

The following syntax makes it easier to set the composition programmatically,
e.g. inside a for loop:

    phase.Y = {'H2':0.1, 'O2':0.4, 'AR':0.5}
This commit is contained in:
Ray Speth 2014-04-08 16:26:34 +00:00
parent 6449415933
commit d19f975940
3 changed files with 44 additions and 5 deletions

View file

@ -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 +

View file

@ -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)

View file

@ -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)