[Python] Add functions for creating Species objects from CTI/XML

This commit is contained in:
Ray Speth 2015-04-20 18:32:49 -04:00
parent 64c66437eb
commit a4ba47594c
5 changed files with 177 additions and 11 deletions

View file

@ -53,6 +53,17 @@ public:
//! Create a new Species object from a 'species' XML_Node.
shared_ptr<Species> newSpecies(const XML_Node& species_node);
//! Generate Species objects for all <species> nodes in an XML document.
//!
//! The <species> nodes are assumed to be children of the <speciesData> node in
//! an XML document with a <ctml> root node, as in the case of XML files
//! produced by conversion from CTI files.
//!
//! This function can be used in combination with get_XML_File and
//! get_XML_from_string to get Species objects from either a file or a string,
//! respectively, where the string or file is formatted as either CTI or XML.
std::vector<shared_ptr<Species> > getSpecies(const XML_Node& node);
}
#endif

View file

@ -53,7 +53,7 @@ cdef extern from "cantera/thermo/SpeciesThermoFactory.h":
cdef CxxSpeciesThermo* CxxNewSpeciesThermo "Cantera::newSpeciesThermoInterpType"\
(int, double, double, double, double*) except +
cdef extern from "cantera/thermo/Species.h":
cdef extern from "cantera/thermo/Species.h" namespace "Cantera":
cdef cppclass CxxSpecies "Cantera::Species":
CxxSpecies()
CxxSpecies(string, stdmap[string,double])
@ -64,6 +64,9 @@ cdef extern from "cantera/thermo/Species.h":
double charge
double size
cdef shared_ptr[CxxSpecies] CxxNewSpecies "newSpecies" (XML_Node&)
cdef vector[shared_ptr[CxxSpecies]] CxxGetSpecies "getSpecies" (XML_Node&)
cdef extern from "cantera/thermo/ThermoPhase.h" namespace "Cantera":
cdef cppclass CxxThermoPhase "Cantera::ThermoPhase":
CxxThermoPhase()

View file

