From 358195ea9eb99ccbf356338b7d31fac55fc0eb01 Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Tue, 7 Jan 2020 11:50:34 -0600 Subject: [PATCH] [Reactor] Update Cython interface for mass_flow_rate - introduce MassFlowController.mass_flow_rate as property - deprecate MassFlowController.set_mass_flow_rate --- interfaces/cython/cantera/_cantera.pxd | 1 + interfaces/cython/cantera/reactor.pyx | 44 +++++++++++++------ .../cython/cantera/test/test_reactor.py | 10 ++--- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/interfaces/cython/cantera/_cantera.pxd b/interfaces/cython/cantera/_cantera.pxd index a1783e7d77..e60bee2922 100644 --- a/interfaces/cython/cantera/_cantera.pxd +++ b/interfaces/cython/cantera/_cantera.pxd @@ -613,6 +613,7 @@ cdef extern from "cantera/zerodim.h" namespace "Cantera": cdef cppclass CxxMassFlowController "Cantera::MassFlowController" (CxxFlowDevice): CxxMassFlowController() + void setMassFlowRate(double) void setMassFlowCoeff(double) double getMassFlowCoeff() diff --git a/interfaces/cython/cantera/reactor.pyx b/interfaces/cython/cantera/reactor.pyx index 66b7a4d47a..7c16218fd9 100644 --- a/interfaces/cython/cantera/reactor.pyx +++ b/interfaces/cython/cantera/reactor.pyx @@ -764,13 +764,13 @@ cdef class MassFlowController(FlowDevice): where :math:`\dot m_0` is a constant value and :math:`g(t)` is a function of time. Both :math:`\dot m_0` and :math:`g(t)` can be set individually by the property `mass_flow_coeff` and the method `set_time_function`, - respectively. The method `set_mass_flow_rate` combines the former - into a single function. Note that if :math:`\dot m_0*g(t) < 0`, the mass flow + respectively. The property `mass_flow_rate` combines the former + into a single interface. Note that if :math:`\dot m_0*g(t) < 0`, the mass flow rate will be set to zero, since reversal of the flow direction is not allowed. Unlike a real mass flow controller, a MassFlowController object will maintain the flow even if the downstream pressure is greater than the - upstream pressure. This allows simple implementation of loops, in which + upstream pressure. This allows simple implementation of loops, in which exhaust gas from a reactor is fed back into it through an inlet. But note that this capability should be used with caution, since no account is taken of the work required to do this. @@ -780,11 +780,7 @@ cdef class MassFlowController(FlowDevice): # The signature of this function causes warnings for Sphinx documentation def __init__(self, upstream, downstream, *, name=None, mdot=1.): super().__init__(upstream, downstream, name=name) - if isinstance(mdot, _numbers.Real): - self.mass_flow_coeff = mdot - else: - self.mass_flow_coeff = 1. - self.set_time_function(mdot) + self.mass_flow_rate = mdot property mass_flow_coeff: r"""Set the mass flow rate [kg/s] through the mass flow controller @@ -800,6 +796,24 @@ cdef class MassFlowController(FlowDevice): def __set__(self, double value): (self.dev).setMassFlowCoeff(value) + property mass_flow_rate: + r""" + Set the mass flow rate [kg/s] through this controller to be either + a constant or an arbitrary function of time. See `Func1`. + + Note that depending on the argument type, this method either changes + the property `mass_flow_coeff` or calls the `set_time_function` method. + + >>> mfc.mass_flow_rate = 0.3 + >>> mfc.mass_flow_rate = lambda t: 2.5 * exp(-10 * (t - 0.5)**2) + """ + def __set__(self, m): + if isinstance(m, _numbers.Real): + (self.dev).setMassFlowRate(m) + else: + self.mass_flow_coeff = 1. + self.set_time_function(m) + def set_mass_flow_rate(self, m): r""" Set the mass flow rate [kg/s] through this controller to be either @@ -810,12 +824,16 @@ cdef class MassFlowController(FlowDevice): >>> mfc.set_mass_flow_rate(0.3) >>> mfc.set_mass_flow_rate(lambda t: 2.5 * exp(-10 * (t - 0.5)**2)) + + .. deprecated:: 2.5 + + To be deprecated with version 2.5, and removed thereafter. + Replaced by property `mass_flow_rate`. """ - if isinstance(m, _numbers.Real): - self.mass_flow_coeff = m - else: - self.mass_flow_coeff = 1. - self.set_time_function(m) + warnings.warn("To be removed after Cantera 2.5. " + "Replaced by property 'mass_flow_rate'", DeprecationWarning) + + self.mass_flow_rate = m cdef class Valve(FlowDevice): diff --git a/interfaces/cython/cantera/test/test_reactor.py b/interfaces/cython/cantera/test/test_reactor.py index e788766bd4..e1963231e1 100644 --- a/interfaces/cython/cantera/test/test_reactor.py +++ b/interfaces/cython/cantera/test/test_reactor.py @@ -454,7 +454,7 @@ def test_mass_flow_controller(self): reservoir = ct.Reservoir(gas2) mfc = ct.MassFlowController(reservoir, self.r1) - mfc.set_mass_flow_rate(lambda t: 0.1 if 0.2 <= t < 1.2 else 0.0) + mfc.mass_flow_rate = lambda t: 0.1 if 0.2 <= t < 1.2 else 0.0 self.assertEqual(mfc.mass_flow_coeff, 1.) self.assertEqual(mfc.type, type(mfc).__name__) @@ -487,7 +487,7 @@ def test_mass_flow_controller_errors(self): # Make sure Python error message actually gets displayed self.make_reactors(n_reactors=2) mfc = ct.MassFlowController(self.r1, self.r2) - mfc.set_mass_flow_rate(lambda t: eggs) + mfc.mass_flow_rate = lambda t: eggs with self.assertRaisesRegex(Exception, 'eggs'): self.net.step() @@ -849,9 +849,9 @@ def setup(self, T0, P0, mdot_fuel, mdot_ox): # connect the reactor to the reservoirs self.fuel_mfc = ct.MassFlowController(self.fuel_in, self.combustor) - self.fuel_mfc.set_mass_flow_rate(mdot_fuel) + self.fuel_mfc.mass_flow_rate = mdot_fuel self.oxidizer_mfc = ct.MassFlowController(self.oxidizer_in, self.combustor) - self.oxidizer_mfc.set_mass_flow_rate(mdot_ox) + self.oxidizer_mfc.mass_flow_rate = mdot_ox self.valve = ct.Valve(self.combustor, self.exhaust) self.valve.valve_coeff = 1.0 @@ -1595,7 +1595,7 @@ def igniter_mdot(t, t0=0.1, fwhm=0.05, amplitude=0.1): # integration self.igniter.density return amplitude * math.exp(-(t-t0)**2 * 4 * math.log(2) / fwhm**2) - self.m3.set_mass_flow_rate(igniter_mdot) + self.m3.mass_flow_rate = igniter_mdot self.data = [] for t in np.linspace(0, 0.25, 101)[1:]: