[Cython] Extract wall surface properties into a separate class

This commit is contained in:
Ray Speth 2012-10-30 15:34:35 +00:00
parent 20dbfc9b98
commit 59b34ce549
3 changed files with 78 additions and 82 deletions

View file

@ -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

View file

@ -229,6 +229,46 @@ cdef class FlowReactor(Reactor):
return (<CxxFlowReactor*>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:
"""

View file

@ -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)