[ReactorNet] improve handling of max_time_step

* implement ReactorNet::maxTimeStep to allow for external queries
* implement getter/setter for property ReactorNet.max_time_step
* deprecate ReactorNet.set_max_time_step
This commit is contained in:
Ingmar Schoegl 2019-10-22 07:59:16 -05:00 committed by Bryan W. Weber
parent 3b7eb0dc8d
commit 76901b7f50
4 changed files with 54 additions and 16 deletions

View file

@ -35,6 +35,11 @@ public:
//! using the current mixture state as the initial condition. //! using the current mixture state as the initial condition.
void setInitialTime(double time); void setInitialTime(double time);
//! Get the maximum time step.
double maxTimeStep() {
return m_maxstep;
}
//! Set the maximum time step. //! Set the maximum time step.
void setMaxTimeStep(double maxstep); void setMaxTimeStep(double maxstep);

View file

@ -630,6 +630,7 @@ cdef extern from "cantera/zerodim.h" namespace "Cantera":
void setTolerances(double, double) void setTolerances(double, double)
double rtol() double rtol()
double atol() double atol()
double maxTimeStep()
void setMaxTimeStep(double) void setMaxTimeStep(double)
void setMaxErrTestFails(int) void setMaxErrTestFails(int)
void setMaxSteps(int) void setMaxSteps(int)

View file

@ -761,11 +761,11 @@ cdef class MassFlowController(FlowDevice):
.. math:: \dot m = \max(\dot m_0*g(t), 0.), .. math:: \dot m = \max(\dot m_0*g(t), 0.),
where :math:`\dot m_0` is a constant value and :math:`g(t)` is a function of 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 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`, the property `mass_flow_coeff` and the method `set_time_function`,
respectively. The method `set_mass_flow_rate` combines the former 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 into a single function. 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. 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 Unlike a real mass flow controller, a MassFlowController object will
@ -805,7 +805,7 @@ cdef class MassFlowController(FlowDevice):
Set the mass flow rate [kg/s] through this controller to be either Set the mass flow rate [kg/s] through this controller to be either
a constant or an arbitrary function of time. See `Func1`. a constant or an arbitrary function of time. See `Func1`.
Note that depending on the argument type, this method either changes Note that depending on the argument type, this method either changes
the property `mass_flow_coeff` or calls the `set_time_function` method. the property `mass_flow_coeff` or calls the `set_time_function` method.
>>> mfc.set_mass_flow_rate(0.3) >>> mfc.set_mass_flow_rate(0.3)
@ -887,7 +887,7 @@ cdef class Valve(FlowDevice):
Renamed to `set_pressure_function`. Renamed to `set_pressure_function`.
""" """
warnings.warn("To be removed after Cantera 2.5. " warnings.warn("To be removed after Cantera 2.5. "
"Renamed to `set_pressure_function` instead", DeprecationWarning) "Renamed to 'set_pressure_function' instead", DeprecationWarning)
self.set_pressure_function(k) self.set_pressure_function(k)
@ -909,8 +909,8 @@ cdef class Valve(FlowDevice):
`set_pressure_function`. `set_pressure_function`.
""" """
warnings.warn("To be removed after Cantera 2.5. " warnings.warn("To be removed after Cantera 2.5. "
"Use property `valve_coeff` and/or function " "Use property 'valve_coeff' and/or function "
"`set_pressure_function` instead.", DeprecationWarning) "'set_pressure_function' instead.", DeprecationWarning)
if isinstance(k, _numbers.Real): if isinstance(k, _numbers.Real):
self.valve_coeff = k self.valve_coeff = k
@ -936,7 +936,7 @@ cdef class PressureController(FlowDevice):
.. math:: \dot m = \dot m_{\rm master} + K_v*f(P_1 - P_2) .. math:: \dot m = \dot m_{\rm master} + K_v*f(P_1 - P_2)
where :math:`f` is the arbitrary function of a single argument. where :math:`f` is the arbitrary function of a single argument.
""" """
flowdevice_type = "PressureController" flowdevice_type = "PressureController"
@ -972,7 +972,7 @@ cdef class PressureController(FlowDevice):
Replaced by property `pressure_coeff`. Replaced by property `pressure_coeff`.
""" """
warnings.warn("To be removed after Cantera 2.5. " warnings.warn("To be removed after Cantera 2.5. "
"Use property `pressure_coeff` instead", DeprecationWarning) "Use property 'pressure_coeff' instead", DeprecationWarning)
(<CxxPressureController*>self.dev).setPressureCoeff(k) (<CxxPressureController*>self.dev).setPressureCoeff(k)
def set_master(self, FlowDevice d): def set_master(self, FlowDevice d):
@ -1052,11 +1052,30 @@ cdef class ReactorNet:
""" """
self.net.setInitialTime(t) self.net.setInitialTime(t)
property max_time_step:
"""
Get/set the maximum time step *t* [s] that the integrator is
allowed to use. The default value is set to zero, i.e. no time
step maximum is used.
"""
def __get__(self):
return self.net.maxTimeStep()
def __set__(self, double t):
self.net.setMaxTimeStep(t)
def set_max_time_step(self, double t): def set_max_time_step(self, double t):
""" """
Set the maximum time step *t* [s] that the integrator is allowed Set the maximum time step *t* [s] that the integrator is allowed
to use. to use.
.. deprecated:: 2.5
To be deprecated with version 2.5, and removed thereafter.
Replaced by property `max_time_step`.
""" """
warnings.warn("To be removed after Cantera 2.5. "
"Use property 'max_time_step' instead", DeprecationWarning)
self.net.setMaxTimeStep(t) self.net.setMaxTimeStep(t)
property max_err_test_fails: property max_err_test_fails:

View file

@ -149,7 +149,20 @@ class TestReactor(utilities.CanteraTest):
tEnd = 10.0 tEnd = 10.0
dt_max = 0.07 dt_max = 0.07
t = tStart t = tStart
self.net.set_max_time_step(dt_max)
with warnings.catch_warnings(record=True) as w:
# cause all warnings to always be triggered.
warnings.simplefilter("always")
self.net.set_max_time_step(dt_max)
self.assertEqual(len(w), 1)
self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
self.assertIn("To be removed after Cantera 2.5. ",
str(w[-1].message))
self.net.max_time_step = dt_max
self.assertEqual(self.net.max_time_step, dt_max)
self.net.set_initial_time(tStart) self.net.set_initial_time(tStart)
self.assertNear(self.net.time, tStart) self.assertNear(self.net.time, tStart)
@ -169,7 +182,7 @@ class TestReactor(utilities.CanteraTest):
max_steps = 10 max_steps = 10
max_step_size = 1e-07 max_step_size = 1e-07
self.net.set_initial_time(0) self.net.set_initial_time(0)
self.net.set_max_time_step(max_step_size) self.net.max_time_step = max_step_size
self.net.max_steps = max_steps self.net.max_steps = max_steps
with self.assertRaisesRegex( with self.assertRaisesRegex(
ct.CanteraError, 'mxstep steps taken before reaching tout'): ct.CanteraError, 'mxstep steps taken before reaching tout'):
@ -461,7 +474,7 @@ class TestReactor(utilities.CanteraTest):
self.assertNear(mfc.mdot(1.2), 0.) self.assertNear(mfc.mdot(1.2), 0.)
self.net.rtol = 1e-11 self.net.rtol = 1e-11
self.net.set_max_time_step(0.05) self.net.max_time_step = 0.05
self.net.advance(2.5) self.net.advance(2.5)
mb = self.r1.volume * self.r1.density mb = self.r1.volume * self.r1.density
@ -900,7 +913,7 @@ class TestWellStirredReactorIgnition(utilities.CanteraTest):
def test_ignition3(self): def test_ignition3(self):
self.setup(900.0, 10*ct.one_atm, 1.0, 80.0) self.setup(900.0, 10*ct.one_atm, 1.0, 80.0)
self.net.set_max_time_step(0.5) self.net.max_time_step = 0.5
t,T = self.integrate(100.0) t,T = self.integrate(100.0)
self.assertTrue(T[-1] < 910) # mixture did not ignite self.assertTrue(T[-1] < 910) # mixture did not ignite
@ -978,8 +991,8 @@ class TestConstPressureReactor(utilities.CanteraTest):
self.net1 = ct.ReactorNet([self.r1]) self.net1 = ct.ReactorNet([self.r1])
self.net2 = ct.ReactorNet([self.r2]) self.net2 = ct.ReactorNet([self.r2])
self.net1.set_max_time_step(0.05) self.net1.max_time_step = 0.05
self.net2.set_max_time_step(0.05) self.net2.max_time_step = 0.05
self.net2.max_err_test_fails = 10 self.net2.max_err_test_fails = 10
def test_component_index(self): def test_component_index(self):