Skip to content

Commit

Permalink
[Reactor] Fix segfaults in updateMassFlowRate due to unset parameters
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
speth committed Jun 18, 2015
1 parent cd545af commit c0fa589
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 4 deletions.
15 changes: 12 additions & 3 deletions include/cantera/zeroD/flowControllers.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,18 @@ class PressureController : public FlowDevice
}

virtual bool ready() {
return FlowDevice::ready() && m_master != 0;
return FlowDevice::ready() && m_master != 0 && m_coeffs.size() == 1;
}

void setMaster(FlowDevice* master) {
m_master = master;
}

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());
Expand All @@ -72,7 +76,8 @@ class PressureController : public FlowDevice
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
Expand All @@ -86,11 +91,15 @@ class Valve : public FlowDevice
}

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);
Expand Down
2 changes: 1 addition & 1 deletion interfaces/cython/cantera/_cantera.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -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*)
Expand Down
19 changes: 19 additions & 0 deletions interfaces/cython/cantera/test/test_reactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,25 @@ def test_pressure_controller(self):
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
Expand Down

0 comments on commit c0fa589

Please sign in to comment.