@ -627,6 +627,9 @@ ideal_gas(name='spam', elements='O H',
class TestSpecies(utilities.CanteraTest):
def setUp(self):
self.gas = ct.Solution('h2o2.xml')
def test_standalone(self):
s = ct.Species('CH4', {'C':1, 'H':4})
@ -642,22 +645,82 @@ class TestSpecies(utilities.CanteraTest):
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 k in range(self.gas.n_species):
s = self.gas.species(k)
self.assertEqual(s.name, self.gas.species_name(k))
for m,n in s.composition.items():
self.assertEqual(n, gas.n_atoms(k,m))
self.assertEqual(n, self.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)
for name in self.gas.species_names:
s = self.gas.species(name)
self.assertEqual(s.name, name)
def test_fromCti(self):
h2_cti = """
species(
name="H2",
atoms="H:2",
thermo=(
NASA([200.00, 1000.00],
[2.344331120E+00, 7.980520750E-03, -1.947815100E-05,
2.015720940E-08, -7.376117610E-12, -9.179351730E+02,
6.830102380E-01]),
NASA([1000.00, 3500.00],
[3.337279200E+00, -4.940247310E-05, 4.994567780E-07,
-1.795663940E-10, 2.002553760E-14, -9.501589220E+02,
-3.205023310E+00])
),
transport=gas_transport(geom="linear",
diam=2.92,
well_depth=38.00,
polar=0.79,
rot_relax=280.00),
note = "TPIS78"
)"""
s1 = self.gas.species('H2')
s2 = ct.Species.fromCti(h2_cti)
self.assertEqual(s2.name, 'H2')
self.assertEqual(s1.composition, s2.composition)
self.assertEqual(s1.thermo.cp(350), s2.thermo.cp(350))
def test_fromXml(self):
import xml.etree.ElementTree as ET
root = ET.parse('../../build/data/h2o2.xml').getroot()
h2_node = root.find('.//species[@name="H2"]')
h2_string = ET.tostring(h2_node)
s1 = self.gas.species('H2')
s2 = ct.Species.fromXml(h2_string)
self.assertEqual(s2.name, 'H2')
self.assertEqual(s1.composition, s2.composition)
self.assertEqual(s1.thermo.cp(350), s2.thermo.cp(350))
def test_listFromFile_cti(self):
S = ct.Species.listFromFile('h2o2.cti')
self.assertEqual({sp.name for sp in S},
set(self.gas.species_names))
def test_listFromFile_xml(self):
S = ct.Species.listFromFile('h2o2.xml')
self.assertEqual({sp.name for sp in S},
set(self.gas.species_names))
def test_listFromCti(self):
S = ct.Species.listFromCti(open('../../build/data/h2o2.cti').read())
self.assertEqual({sp.name for sp in S},
set(self.gas.species_names))
def test_listFromXml(self):
S = ct.Species.listFromXml(open('../../build/data/h2o2.xml').read())
self.assertEqual({sp.name for sp in S},
set(self.gas.species_names))
class TestSpeciesThermo(utilities.CanteraTest):
def setUp(self):

View file

@ -36,6 +36,80 @@ cdef class Species:
self._species = other
self.species = self._species.get()
@staticmethod
def fromCti(text):
"""
Create a Species object from its CTI string representation.
"""
cxx_species = CxxGetSpecies(deref(CxxGetXmlFromString(stringify(text))))
assert cxx_species.size() == 1, cxx_species.size()
species = Species(init=False)
species._assign(cxx_species[0])
return species
@staticmethod
def fromXml(text):
"""
Create a Species object from its XML string representation.
"""
cxx_species = CxxNewSpecies(deref(CxxGetXmlFromString(stringify(text))))
species = Species(init=False)
species._assign(cxx_species)
return species
@staticmethod
def listFromFile(filename):
"""
Create a list of Species objects from all of the species defined in a
CTI or XML file.
Directories on Cantera's input file path will be searched for the
specified file.
In the case of an XML file, the <species> nodes are assumed to be
children of the <speciesData> node in a document with a <ctml> root
node, as in the XML files produced by conversion from CTI files.
"""
cxx_species = CxxGetSpecies(deref(CxxGetXmlFile(stringify(filename))))
species = []
for a in cxx_species:
b = Species(init=False)
b._assign(a)
species.append(b)
return species
@staticmethod
def listFromXml(text):
"""
Create a list of Species objects from all the species defined in an
XML string. The <species> nodes are assumed to be children of the
<speciesData> node in a document with a <ctml> root node, as in the XML
files produced by conversion from CTI files.
"""
cxx_species = CxxGetSpecies(deref(CxxGetXmlFromString(stringify(text))))
species = []
for a in cxx_species:
b = Species(init=False)
b._assign(a)
species.append(b)
return species
@staticmethod
def listFromCti(text):
"""
Create a list of Species objects from all the species defined in a CTI
string.
"""
# Currently identical to listFromXml since get_XML_from_string is able
# to distinguish between CTI and XML.
cxx_species = CxxGetSpecies(deref(CxxGetXmlFromString(stringify(text))))
species = []
for a in cxx_species:
b = Species(init=False)
b._assign(a)
species.append(b)
return species
property name:
def __get__(self):
return pystr(self.species.name)

View file

@ -82,4 +82,19 @@ shared_ptr<Species> newSpecies(const XML_Node& species_node)
return s;
}
std::vector<shared_ptr<Species> > getSpecies(const XML_Node& node)
{
std::vector<shared_ptr<Species> > all_species;
std::vector<XML_Node*> species_nodes =
node.child("speciesData").getChildren("species");
for (std::vector<XML_Node*>::iterator iter = species_nodes.begin();
iter != species_nodes.end();
++iter)
{
all_species.push_back(newSpecies(**iter));
}
return all_species;
}
}