From c0fa589b8caa3d18bbeb12e77e371541cb0c0aff Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Thu, 18 Jun 2015 12:18:59 -0400 Subject: [PATCH] [Reactor] Fix segfaults in updateMassFlowRate due to unset parameters The downstream and upstream Reactors, the "master" flow controller, and the coefficient arrays were being read without checking that they had been initialized. Fixes #278. --- include/cantera/zeroD/flowControllers.h | 15 ++++++++++++--- interfaces/cython/cantera/_cantera.pxd | 2 +- .../cython/cantera/test/test_reactor.py | 19 +++++++++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/include/cantera/zeroD/flowControllers.h b/include/cantera/zeroD/flowControllers.h index 73b8807cd..c301043f3 100644 --- a/include/cantera/zeroD/flowControllers.h +++ b/include/cantera/zeroD/flowControllers.h @@ -54,7 +54,7 @@ public: } virtual bool ready() { - return FlowDevice::ready() && m_master != 0; + return FlowDevice::ready() && m_master != 0 && m_coeffs.size() == 1; } void setMaster(FlowDevice* master) { @@ -62,6 +62,10 @@ public: } virtual void updateMassFlowRate(doublereal time) { + if (!ready()) { + throw CanteraError("PressureController::updateMassFlowRate", + "Device is not ready; some parameters have not been set."); + } doublereal master_mdot = m_master->massFlowRate(time); m_mdot = master_mdot + m_coeffs[0]*(in().pressure() - out().pressure()); @@ -72,7 +76,8 @@ protected: FlowDevice* m_master; }; -//! Supply a mass flow rate that is a function of the pressure drop across the valve. +//! Supply a mass flow rate that is a function of the pressure drop across the +//! valve. /*! * The default behavior is a linearly proportional to the pressure difference. * Note that real valves do not have this behavior, so this class does not @@ -86,11 +91,15 @@ public: } virtual bool ready() { - return FlowDevice::ready() && m_coeffs.size() >= 1; + return FlowDevice::ready() && (m_coeffs.size() == 1 || m_func); } /// Compute the currrent mass flow rate, based on the pressure difference. virtual void updateMassFlowRate(doublereal time) { + if (!ready()) { + throw CanteraError("Valve::updateMassFlowRate", + "Device is not ready; some parameters have not been set."); + } double delta_P = in().pressure() - out().pressure(); if (m_func) { m_mdot = m_func->eval(delta_P); diff --git a/interfaces/cython/cantera/_cantera.pxd b/interfaces/cython/cantera/_cantera.pxd index d50389605..91ecd9c48 100644 --- a/interfaces/cython/cantera/_cantera.pxd +++ b/interfaces/cython/cantera/_cantera.pxd @@ -517,7 +517,7 @@ cdef extern from "cantera/zeroD/Wall.h": cdef extern from "cantera/zeroD/flowControllers.h": cdef cppclass CxxFlowDevice "Cantera::FlowDevice": CxxFlowDevice() - double massFlowRate(double) + double massFlowRate(double) except + cbool install(CxxReactorBase&, CxxReactorBase&) void setFunction(CxxFunc1*) void setParameters(int, double*) diff --git a/interfaces/cython/cantera/test/test_reactor.py b/interfaces/cython/cantera/test/test_reactor.py index ae8d81079..941781696 100644 --- a/interfaces/cython/cantera/test/test_reactor.py +++ b/interfaces/cython/cantera/test/test_reactor.py @@ -457,6 +457,25 @@ class TestReactor(utilities.CanteraTest): dP = self.r1.thermo.P - outlet_reservoir.thermo.P self.assertNear(mdot(t) + 1e-5 * dP, pc.mdot(t)) + def test_pressure_controller_errors(self): + self.make_reactors() + res = ct.Reservoir(self.gas1) + mfc = ct.MassFlowController(res, self.r1, mdot=0.6) + + p = ct.PressureController(self.r1, self.r2, master=mfc, K=0.5) + + with self.assertRaises(RuntimeError): + p = ct.PressureController(self.r1, self.r2, K=0.5) + p.mdot(0.0) + + with self.assertRaises(RuntimeError): + p = ct.PressureController(self.r1, self.r2, master=mfc) + p.mdot(0.0) + + with self.assertRaises(RuntimeError): + p = ct.PressureController(self.r1, self.r2) + p.mdot(0.0) + def test_set_initial_time(self): self.make_reactors(P1=10*ct.one_atm, X1='AR:1.0', X2='O2:1.0') self.net.rtol = 1e-12