From c5bc4d34127bef19c7b0c1c27e8e227536d499d0 Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Mon, 22 Jun 2015 12:11:09 -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 6f689d81a..ac28ddbed 100644 --- a/interfaces/cython/cantera/_cantera.pxd +++ b/interfaces/cython/cantera/_cantera.pxd @@ -512,7 +512,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 ab1ba960a..a54aa6b98 100644 --- a/interfaces/cython/cantera/test/test_reactor.py +++ b/interfaces/cython/cantera/test/test_reactor.py @@ -456,6 +456,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