[Python] Add basic access to Species objects

This commit is contained in:
Ray Speth 2015-04-15 15:57:19 -04:00
parent aee6cc14ac
commit 71f912d211
4 changed files with 109 additions and 2 deletions

View file

@ -38,6 +38,21 @@ cdef extern from "cantera/cython/funcWrapper.h":
CxxFunc1(callback_wrapper, void*)
double eval(double) except +translate_exception
cdef extern from "cantera/base/smart_ptr.h":
cppclass shared_ptr "Cantera::shared_ptr" [T]:
T* get()
void reset(T*)
cdef extern from "cantera/thermo/Species.h":
cdef cppclass CxxSpecies "Cantera::Species":
CxxSpecies()
CxxSpecies(string, stdmap[string,double])
string name
stdmap[string,double] composition
double charge
double size
cdef extern from "cantera/thermo/ThermoPhase.h" namespace "Cantera":
cdef cppclass CxxThermoPhase "Cantera::ThermoPhase":
@ -75,6 +90,8 @@ cdef extern from "cantera/thermo/ThermoPhase.h" namespace "Cantera":
# species properties
size_t nSpecies()
shared_ptr[CxxSpecies] species(string) except +
shared_ptr[CxxSpecies] species(size_t) except +
size_t speciesIndex(string) except +
string speciesName(size_t) except +
double nAtoms(size_t, size_t) except +
@ -588,6 +605,12 @@ ctypedef void (*transportMethod2d)(CxxTransport*, size_t, double*) except +
ctypedef void (*kineticsMethod1d)(CxxKinetics*, double*) except +
# classes
cdef class Species:
cdef shared_ptr[CxxSpecies] _species
cdef CxxSpecies* species
cdef _assign(self, shared_ptr[CxxSpecies] other)
cdef class _SolutionBase:
cdef CxxThermoPhase* thermo
cdef CxxKinetics* kinetics

View file

@ -624,3 +624,36 @@ ideal_gas(name='spam', elements='O H',
def test_checkReactionBalance(self):
with self.assertRaises(Exception):
ct.Solution('../data/h2o2_unbalancedReaction.xml')
class TestSpecies(utilities.CanteraTest):
def test_standalone(self):
s = ct.Species('CH4', {'C':1, 'H':4})
self.assertEqual(s.name, 'CH4')
c = s.composition
self.assertEqual(len(c), 2)
self.assertEqual(c['C'], 1)
self.assertEqual(c['H'], 4)
def test_defaults(self):
s = ct.Species('H2')
self.assertEqual(s.size, 0.0)
self.assertEqual(s.charge, 0.0)
def test_index_accessor(self):
gas = ct.Solution('h2o2.xml')
for k in range(gas.n_species):
s = gas.species(k)
self.assertEqual(s.name, gas.species_name(k))
for m,n in s.composition.items():
self.assertEqual(n, gas.n_atoms(k,m))
def test_name_accessor(self):
gas = ct.Solution('h2o2.xml')
for name in gas.species_names:
s = gas.species(name)
self.assertEqual(s.name, name)

View file

@ -13,6 +13,47 @@ cdef stdmap[string,double] comp_map(dict X) except *:
m[stringify(species)] = value
return m
cdef comp_map_to_dict(stdmap[string,double] m):
return {pystr(species):value for species,value in m.items()}
cdef class Species:
def __cinit__(self, *args, init=True, **kwargs):
if init:
self._species.reset(new CxxSpecies())
self.species = self._species.get()
def __init__(self, name=None, composition=None, charge=None, size=None,
*args, init=True, **kwargs):
if not init:
return
if name is not None:
self.species.name = stringify(name)
if composition is not None:
self.species.composition = comp_map(composition)
cdef _assign(self, shared_ptr[CxxSpecies] other):
self._species = other
self.species = self._species.get()
property name:
def __get__(self):
return pystr(self.species.name)
property composition:
def __get__(self):
return comp_map_to_dict(self.species.composition)
property charge:
def __get__(self):
return self.species.charge
property size:
def __get__(self):
return self.species.size
cdef class ThermoPhase(_SolutionBase):
"""
@ -237,6 +278,16 @@ cdef class ThermoPhase(_SolutionBase):
return index
def species(self, k):
s = Species(init=False)
if isinstance(k, (str, unicode)):
s._assign(self.thermo.species(stringify(k)))
elif isinstance(k, (int, float)):
s._assign(self.thermo.species(<int>k))
else:
raise TypeError("Argument must be a string or a number")
return s
def n_atoms(self, species, element):
"""
Number of atoms of element *element* in species *species*. The element

View file

@ -9,8 +9,8 @@
namespace Cantera {
Species::Species()
: charge(std::numeric_limits<double>::quiet_NaN())
, size(std::numeric_limits<double>::quiet_NaN())
: charge(0.0)
, size(0.0)
{
}