[Kinetics] Add functions for creating Reaction objects from CTI/XML

This commit is contained in:
Ray Speth 2015-04-27 18:00:42 -04:00
parent b6ac3ce995
commit c994917bae
5 changed files with 143 additions and 0 deletions

View file

@ -255,6 +255,27 @@ public:
//! Create a new Reaction object for the reaction defined in `rxn_node`
shared_ptr<Reaction> newReaction(const XML_Node& rxn_node);
//! Create Reaction objects for all <reaction> nodes in an XML document.
//!
//! The `<reaction>` nodes are assumed to be children of the `<reactionData>`
//! 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 Reaction objects from either a file or a
//! string, respectively, where the string or file is formatted as either CTI
//! or XML.
//!
//! If Reaction objects are being created from a CTI definition that does not
//! contain corresponding phase definitions, then one of the following must be
//! true, or the resulting rate constants will be incorrect:
//!
//! - The rate constants are expressed in (kmol, meter, second) units
//! - A `units` directive is included **and** all reactions take place in
//! bulk (e.g. gas) phases
std::vector<shared_ptr<Reaction> > getReactions(const XML_Node& node);
}
#endif

View file

@ -192,6 +192,9 @@ cdef extern from "cantera/thermo/SurfPhase.h":
cdef extern from "cantera/kinetics/Reaction.h" namespace "Cantera":
cdef shared_ptr[CxxReaction] CxxNewReaction "newReaction" (XML_Node&)
cdef vector[shared_ptr[CxxReaction]] CxxGetReactions "getReactions" (XML_Node&)
cdef cppclass CxxArrhenius "Cantera::Arrhenius":
CxxArrhenius()
CxxArrhenius(double, double, double)

View file

@ -22,6 +22,61 @@ cdef class Reaction:
self._reaction = other
self.reaction = self._reaction.get()
@staticmethod
def fromCti(text):
"""
Create a Reaction object from its CTI string representation.
"""
cxx_reactions = CxxGetReactions(deref(CxxGetXmlFromString(stringify(text))))
assert cxx_reactions.size() == 1, cxx_reactions.size()
return wrapReaction(cxx_reactions[0])
@staticmethod
def fromXml(text):
"""
Create a Reaction object from its XML string representation.
"""
cxx_reaction = CxxNewReaction(deref(CxxGetXmlFromString(stringify(text))))
return wrapReaction(cxx_reaction)
@staticmethod
def listFromFile(filename):
"""
Create a list of Reaction objects from all of the reactions 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 <reactions> nodes are assumed to be
children of the <reactionsData> node in a document with a <ctml> root
node, as in the XML files produced by conversion from CTI files.
"""
cxx_reactions = CxxGetReactions(deref(CxxGetXmlFile(stringify(filename))))
return [wrapReaction(r) for r in cxx_reactions]
@staticmethod
def listFromXml(text):
"""
Create a list of Reaction objects from all the reaction defined in an
XML string. The <reaction> nodes are assumed to be children of the
<reactionData> node in a document with a <ctml> root node, as in the XML
files produced by conversion from CTI files.
"""
cxx_reactions = CxxGetReactions(deref(CxxGetXmlFromString(stringify(text))))
return [wrapReaction(r) for r in cxx_reactions]
@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_reactions = CxxGetReactions(deref(CxxGetXmlFromString(stringify(text))))
return [wrapReaction(r) for r in cxx_reactions]
property reactant_string:
def __get__(self):
return pystr(self.reaction.reactantString())

View file

@ -510,3 +510,52 @@ class TestDuplicateReactions(utilities.CanteraTest):
def test_declared_duplicate(self):
gas = ct.Solution(self.infile, 'I')
self.assertEqual(gas.n_reactions, 2)
class TestReaction(utilities.CanteraTest):
@classmethod
def setUpClass(cls):
cls.gas = ct.Solution('h2o2.xml')
def test_fromCti(self):
r = ct.Reaction.fromCti('''three_body_reaction('2 O + M <=> O2 + M',
[1.200000e+11, -1.0, 0.0], efficiencies='AR:0.83 H2:2.4 H2O:15.4')''')
self.assertTrue(isinstance(r, ct.ThirdBodyReaction))
self.assertEqual(r.reactants['O'], 2)
self.assertEqual(r.products['O2'], 1)
self.assertEqual(r.efficiencies['H2O'], 15.4)
self.assertEqual(r.rate.temperature_exponent, -1.0)
def test_fromXml(self):
import xml.etree.ElementTree as ET
root = ET.parse('../../build/data/h2o2.xml').getroot()
rxn_node = root.find('.//reaction[@id="0001"]')
r = ct.Reaction.fromXml(ET.tostring(rxn_node))
self.assertTrue(isinstance(r, ct.ThirdBodyReaction))
self.assertEqual(r.reactants['O'], 2)
self.assertEqual(r.products['O2'], 1)
self.assertEqual(r.efficiencies['H2O'], 15.4)
self.assertEqual(r.rate.temperature_exponent, -1.0)
def test_listFromFile(self):
R = ct.Reaction.listFromFile('h2o2.xml')
eq1 = [r.equation for r in R]
eq2 = [self.gas.reaction(i).equation
for i in range(self.gas.n_reactions)]
self.assertEqual(eq1, eq2)
def test_listFromCti(self):
R = ct.Reaction.listFromCti(open('../../build/data/h2o2.cti').read())
eq1 = [r.equation for r in R]
eq2 = [self.gas.reaction(i).equation
for i in range(self.gas.n_reactions)]
self.assertEqual(eq1, eq2)
def test_listFromXml(self):
R = ct.Reaction.listFromCti(open('../../build/data/h2o2.xml').read())
eq1 = [r.equation for r in R]
eq2 = [self.gas.reaction(i).equation
for i in range(self.gas.n_reactions)]
self.assertEqual(eq1, eq2)

View file

@ -673,4 +673,19 @@ shared_ptr<Reaction> newReaction(const XML_Node& rxn_node)
}
}
std::vector<shared_ptr<Reaction> > getReactions(const XML_Node& node)
{
std::vector<shared_ptr<Reaction> > all_reactions;
std::vector<XML_Node*> reaction_nodes =
node.child("reactionData").getChildren("reaction");
for (std::vector<XML_Node*>::iterator iter = reaction_nodes.begin();
iter != reaction_nodes.end();
++iter)
{
all_reactions.push_back(newReaction(**iter));
}
return all_reactions;
}
}