[Kinetics] Add functions for creating Reaction objects from CTI/XML
This commit is contained in:
parent
b6ac3ce995
commit
c994917bae
5 changed files with 143 additions and 0 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue