From 59b34ce549dd66ac6ab0ef405766fdaf9a3ddbf3 Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Tue, 30 Oct 2012 15:34:35 +0000 Subject: [PATCH] [Cython] Extract wall surface properties into a separate class --- interfaces/cython/cantera/_cantera.pxd | 10 +- interfaces/cython/cantera/reactor.pyx | 126 ++++++++---------- .../cython/cantera/test/test_reactor.py | 24 ++-- 3 files changed, 78 insertions(+), 82 deletions(-) diff --git a/interfaces/cython/cantera/_cantera.pxd b/interfaces/cython/cantera/_cantera.pxd index 38d93e401..7c58fdeac 100644 --- a/interfaces/cython/cantera/_cantera.pxd +++ b/interfaces/cython/cantera/_cantera.pxd @@ -433,13 +433,19 @@ cdef class Reactor(ReactorBase): cdef CxxReactor* reactor cdef object _kinetics +cdef class WallSurface: + cdef CxxWall* cxxwall + cdef object wall + cdef int side + cdef Kinetics _kinetics + cdef class Wall: cdef CxxWall* wall + cdef WallSurface leftSurface + cdef WallSurface rightSurface cdef object _velocityFunc cdef object _heatFluxFunc cdef str name - cdef Kinetics _leftKinetics - cdef Kinetics _rightKinetics cdef class FlowDevice: cdef CxxFlowDevice* dev diff --git a/interfaces/cython/cantera/reactor.pyx b/interfaces/cython/cantera/reactor.pyx index 589460aab..58135f7fb 100644 --- a/interfaces/cython/cantera/reactor.pyx +++ b/interfaces/cython/cantera/reactor.pyx @@ -229,6 +229,46 @@ cdef class FlowReactor(Reactor): return (self.reactor).distance() +cdef class WallSurface: + """ + Represents a wall surface in contact with the contents of a reactor. + """ + def __cinit__(self, Wall wall, int side): + self.wall = wall + self.cxxwall = wall.wall + self.side = side + self._kinetics = None + + property kinetics: + """ + The `InterfaceKinetics` object used for calculating reaction + rates on this wall surface. + """ + def __get__(self): + return self._kinetics + def __set__(self, Kinetics k): + self._kinetics = k + self.wall._setKinetics() + + property coverages: + """ + The fraction of sites covered by each surface species. + """ + def __get__(self): + if self._kinetics is None: + raise Exception('No kinetics manager present') + self.cxxwall.syncCoverages(self.side) + return self._kinetics.coverages + def __set__(self, coverages): + if self._kinetics is None: + raise Exception("Can't set coverages before assigning kinetics manager.") + if len(coverages) != self._kinetics.nSpecies: + raise ValueError('Incorrect number of site coverages specified') + cdef np.ndarray[np.double_t, ndim=1] data = \ + np.ascontiguousarray(coverages, dtype=np.double) + self.cxxwall.setCoverages(self.side, &data[0]) + + cdef class Wall: r""" A Wall separates two reactors, or a reactor and a reservoir. A wall has a @@ -266,6 +306,8 @@ cdef class Wall: def __cinit__(self, *args, **kwargs): self.wall = new CxxWall() + self.leftSurface = WallSurface(self, 0) + self.rightSurface = WallSurface(self, 1) def __init__(self, left, right, *, name=None, A=None, K=None, U=None, Q=None, velocity=None, kinetics=(None,None)): @@ -299,8 +341,6 @@ cdef class Wall: """ self._velocityFunc = None self._heatFluxFunc = None - self._leftKinetics = None - self._rightKinetics = None self._install(left, right) if name is not None: @@ -321,9 +361,9 @@ cdef class Wall: if velocity is not None: self.setVelocity(velocity) if kinetics[0] is not None: - self.leftKinetics = kinetics[0] + self.leftSurface.kinetics = kinetics[0] if kinetics[1] is not None: - self.leftKinetics = kinetics[1] + self.rightSurface.kinetics = kinetics[1] def _install(self, ReactorBase left, ReactorBase right): """ @@ -334,6 +374,16 @@ cdef class Wall: right._addWall(self) self.wall.install(deref(left.rbase), deref(right.rbase)) + property left: + """ The left surface of this wall. """ + def __get__(self): + return self.leftSurface + + property right: + """ The right surface of this wall. """ + def __get__(self): + return self.rightSurface + property expansionRateCoeff: """ The coefficient *K* [m/s/Pa] that determines the velocity of the wall @@ -409,73 +459,13 @@ cdef class Wall: """ return self.wall.Q(t) - property leftKinetics: - """ - The `InterfaceKinetics` object used for calculating surface reactions - at the interface between the wall and the left-hand reactor. - """ - def __get__(self): - return self._leftKinetics - def __set__(self, Kinetics k): - self._leftKinetics = k - self._setKinetics() - - property rightKinetics: - """ - The `InterfaceKinetics` object used for calculating surface reactions - at the interface between the wall and the right-hand reactor. - """ - def __get__(self): - return self._rightKinetics - def __set__(self, Kinetics k): - self._rightKinetics = k - self._setKinetics() - def _setKinetics(self): - cdef CxxKinetics* L = (self._leftKinetics.kinetics - if self._leftKinetics else NULL) - cdef CxxKinetics* R = (self._rightKinetics.kinetics - if self._rightKinetics else NULL) + cdef CxxKinetics* L = (self.leftSurface._kinetics.kinetics + if self.leftSurface._kinetics else NULL) + cdef CxxKinetics* R = (self.rightSurface._kinetics.kinetics + if self.rightSurface._kinetics else NULL) self.wall.setKinetics(L, R) - property leftCoverages: - """ - The fraction of sites covered by each surface species on the - left-hand interface. - """ - def __get__(self): - if self._leftKinetics is None: - raise Exception('No kinetics manager present') - self.wall.syncCoverages(0) - return self.leftKinetics.coverages - def __set__(self, coverages): - if self._leftKinetics is None: - raise Exception("Can't set coverages before assigning kinetics manager.") - if len(coverages) != self._leftKinetics.nSpecies: - raise ValueError('Incorrect number of site coverages specified') - cdef np.ndarray[np.double_t, ndim=1] data = \ - np.ascontiguousarray(coverages, dtype=np.double) - self.wall.setCoverages(0, &data[0]) - - property rightCoverages: - """ - The fraction of sites covered by each surface species on the - right-hand interface. - """ - def __get__(self): - if self._rightKinetics is None: - raise Exception('No kinetics manager present') - self.wall.syncCoverages(1) - return self._rightKinetics.coverages - def __set__(self, coverages): - if self._rightKinetics is None: - raise Exception("Can't set coverages before assigning kinetics manager.") - if len(coverages) != self._rightKinetics.nSpecies: - raise ValueError('Incorrect number of site coverages specified') - cdef np.ndarray[np.double_t, ndim=1] data = \ - np.ascontiguousarray(coverages, dtype=np.double) - self.wall.setCoverages(1, &data[0]) - cdef class FlowDevice: """ diff --git a/interfaces/cython/cantera/test/test_reactor.py b/interfaces/cython/cantera/test/test_reactor.py index 827c23d20..a78c841e2 100644 --- a/interfaces/cython/cantera/test/test_reactor.py +++ b/interfaces/cython/cantera/test/test_reactor.py @@ -504,28 +504,28 @@ class TestWallKinetics(utilities.CanteraTest): def test_coverages(self): self.makeReactors() - self.w.leftKinetics = self.interface + self.w.left.kinetics = self.interface C = np.zeros(self.interface.nSpecies) C[0] = 0.3 C[4] = 0.7 - self.w.leftCoverages = C - self.assertArrayNear(self.w.leftCoverages, C) + self.w.left.coverages = C + self.assertArrayNear(self.w.left.coverages, C) self.net.advance(1e-5) - C_left = self.w.leftCoverages + C_left = self.w.left.coverages - self.assertEqual(self.w.rightKinetics, None) - self.assertRaises(Exception, lambda: self.w.rightCoverages) + self.assertEqual(self.w.right.kinetics, None) + self.assertRaises(Exception, lambda: self.w.right.coverages) self.makeReactors() - self.w.rightKinetics = self.interface - self.w.rightCoverages = C - self.assertArrayNear(self.w.rightCoverages, C) - self.assertEqual(self.w.leftKinetics, None) - self.assertRaises(Exception, lambda: self.w.leftCoverages) + self.w.right.kinetics = self.interface + self.w.right.coverages = C + self.assertArrayNear(self.w.right.coverages, C) + self.assertEqual(self.w.left.kinetics, None) + self.assertRaises(Exception, lambda: self.w.left.coverages) self.net.advance(1e-5) - C_right = self.w.rightCoverages + C_right = self.w.right.coverages self.assertNear(sum(C_left), 1.0) self.assertArrayNear(C_left, C_right)