From 0a2b4816efac29899bb16138b74508d6a9057809 Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Wed, 29 Apr 2015 19:35:13 -0400 Subject: [PATCH] [Python] Add setters for constructing elementary and third-body reactions This allows creating reactions of these types without needing an XML or CTI input file. --- interfaces/cython/cantera/reaction.pyx | 29 ++++++++++++++-- .../cython/cantera/test/test_kinetics.py | 34 +++++++++++++++++++ 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/interfaces/cython/cantera/reaction.pyx b/interfaces/cython/cantera/reaction.pyx index f101c0429..9e1953595 100644 --- a/interfaces/cython/cantera/reaction.pyx +++ b/interfaces/cython/cantera/reaction.pyx @@ -94,40 +94,56 @@ cdef class Reaction: property reactants: def __get__(self): return comp_map_to_dict(self.reaction.reactants) + def __set__(self, reactants): + self.reaction.reactants = comp_map(reactants) property products: def __get__(self): return comp_map_to_dict(self.reaction.products) + def __set__(self, products): + self.reaction.products = comp_map(products) property orders: def __get__(self): return comp_map_to_dict(self.reaction.orders) + def __set__(self, orders): + self.reaction.orders = comp_map(orders) property ID: def __get__(self): return pystr(self.reaction.id) + def __set__(self, ID): + self.reaction.id = stringify(ID) property reversible: def __get__(self): return self.reaction.reversible + def __set__(self, reversible): + self.reaction.reversible = reversible property duplicate: def __get__(self): return self.reaction.duplicate + def __set__(self, duplicate): + self.reaction.duplicate = duplicate property allow_nonreactant_orders: def __get__(self): return self.reaction.allow_nonreactant_orders + def __set__(self, allow): + self.reaction.allow_nonreactant_orders = allow property allow_negative_orders: def __get__(self): return self.reaction.allow_negative_orders + def __set__(self, allow): + self.reaction.allow_negative_orders = allow cdef class Arrhenius: - def __cinit__(self, A=0, b=0, E=0, init=True): + def __cinit__(self, A=0, b=0, E=0, Ta=0, init=True): if init: - self.rate = new CxxArrhenius(A, b, E) + self.rate = new CxxArrhenius(A, b, E / gas_constant) self.reaction = None def __dealloc__(self): @@ -155,7 +171,7 @@ cdef wrapArrhenius(CxxArrhenius* rate, Reaction reaction): cdef copyArrhenius(CxxArrhenius* rate): r = Arrhenius(rate.preExponentialFactor(), rate.temperatureExponent(), - rate.activationEnergy_R()) + rate.activationEnergy_R() * gas_constant) return r @@ -166,6 +182,9 @@ cdef class ElementaryReaction(Reaction): def __get__(self): cdef CxxElementaryReaction* r = self.reaction return wrapArrhenius(&(r.rate), self) + def __set__(self, Arrhenius rate): + cdef CxxElementaryReaction* r = self.reaction + r.rate = deref(rate.rate) cdef class ThirdBodyReaction(ElementaryReaction): @@ -177,10 +196,14 @@ cdef class ThirdBodyReaction(ElementaryReaction): property efficiencies: def __get__(self): return comp_map_to_dict(self.tbr().third_body.efficiencies) + def __set__(self, eff): + self.tbr().third_body.efficiencies = comp_map(eff) property default_efficiency: def __get__(self): return self.tbr().third_body.default_efficiency + def __set__(self, default_eff): + self.tbr().third_body.default_efficiency = default_eff def efficiency(self, species): return self.tbr().third_body.efficiency(stringify(species)) diff --git a/interfaces/cython/cantera/test/test_kinetics.py b/interfaces/cython/cantera/test/test_kinetics.py index a96e99d09..c3274ee78 100644 --- a/interfaces/cython/cantera/test/test_kinetics.py +++ b/interfaces/cython/cantera/test/test_kinetics.py @@ -597,6 +597,9 @@ class TestReaction(utilities.CanteraTest): @classmethod def setUpClass(cls): cls.gas = ct.Solution('h2o2.xml') + cls.gas.X = 'H2:0.1, H2O:0.2, O2:0.7, O:1e-4, OH:1e-5, H:2e-5' + cls.gas.TP = 900, 2*ct.one_atm + cls.species = ct.Species.listFromFile('h2o2.xml') def test_fromCti(self): r = ct.Reaction.fromCti('''three_body_reaction('2 O + M <=> O2 + M', @@ -640,3 +643,34 @@ class TestReaction(utilities.CanteraTest): eq2 = [self.gas.reaction(i).equation for i in range(self.gas.n_reactions)] self.assertEqual(eq1, eq2) + + def test_elementary(self): + r = ct.ElementaryReaction() + r.reactants = {'O':1, 'H2':1} + r.products = {'H':1, 'OH':1} + r.rate = ct.Arrhenius(3.87e1, 2.7, 6260*1000*4.184) + + gas2 = ct.Solution(thermo='IdealGas', kinetics='GasKinetics', + species=self.species, reactions=[r]) + gas2.TPX = self.gas.TPX + + self.assertNear(gas2.forward_rate_constants[0], + self.gas.forward_rate_constants[2]) + self.assertNear(gas2.net_rates_of_progress[0], + self.gas.net_rates_of_progress[2]) + + def test_thirdbody(self): + r = ct.ThirdBodyReaction() + r.reactants = {'O':1, 'H':1} + r.products = {'OH':1} + r.rate = ct.Arrhenius(5e11, -1.0, 0.0) + r.efficiencies = {'AR':0.7, 'H2':2.0, 'H2O':6.0} + + gas2 = ct.Solution(thermo='IdealGas', kinetics='GasKinetics', + species=self.species, reactions=[r]) + gas2.TPX = self.gas.TPX + + self.assertNear(gas2.forward_rate_constants[0], + self.gas.forward_rate_constants[1]) + self.assertNear(gas2.net_rates_of_progress[0], + self.gas.net_rates_of_progress[1])