[Reactor] clarify FlowDevice interface
* differentiated Valve::setValveCoeff from PressureController::setPressureCoeff and introduced MassFlowController::setMassFlowCoeff for consistency. * introduced FlowDevice::setTimeFunction and FlowDevice::setPressureFunction to differentiate time-dependent and pressure-dependent functions. * introduced arbitrary pressure dependence for PressureController * deprecated FlowDevice::setFunction which is replaced by time and pressure specific functions. * introduced properties Valve.valve_coeff / PressureController.pressure_coeff / MassFlowController.mass_flow_coeff in Cython interface and deprecated Valve.set_pressure_coeff / PressureController.set_pressure_coeff * deprecated corresponding function calls in clib interface * deprecate FlowDevice.setParameters (which was only used by MATLAB interface)
This commit is contained in:
parent
7523022d71
commit
bc8b4be654
14 changed files with 527 additions and 108 deletions
|
|
@ -3,7 +3,7 @@
|
|||
*/
|
||||
|
||||
// This file is part of Cantera. See License.txt in the top-level directory or
|
||||
// at http://www.cantera.org/license.txt for license and copyright information.
|
||||
// at https://cantera.org/license.txt for license and copyright information.
|
||||
|
||||
#ifndef CTC_REACTOR_H
|
||||
#define CTC_REACTOR_H
|
||||
|
|
@ -55,8 +55,13 @@ extern "C" {
|
|||
CANTERA_CAPI int flowdev_setMaster(int i, int n);
|
||||
CANTERA_CAPI double flowdev_massFlowRate(int i, double time);
|
||||
CANTERA_CAPI int flowdev_setMassFlowRate(int i, double mdot);
|
||||
CANTERA_CAPI int flowdev_setParameters(int i, int n, const double* v);
|
||||
CANTERA_CAPI int flowdev_setFunction(int i, int n);
|
||||
CANTERA_CAPI int flowdev_setParameters(int i, int n, const double* v); //!< @deprecated To be removed after Cantera 2.5.
|
||||
CANTERA_CAPI int flowdev_setMassFlowCoeff(int i, double v);
|
||||
CANTERA_CAPI int flowdev_setValveCoeff(int i, double v);
|
||||
CANTERA_CAPI int flowdev_setPressureCoeff(int i, double v);
|
||||
CANTERA_CAPI int flowdev_setFunction(int i, int n); //!< @deprecated To be removed after Cantera 2.5.
|
||||
CANTERA_CAPI int flowdev_setPressureFunction(int i, int n);
|
||||
CANTERA_CAPI int flowdev_setTimeFunction(int i, int n);
|
||||
|
||||
CANTERA_CAPI int wall_new2(const char* type);
|
||||
CANTERA_CAPI int wall_new(int type); //!< @deprecated To be changed after Cantera 2.5.
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ public:
|
|||
}
|
||||
|
||||
//! Mass flow rate (kg/s).
|
||||
doublereal massFlowRate(double time = -999.0) {
|
||||
double massFlowRate(double time = -999.0) {
|
||||
if (time != -999.0) {
|
||||
updateMassFlowRate(time);
|
||||
}
|
||||
|
|
@ -63,14 +63,14 @@ public:
|
|||
|
||||
//! Update the mass flow rate at time 'time'. This must be overloaded in
|
||||
//! subclassess to update m_mdot.
|
||||
virtual void updateMassFlowRate(doublereal time) {}
|
||||
virtual void updateMassFlowRate(double time) {}
|
||||
|
||||
//! Mass flow rate (kg/s) of outlet species k. Returns zero if this species
|
||||
//! is not present in the upstream mixture.
|
||||
doublereal outletSpeciesMassFlowRate(size_t k);
|
||||
double outletSpeciesMassFlowRate(size_t k);
|
||||
|
||||
//! specific enthalpy
|
||||
doublereal enthalpy_mass();
|
||||
double enthalpy_mass();
|
||||
|
||||
//! Install a flow device between two reactors.
|
||||
/*!
|
||||
|
|
@ -93,28 +93,64 @@ public:
|
|||
return *m_out;
|
||||
}
|
||||
|
||||
//! set parameters. Generic function used only in the Matlab interface. From
|
||||
//! Python or C++, device-specific functions like Valve::setPressureCoeff
|
||||
//! should be used instead.
|
||||
//! Set parameters. Generic function formerly used in the Matlab interface.
|
||||
//! @deprecated To be removed after Cantera 2.5.
|
||||
virtual void setParameters(int n, const double* coeffs) {
|
||||
m_coeffs.resize(n);
|
||||
std::copy(coeffs, coeffs + n, m_coeffs.begin());
|
||||
warn_deprecated("FlowDevice::setParameters()",
|
||||
"To be removed after Cantera 2.5. "
|
||||
"Use device-specific functions (e.g. "
|
||||
"Valve::setValveCoeff) instead.");
|
||||
m_coeff = coeffs[0]; // vectorized coefficients are not used
|
||||
}
|
||||
|
||||
//! Set a function of a single variable that is used in determining the
|
||||
//! mass flow rate through the device. The meaning of this function
|
||||
//! depends on the parameterization of the derived type.
|
||||
void setFunction(Func1* f);
|
||||
//! @deprecated To be removed after Cantera 2.5.
|
||||
void setFunction(Func1* f) {
|
||||
warn_deprecated("FlowDevice::setFunction()",
|
||||
"To be removed after Cantera 2.5. "
|
||||
"Use FlowDevice::setTimeFunction or "
|
||||
"FlowDevice::setPressureFunction instead.");
|
||||
if (typeStr()=="MassFlowController") {
|
||||
setTimeFunction(f);
|
||||
} else if (typeStr()=="Valve") {
|
||||
setPressureFunction(f);
|
||||
}
|
||||
}
|
||||
|
||||
//! Set a function of pressure that is used in determining the
|
||||
//! mass flow rate through the device. The evaluation of mass flow
|
||||
//! depends on the derived flow device class.
|
||||
virtual void setPressureFunction(Func1* f);
|
||||
|
||||
//! Set a function of time that is used in determining
|
||||
//! the mass flow rate through the device. The evaluation of mass flow
|
||||
//! depends on the derived flow device class.
|
||||
virtual void setTimeFunction(Func1* g);
|
||||
|
||||
//! Set the fixed mass flow rate (kg/s) through the flow device.
|
||||
void setMassFlowRate(doublereal mdot) {
|
||||
//! @deprecated To be removed after Cantera 2.5.
|
||||
void setMassFlowRate(double mdot) {
|
||||
warn_deprecated("FlowDevice::setMassFlowRate()",
|
||||
"To be removed after Cantera 2.5. "
|
||||
"Use device-specific functions (e.g. "
|
||||
"Valve::setValveCoeff) instead.");
|
||||
m_mdot = mdot;
|
||||
}
|
||||
|
||||
protected:
|
||||
doublereal m_mdot;
|
||||
Func1* m_func;
|
||||
vector_fp m_coeffs;
|
||||
double m_mdot;
|
||||
|
||||
//! Function set by setPressureFunction; used by updateMassFlowRate
|
||||
Func1* m_pfunc;
|
||||
|
||||
//! Function set by setTimeFunction; used by updateMassFlowRate
|
||||
Func1* m_tfunc;
|
||||
|
||||
//! Coefficient set by derived classes; used by updateMassFlowRate
|
||||
double m_coeff;
|
||||
|
||||
int m_type; //!< @deprecated To be removed after Cantera 2.5.
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#define CT_FLOWCONTR_H
|
||||
|
||||
#include "FlowDevice.h"
|
||||
#include "cantera/base/ctexceptions.h"
|
||||
|
||||
namespace Cantera
|
||||
{
|
||||
|
|
@ -28,6 +29,27 @@ public:
|
|||
return FlowDevice::ready() && m_mdot >= 0.0;
|
||||
}
|
||||
|
||||
//! Set the mass flow coefficient.
|
||||
/*!
|
||||
* *m* has units of kg/s. The mass flow rate is computed as:
|
||||
* \f[\dot{m} = m g(t) \f]
|
||||
* where *g* is a function of time that is set by `setTimeFunction`.
|
||||
* If no function is specified, the mass flow rate defaults to:
|
||||
* \f[\dot{m} = m \f]
|
||||
*/
|
||||
void setMassFlowCoeff(double m) {
|
||||
m_coeff = m;
|
||||
}
|
||||
|
||||
//! Get the mass flow coefficient.
|
||||
double getMassFlowCoeff() {
|
||||
return m_coeff;
|
||||
}
|
||||
|
||||
virtual void setPressureFunction(Func1* f) {
|
||||
throw NotImplementedError("MassFlowController::setPressureFunction");
|
||||
}
|
||||
|
||||
/// If a function of time has been specified for mdot, then update the
|
||||
/// stored mass flow rate. Otherwise, mdot is a constant, and does not
|
||||
/// need updating.
|
||||
|
|
@ -49,21 +71,34 @@ public:
|
|||
}
|
||||
|
||||
virtual bool ready() {
|
||||
return FlowDevice::ready() && m_master != 0 && m_coeffs.size() == 1;
|
||||
return FlowDevice::ready() && m_master != 0;
|
||||
}
|
||||
|
||||
void setMaster(FlowDevice* master) {
|
||||
m_master = master;
|
||||
}
|
||||
|
||||
virtual void setTimeFunction(Func1* g) {
|
||||
throw NotImplementedError("PressureController::setTimeFunction");
|
||||
}
|
||||
|
||||
//! Set the proportionality constant between pressure drop and mass flow
|
||||
//! rate
|
||||
/*!
|
||||
* *c* has units of kg/s/Pa. The mass flow rate is computed as:
|
||||
* \f[\dot{m} = \dot{m}_{master} + c f(\Delta P) \f]
|
||||
* where *f* is a functions of pressure drop that is set by
|
||||
* `setPressureFunction`. If no functions is specified, the mass flow
|
||||
* rate defaults to:
|
||||
* \f[\dot{m} = \dot{m}_{master} + c \Delta P \f]
|
||||
*/
|
||||
void setPressureCoeff(double c) {
|
||||
m_coeffs = {c};
|
||||
m_coeff = c;
|
||||
}
|
||||
|
||||
//! Get the pressure coefficient.
|
||||
double getPressureCoeff() {
|
||||
return m_coeff;
|
||||
}
|
||||
|
||||
virtual void updateMassFlowRate(double time);
|
||||
|
|
@ -88,18 +123,37 @@ public:
|
|||
return "Valve";
|
||||
}
|
||||
|
||||
virtual bool ready() {
|
||||
return FlowDevice::ready() && (m_coeffs.size() == 1 || m_func);
|
||||
}
|
||||
|
||||
//! Set the proportionality constant between pressure drop and mass flow
|
||||
//! rate
|
||||
/*!
|
||||
* *c* has units of kg/s/Pa. The mass flow rate is computed as:
|
||||
* \f[\dot{m} = c \Delta P \f]
|
||||
*/
|
||||
//! @deprecated To be removed after Cantera 2.5.
|
||||
void setPressureCoeff(double c) {
|
||||
m_coeffs = {c};
|
||||
warn_deprecated("Valve::setParameters()",
|
||||
"To be removed after Cantera 2.5. "
|
||||
"Use Valve::setValveCoeff instead.");
|
||||
m_coeff = c;
|
||||
}
|
||||
|
||||
//! Set the proportionality constant between pressure drop and mass flow
|
||||
//! rate
|
||||
/*!
|
||||
* *c* has units of kg/s/Pa. The mass flow rate is computed as:
|
||||
* \f[\dot{m} = c g(t) f(\Delta P) \f]
|
||||
* where *g* and *f* are functions of time and pressure drop that are set
|
||||
* by `setTimeFunction` and `setPressureFunction`, respectively. If no functions are
|
||||
* specified, the mass flow rate defaults to:
|
||||
* \f[\dot{m} = c \Delta P \f]
|
||||
*/
|
||||
void setValveCoeff(double c) {
|
||||
m_coeff = c;
|
||||
}
|
||||
|
||||
//! Get the valve coefficient.
|
||||
double getValveCoeff() {
|
||||
return m_coeff;
|
||||
}
|
||||
|
||||
/// Compute the currrent mass flow rate, based on the pressure difference.
|
||||
|
|
|
|||
|
|
@ -585,17 +585,22 @@ cdef extern from "cantera/zerodim.h" namespace "Cantera":
|
|||
string typeStr()
|
||||
double massFlowRate(double) except +translate_exception
|
||||
cbool install(CxxReactorBase&, CxxReactorBase&) except +translate_exception
|
||||
void setFunction(CxxFunc1*)
|
||||
void setPressureFunction(CxxFunc1*) except +translate_exception
|
||||
void setTimeFunction(CxxFunc1*) except +translate_exception
|
||||
|
||||
cdef cppclass CxxMassFlowController "Cantera::MassFlowController" (CxxFlowDevice):
|
||||
CxxMassFlowController()
|
||||
void setMassFlowCoeff(double)
|
||||
double getMassFlowCoeff()
|
||||
|
||||
cdef cppclass CxxValve "Cantera::Valve" (CxxFlowDevice):
|
||||
void setPressureCoeff(double)
|
||||
CxxValve()
|
||||
double getValveCoeff()
|
||||
void setValveCoeff(double)
|
||||
|
||||
cdef cppclass CxxPressureController "Cantera::PressureController" (CxxFlowDevice):
|
||||
CxxPressureController()
|
||||
double getPressureCoeff()
|
||||
void setPressureCoeff(double)
|
||||
void setMaster(CxxFlowDevice*)
|
||||
|
||||
|
|
@ -1032,6 +1037,7 @@ cdef class Wall(WallBase):
|
|||
cdef class FlowDevice:
|
||||
cdef CxxFlowDevice* dev
|
||||
cdef Func1 _rate_func
|
||||
cdef Func1 _time_func
|
||||
cdef str name
|
||||
cdef ReactorBase _upstream
|
||||
cdef ReactorBase _downstream
|
||||
|
|
|
|||
|
|
@ -125,15 +125,15 @@ for n1, t_i in enumerate(t):
|
|||
# define opening and closing of valves and injector
|
||||
if (np.mod(crank_angle(t_i) - inlet_open, 4 * np.pi) <
|
||||
np.mod(inlet_close - inlet_open, 4 * np.pi)):
|
||||
inlet_valve.set_valve_coeff(inlet_valve_coeff)
|
||||
inlet_valve.valve_coeff = inlet_valve_coeff
|
||||
test[n1] = 1
|
||||
else:
|
||||
inlet_valve.set_valve_coeff(0)
|
||||
inlet_valve.valve_coeff = 0.
|
||||
if (np.mod(crank_angle(t_i) - outlet_open, 4 * np.pi) <
|
||||
np.mod(outlet_close - outlet_open, 4 * np.pi)):
|
||||
outlet_valve.set_valve_coeff(outlet_valve_coeff)
|
||||
outlet_valve.valve_coeff = outlet_valve_coeff
|
||||
else:
|
||||
outlet_valve.set_valve_coeff(0)
|
||||
outlet_valve.valve_coeff = 0.
|
||||
if (np.mod(crank_angle(t_i) - injector_open, 4 * np.pi) <
|
||||
np.mod(injector_close - injector_open, 4 * np.pi)):
|
||||
injector_mfc.set_mass_flow_rate(injector_mass / injector_t_open)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# This file is part of Cantera. See License.txt in the top-level directory or
|
||||
# at https://cantera.org/license.txt for license and copyright information.
|
||||
|
||||
import warnings
|
||||
from collections import defaultdict as _defaultdict
|
||||
import numbers as _numbers
|
||||
|
||||
|
|
@ -712,6 +713,45 @@ cdef class FlowDevice:
|
|||
"""
|
||||
return self.dev.massFlowRate(t)
|
||||
|
||||
def set_pressure_function(self, k):
|
||||
r"""
|
||||
Set the relationship between mass flow rate and the pressure drop across a
|
||||
flow device. The mass flow rate [kg/s] is calculated given the pressure
|
||||
drop [Pa] and a coefficient set by a flow device specific function.
|
||||
The calculation of mass flow rate depends to the flow device.
|
||||
|
||||
>>> F = FlowDevice(res1, reactor1)
|
||||
>>> F.set_pressure_function(lambda dP: dP**2)
|
||||
|
||||
where FlowDevice is either a Valve or PressureController object.
|
||||
"""
|
||||
cdef Func1 f
|
||||
if isinstance(k, Func1):
|
||||
f = k
|
||||
else:
|
||||
f = Func1(k)
|
||||
self._rate_func = f
|
||||
self.dev.setPressureFunction(f.func)
|
||||
|
||||
def set_time_function(self, k):
|
||||
r"""
|
||||
Set the time dependence of a flow device. The mass flow rate [kg/s] is
|
||||
calculated for a flow device, and multiplied by a function of time.
|
||||
The calculation of mass flow rate depends to the flow device.
|
||||
|
||||
>>> F = FlowDevice(res1, reactor1)
|
||||
>>> F.set_time_function(lambda t: exp(-10 * (t - 0.5)**2))
|
||||
|
||||
where FlowDevice is either a Valve or MassFlowController object.
|
||||
"""
|
||||
cdef Func1 g
|
||||
if isinstance(k, Func1):
|
||||
g = k
|
||||
else:
|
||||
g = Func1(k)
|
||||
self._time_func = g
|
||||
self.dev.setTimeFunction(g.func)
|
||||
|
||||
|
||||
cdef class MassFlowController(FlowDevice):
|
||||
r"""
|
||||
|
|
@ -719,13 +759,14 @@ cdef class MassFlowController(FlowDevice):
|
|||
flow rate independent of upstream and downstream conditions. The equation
|
||||
used to compute the mass flow rate is
|
||||
|
||||
.. math::
|
||||
.. math:: \dot m = \max(\dot m_0*g(t), 0.),
|
||||
|
||||
\dot m = \max(\dot m_0, 0.0),
|
||||
|
||||
where :math:`\dot m_0` is either a constant value or a function of time.
|
||||
Note that if :math:`\dot m_0 < 0`, the mass flow rate will be set to zero,
|
||||
since reversal of the flow direction is not allowed.
|
||||
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
|
||||
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
|
||||
|
|
@ -737,27 +778,44 @@ cdef class MassFlowController(FlowDevice):
|
|||
flowdevice_type = "MassFlowController"
|
||||
|
||||
# The signature of this function causes warnings for Sphinx documentation
|
||||
def __init__(self, upstream, downstream, *, name=None, mdot=None):
|
||||
def __init__(self, upstream, downstream, *, name=None, mdot=1.):
|
||||
super().__init__(upstream, downstream, name=name)
|
||||
if mdot is not None:
|
||||
self.set_mass_flow_rate(mdot)
|
||||
if isinstance(mdot, _numbers.Real):
|
||||
self.mass_flow_coeff = mdot
|
||||
else:
|
||||
self.mass_flow_coeff = 1.
|
||||
self.set_time_function(mdot)
|
||||
|
||||
property mass_flow_coeff:
|
||||
r"""Set the mass flow rate [kg/s] through the mass flow controller
|
||||
as a constant, which may be modified by a function of time, see
|
||||
`set_time_function`.
|
||||
|
||||
>>> mfc = MassFlowController(res1, reactor1)
|
||||
>>> mfc.mass_flow_coeff = 1e-4 # Set the flow rate to a constant
|
||||
>>> mfc.mass_flow_coeff # Get the flow rate value
|
||||
"""
|
||||
def __get__(self):
|
||||
return (<CxxMassFlowController*>self.dev).getMassFlowCoeff()
|
||||
def __set__(self, double value):
|
||||
(<CxxMassFlowController*>self.dev).setMassFlowCoeff(value)
|
||||
|
||||
def set_mass_flow_rate(self, m):
|
||||
"""
|
||||
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.set_mass_flow_rate(0.3)
|
||||
>>> mfc.set_mass_flow_rate(lambda t: 2.5 * exp(-10 * (t - 0.5)**2))
|
||||
"""
|
||||
cdef Func1 f
|
||||
if isinstance(m, Func1):
|
||||
f = m
|
||||
if isinstance(m, _numbers.Real):
|
||||
self.mass_flow_coeff = m
|
||||
else:
|
||||
f = Func1(m)
|
||||
|
||||
self._rate_func = f
|
||||
self.dev.setFunction(f.func)
|
||||
self.mass_flow_coeff = 1.
|
||||
self.set_time_function(m)
|
||||
|
||||
|
||||
cdef class Valve(FlowDevice):
|
||||
|
|
@ -772,13 +830,18 @@ cdef class Valve(FlowDevice):
|
|||
:math:`\dot m = 0`. However, an arbitrary function can also be specified,
|
||||
such that
|
||||
|
||||
.. math:: \dot m = f(P_1 - P_2)
|
||||
.. math:: \dot m = K_v*f(P_1 - P_2)
|
||||
|
||||
where :math:`f` is the arbitrary function that returns the mass flow rate given
|
||||
a single argument, the pressure differential. See the documentation for the
|
||||
`set_valve_coeff` method for an example. Note that it is never possible for
|
||||
the flow to reverse and go from the downstream to the upstream
|
||||
reactor/reservoir through a line containing a `Valve` object.
|
||||
where :math:`f` is the arbitrary function that multiplies :math:`K_v` given
|
||||
a single argument, the pressure differential. Further, a valve opening function
|
||||
:math:`g` may be specified using the method `set_time_function`, such that
|
||||
|
||||
.. math:: \dot m = K_v*g(t)*f(P_1 - P_2)
|
||||
|
||||
See the documentation for the `valve_coeff` property as well as the
|
||||
`set_pressure_function` and `set_time_function` methods for examples. Note that
|
||||
it is never possible for the flow to reverse and go from the downstream to the
|
||||
upstream reactor/reservoir through a line containing a `Valve` object.
|
||||
|
||||
`Valve` objects are often used between an upstream reactor and a
|
||||
downstream reactor or reservoir to maintain them both at nearly the same
|
||||
|
|
@ -789,10 +852,44 @@ cdef class Valve(FlowDevice):
|
|||
flowdevice_type = "Valve"
|
||||
|
||||
# The signature of this function causes warnings for Sphinx documentation
|
||||
def __init__(self, upstream, downstream, *, name=None, K=None):
|
||||
def __init__(self, upstream, downstream, *, name=None, K=1.):
|
||||
super().__init__(upstream, downstream, name=name)
|
||||
if K is not None:
|
||||
self.set_valve_coeff(K)
|
||||
if isinstance(K, _numbers.Real):
|
||||
self.valve_coeff = K
|
||||
else:
|
||||
self.valve_coeff = 1.
|
||||
self.set_pressure_function(K)
|
||||
|
||||
property valve_coeff:
|
||||
r"""Set valve coefficient, i.e. the proportionality constant between mass
|
||||
flow rate and pressure drop [kg/s/Pa].
|
||||
|
||||
>>> V = Valve(res1, reactor1)
|
||||
>>> V.valve_coeff = 1e-4 # Set the value of K to a constant
|
||||
>>> V.valve_coeff # Get the value of K
|
||||
"""
|
||||
def __get__(self):
|
||||
return (<CxxValve*>self.dev).getValveCoeff()
|
||||
def __set__(self, double value):
|
||||
(<CxxValve*>self.dev).setValveCoeff(value)
|
||||
|
||||
def set_valve_function(self, k):
|
||||
r"""
|
||||
Set the relationship between mass flow rate and the pressure drop across the
|
||||
valve. The mass flow rate [kg/s] is calculated given the pressure drop [Pa].
|
||||
|
||||
>>> V = Valve(res1, reactor1)
|
||||
>>> V.set_valve_function(lambda dP: (1e-5 * dP)**2)
|
||||
|
||||
.. deprecated:: 2.5
|
||||
|
||||
To be deprecated with version 2.5, and removed thereafter.
|
||||
Renamed to `set_pressure_function`.
|
||||
"""
|
||||
warnings.warn("To be removed after Cantera 2.5. "
|
||||
"Renamed to `set_pressure_function` instead", DeprecationWarning)
|
||||
|
||||
self.set_pressure_function(k)
|
||||
|
||||
def set_valve_coeff(self, k):
|
||||
"""
|
||||
|
|
@ -803,20 +900,23 @@ cdef class Valve(FlowDevice):
|
|||
|
||||
>>> V = Valve(res1, reactor1)
|
||||
>>> V.set_valve_coeff(1e-4) # Set the value of K to a constant
|
||||
>>> V.set_valve_coeff(lambda dP: (1e-5 * dP)**2) # Set the value of K to a function
|
||||
"""
|
||||
cdef Func1 f
|
||||
if isinstance(k, _numbers.Real):
|
||||
kv = k
|
||||
(<CxxValve*>self.dev).setPressureCoeff(k)
|
||||
return
|
||||
>>> V.set_valve_coeff(lambda dP: (1e-5 * dP)**2) # Set to a function
|
||||
|
||||
if isinstance(k, Func1):
|
||||
f = k
|
||||
.. deprecated:: 2.5
|
||||
|
||||
To be deprecated with version 2.5, and removed thereafter.
|
||||
Functionality is now handled by property `valve_coeff` and
|
||||
`set_pressure_function`.
|
||||
"""
|
||||
warnings.warn("To be removed after Cantera 2.5. "
|
||||
"Use property `valve_coeff` and/or function "
|
||||
"`set_pressure_function` instead.", DeprecationWarning)
|
||||
|
||||
if isinstance(k, _numbers.Real):
|
||||
self.valve_coeff = k
|
||||
else:
|
||||
f = Func1(k)
|
||||
self._rate_func = f
|
||||
self.dev.setFunction(f.func)
|
||||
self.valve_coeff = 1.
|
||||
self.set_pressure_function(k)
|
||||
|
||||
|
||||
cdef class PressureController(FlowDevice):
|
||||
|
|
@ -830,22 +930,49 @@ cdef class PressureController(FlowDevice):
|
|||
difference:
|
||||
|
||||
.. math:: \dot m = \dot m_{\rm master} + K_v(P_1 - P_2).
|
||||
|
||||
As an alternative, an arbitrary function of pressure differential can be
|
||||
specified using the method `set_pressure_function`, such that
|
||||
|
||||
.. 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.
|
||||
"""
|
||||
flowdevice_type = "PressureController"
|
||||
|
||||
# The signature of this function causes warnings for Sphinx documentation
|
||||
def __init__(self, upstream, downstream, *, name=None, master=None, K=None):
|
||||
def __init__(self, upstream, downstream, *, name=None, master=None, K=1.):
|
||||
super().__init__(upstream, downstream, name=name)
|
||||
if master is not None:
|
||||
self.set_master(master)
|
||||
if K is not None:
|
||||
self.set_pressure_coeff(K)
|
||||
if isinstance(K, _numbers.Real):
|
||||
self.pressure_coeff = K
|
||||
else:
|
||||
self.pressure_coeff = 1.
|
||||
self.set_pressure_function(K)
|
||||
|
||||
property pressure_coeff:
|
||||
"""
|
||||
Get/set the proportionality constant :math:`K_v` [kg/s/Pa] between the
|
||||
pressure drop and the mass flow rate.
|
||||
"""
|
||||
def __get__(self):
|
||||
return (<CxxPressureController*>self.dev).getPressureCoeff()
|
||||
def __set__(self, double value):
|
||||
(<CxxPressureController*>self.dev).setPressureCoeff(value)
|
||||
|
||||
def set_pressure_coeff(self, double k):
|
||||
"""
|
||||
Set the proportionality constant :math:`K_v` [kg/s/Pa] between the pressure
|
||||
drop and the mass flow rate.
|
||||
|
||||
.. deprecated:: 2.5
|
||||
|
||||
To be deprecated with version 2.5, and removed thereafter.
|
||||
Replaced by property `pressure_coeff`.
|
||||
"""
|
||||
warnings.warn("To be removed after Cantera 2.5. "
|
||||
"Use property `pressure_coeff` instead", DeprecationWarning)
|
||||
(<CxxPressureController*>self.dev).setPressureCoeff(k)
|
||||
|
||||
def set_master(self, FlowDevice d):
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ from .utilities import unittest
|
|||
import cantera as ct
|
||||
from . import utilities
|
||||
|
||||
import warnings
|
||||
|
||||
class TestReactor(utilities.CanteraTest):
|
||||
reactorClass = ct.Reactor
|
||||
|
|
@ -441,6 +442,7 @@ class TestReactor(utilities.CanteraTest):
|
|||
|
||||
mfc = ct.MassFlowController(reservoir, self.r1)
|
||||
mfc.set_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__)
|
||||
self.assertEqual(len(reservoir.inlets), 0)
|
||||
|
|
@ -453,6 +455,11 @@ class TestReactor(utilities.CanteraTest):
|
|||
ma = self.r1.volume * self.r1.density
|
||||
Ya = self.r1.Y
|
||||
|
||||
self.assertNear(mfc.mdot(0.1), 0.)
|
||||
self.assertNear(mfc.mdot(0.2), 0.1)
|
||||
self.assertNear(mfc.mdot(1.1), 0.1)
|
||||
self.assertNear(mfc.mdot(1.2), 0.)
|
||||
|
||||
self.net.rtol = 1e-11
|
||||
self.net.set_max_time_step(0.05)
|
||||
self.net.advance(2.5)
|
||||
|
|
@ -463,7 +470,7 @@ class TestReactor(utilities.CanteraTest):
|
|||
self.assertNear(ma + 0.1, mb)
|
||||
self.assertArrayNear(ma * Ya + 0.1 * gas2.Y, mb * Yb)
|
||||
|
||||
def test_user_function_error(self):
|
||||
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)
|
||||
|
|
@ -472,14 +479,18 @@ class TestReactor(utilities.CanteraTest):
|
|||
with self.assertRaisesRegex(Exception, 'eggs'):
|
||||
self.net.step()
|
||||
|
||||
with self.assertRaisesRegex(ct.CanteraError, 'NotImplementedError'):
|
||||
mfc.set_pressure_function(lambda p: p**2)
|
||||
|
||||
def test_valve1(self):
|
||||
self.make_reactors(P1=10*ct.one_atm, X1='AR:1.0', X2='O2:1.0')
|
||||
self.net.rtol = 1e-12
|
||||
valve = ct.Valve(self.r1, self.r2)
|
||||
k = 2e-5
|
||||
valve.set_valve_coeff(k)
|
||||
valve.valve_coeff = k
|
||||
|
||||
self.assertEqual(self.r1.outlets, self.r2.inlets)
|
||||
self.assertEqual(valve.valve_coeff, k)
|
||||
self.assertTrue(self.r1.energy_enabled)
|
||||
self.assertTrue(self.r2.energy_enabled)
|
||||
self.assertNear((self.r1.thermo.P - self.r2.thermo.P) * k,
|
||||
|
|
@ -513,7 +524,8 @@ class TestReactor(utilities.CanteraTest):
|
|||
self.r2.energy_enabled = False
|
||||
valve = ct.Valve(self.r1, self.r2)
|
||||
k = 2e-5
|
||||
valve.set_valve_coeff(k)
|
||||
valve.valve_coeff = k
|
||||
self.assertEqual(valve.valve_coeff, k)
|
||||
|
||||
self.assertFalse(self.r1.energy_enabled)
|
||||
self.assertFalse(self.r2.energy_enabled)
|
||||
|
|
@ -544,7 +556,9 @@ class TestReactor(utilities.CanteraTest):
|
|||
self.net.atol = 1e-20
|
||||
valve = ct.Valve(self.r1, self.r2)
|
||||
mdot = lambda dP: 5e-3 * np.sqrt(dP) if dP > 0 else 0.0
|
||||
valve.set_valve_coeff(mdot)
|
||||
valve.set_pressure_function(mdot)
|
||||
self.assertEqual(valve.valve_coeff, 1.)
|
||||
|
||||
Y1 = self.r1.Y
|
||||
kO2 = self.gas1.species_index('O2')
|
||||
kAr = self.gas1.species_index('AR')
|
||||
|
|
@ -564,6 +578,50 @@ class TestReactor(utilities.CanteraTest):
|
|||
self.assertNear(speciesMass(kAr), mAr)
|
||||
self.assertNear(speciesMass(kO2), mO2)
|
||||
|
||||
def test_valve_timing(self):
|
||||
# test timed valve
|
||||
self.make_reactors(P1=10*ct.one_atm, X1='AR:1.0', X2='O2:1.0')
|
||||
self.net.rtol = 1e-12
|
||||
valve = ct.Valve(self.r1, self.r2)
|
||||
k = 2e-5
|
||||
valve.valve_coeff = k
|
||||
valve.set_time_function(lambda t: t>.01)
|
||||
|
||||
mdot = valve.valve_coeff * (self.r1.thermo.P - self.r2.thermo.P)
|
||||
self.assertTrue(valve.mdot(0.0)==0.)
|
||||
self.assertTrue(valve.mdot(0.01)==0.)
|
||||
self.assertTrue(valve.mdot(0.01 + 1e-9)==mdot)
|
||||
self.assertTrue(valve.mdot(0.02)==mdot)
|
||||
|
||||
def test_valve_deprecations(self):
|
||||
# Make sure Python deprecation warnings actually get displayed
|
||||
|
||||
self.make_reactors()
|
||||
valve = ct.Valve(self.r1, self.r2)
|
||||
k = 2e-5
|
||||
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
|
||||
# cause all warnings to always be triggered.
|
||||
warnings.simplefilter("always")
|
||||
valve.set_valve_coeff(k)
|
||||
|
||||
self.assertTrue(len(w) == 1)
|
||||
self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
|
||||
self.assertTrue("To be removed after Cantera 2.5. "
|
||||
in str(w[-1].message))
|
||||
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
|
||||
# cause all warnings to always be triggered.
|
||||
warnings.simplefilter("always")
|
||||
valve.set_valve_function(lambda t: t>.01)
|
||||
|
||||
self.assertTrue(len(w) == 1)
|
||||
self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
|
||||
self.assertTrue("To be removed after Cantera 2.5. "
|
||||
in str(w[-1].message))
|
||||
|
||||
def test_valve_errors(self):
|
||||
self.make_reactors()
|
||||
res = ct.Reservoir()
|
||||
|
|
@ -577,7 +635,7 @@ class TestReactor(utilities.CanteraTest):
|
|||
# inlet and outlet cannot be reassigned
|
||||
v._install(self.r2, self.r1)
|
||||
|
||||
def test_pressure_controller(self):
|
||||
def test_pressure_controller1(self):
|
||||
self.make_reactors(n_reactors=1)
|
||||
g = ct.Solution('h2o2.xml')
|
||||
g.TPX = 500, 2*101325, 'H2:1.0'
|
||||
|
|
@ -587,11 +645,13 @@ class TestReactor(utilities.CanteraTest):
|
|||
|
||||
mfc = ct.MassFlowController(inlet_reservoir, self.r1)
|
||||
mdot = lambda t: np.exp(-100*(t-0.5)**2)
|
||||
mfc.set_mass_flow_rate(mdot)
|
||||
mfc.mass_flow_coeff = 1.
|
||||
mfc.set_time_function(mdot)
|
||||
|
||||
pc = ct.PressureController(self.r1, outlet_reservoir)
|
||||
pc.set_master(mfc)
|
||||
pc.set_pressure_coeff(1e-5)
|
||||
pc.pressure_coeff = 1e-5
|
||||
self.assertEqual(pc.pressure_coeff, 1e-5)
|
||||
|
||||
t = 0
|
||||
while t < 1.0:
|
||||
|
|
@ -600,6 +660,52 @@ 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_controller2(self):
|
||||
self.make_reactors(n_reactors=1)
|
||||
g = ct.Solution('h2o2.xml')
|
||||
g.TPX = 500, 2*101325, 'H2:1.0'
|
||||
inlet_reservoir = ct.Reservoir(g)
|
||||
g.TP = 300, 101325
|
||||
outlet_reservoir = ct.Reservoir(g)
|
||||
|
||||
mfc = ct.MassFlowController(inlet_reservoir, self.r1)
|
||||
mdot = lambda t: np.exp(-100*(t-0.5)**2)
|
||||
mfc.mass_flow_coeff = 1.
|
||||
mfc.set_time_function(mdot)
|
||||
|
||||
pc = ct.PressureController(self.r1, outlet_reservoir)
|
||||
pc.set_master(mfc)
|
||||
pfunc = lambda dp: 1.e-5 * abs(dp)**.5
|
||||
pc.set_pressure_function(pfunc)
|
||||
self.assertEqual(pc.pressure_coeff, 1.)
|
||||
|
||||
t = 0
|
||||
while t < 1.0:
|
||||
t = self.net.step()
|
||||
self.assertNear(mdot(t), mfc.mdot(t))
|
||||
dP = self.r1.thermo.P - outlet_reservoir.thermo.P
|
||||
self.assertNear(mdot(t) + pfunc(dP), pc.mdot(t))
|
||||
|
||||
def test_pressure_controller_deprecations(self):
|
||||
# Make sure Python deprecation warnings actually get displayed
|
||||
|
||||
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 warnings.catch_warnings(record=True) as w:
|
||||
|
||||
# cause all warnings to always be triggered.
|
||||
warnings.simplefilter("always")
|
||||
p.set_pressure_coeff(2.)
|
||||
|
||||
self.assertTrue(len(w) == 1)
|
||||
self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
|
||||
self.assertTrue("To be removed after Cantera 2.5. "
|
||||
in str(w[-1].message))
|
||||
|
||||
def test_pressure_controller_errors(self):
|
||||
self.make_reactors()
|
||||
res = ct.Reservoir(self.gas1)
|
||||
|
|
@ -611,20 +717,20 @@ class TestReactor(utilities.CanteraTest):
|
|||
p = ct.PressureController(self.r1, self.r2, K=0.5)
|
||||
p.mdot(0.0)
|
||||
|
||||
with self.assertRaisesRegex(ct.CanteraError, 'Device is not ready'):
|
||||
p = ct.PressureController(self.r1, self.r2, master=mfc)
|
||||
p.mdot(0.0)
|
||||
|
||||
with self.assertRaisesRegex(ct.CanteraError, 'Device is not ready'):
|
||||
p = ct.PressureController(self.r1, self.r2)
|
||||
p.mdot(0.0)
|
||||
|
||||
with self.assertRaisesRegex(ct.CanteraError, 'NotImplementedError'):
|
||||
p = ct.PressureController(self.r1, self.r2)
|
||||
p.set_time_function(lambda t: t>1.)
|
||||
|
||||
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
|
||||
valve = ct.Valve(self.r1, self.r2)
|
||||
mdot = lambda dP: 5e-3 * np.sqrt(dP) if dP > 0 else 0.0
|
||||
valve.set_valve_coeff(mdot)
|
||||
valve.set_pressure_function(mdot)
|
||||
|
||||
t0 = 0.0
|
||||
tf = t0 + 0.5
|
||||
|
|
@ -637,7 +743,7 @@ class TestReactor(utilities.CanteraTest):
|
|||
self.net.rtol = 1e-12
|
||||
valve = ct.Valve(self.r1, self.r2)
|
||||
mdot = lambda dP: 5e-3 * np.sqrt(dP) if dP > 0 else 0.0
|
||||
valve.set_valve_coeff(mdot)
|
||||
valve.set_pressure_function(mdot)
|
||||
|
||||
t0 = 0.2
|
||||
self.net.set_initial_time(t0)
|
||||
|
|
@ -734,7 +840,7 @@ class TestWellStirredReactorIgnition(utilities.CanteraTest):
|
|||
self.oxidizer_mfc = ct.MassFlowController(self.oxidizer_in, self.combustor)
|
||||
self.oxidizer_mfc.set_mass_flow_rate(mdot_ox)
|
||||
self.valve = ct.Valve(self.combustor, self.exhaust)
|
||||
self.valve.set_valve_coeff(1.0)
|
||||
self.valve.valve_coeff = 1.0
|
||||
|
||||
self.net = ct.ReactorNet()
|
||||
self.net.add_reactor(self.combustor)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ function setFunction(f, mf)
|
|||
%
|
||||
|
||||
if strcmp(f.type, 'MassFlowController')
|
||||
k = flowdevicemethods(5, f.index, func_hndl(mf));
|
||||
k = flowdevicemethods(9, f.index, func_hndl(mf));
|
||||
if k < 0
|
||||
error(geterr);
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ function setMassFlowRate(f, mdot)
|
|||
% Mass flow rate
|
||||
%
|
||||
if strcmp(f.type, 'MassFlowController')
|
||||
k = flowdevicemethods(3, f.index, mdot);
|
||||
k = flowdevicemethods(10, f.index, mdot);
|
||||
if k < 0
|
||||
error(geterr);
|
||||
end
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ void runexample()
|
|||
|
||||
MassFlowController m3;
|
||||
m3.install(igniter, combustor);
|
||||
m3.setFunction(&igniter_mdot);
|
||||
m3.setTimeFunction(&igniter_mdot);
|
||||
|
||||
// put a valve on the exhaust line to regulate the pressure
|
||||
Valve v;
|
||||
|
|
|
|||
|
|
@ -420,6 +420,7 @@ extern "C" {
|
|||
|
||||
int flowdev_setMassFlowRate(int i, double mdot)
|
||||
{
|
||||
/* @deprecated To be removed after Cantera 2.5. */
|
||||
try {
|
||||
FlowDeviceCabinet::item(i).setMassFlowRate(mdot);
|
||||
return 0;
|
||||
|
|
@ -430,6 +431,7 @@ extern "C" {
|
|||
|
||||
int flowdev_setParameters(int i, int n, const double* v)
|
||||
{
|
||||
/* @deprecated To be removed after Cantera 2.5. */
|
||||
try {
|
||||
FlowDeviceCabinet::item(i).setParameters(n, v);
|
||||
return 0;
|
||||
|
|
@ -438,8 +440,39 @@ extern "C" {
|
|||
}
|
||||
}
|
||||
|
||||
int flowdev_setFunction(int i, int n)
|
||||
int flowdev_setMassFlowCoeff(int i, double v)
|
||||
{
|
||||
try {
|
||||
FlowDeviceCabinet::get<MassFlowController>(i).setMassFlowCoeff(v);
|
||||
return 0;
|
||||
} catch (...) {
|
||||
return handleAllExceptions(-1, ERR);
|
||||
}
|
||||
}
|
||||
|
||||
int flowdev_setValveCoeff(int i, double v)
|
||||
{
|
||||
try {
|
||||
FlowDeviceCabinet::get<Valve>(i).setValveCoeff(v);
|
||||
return 0;
|
||||
} catch (...) {
|
||||
return handleAllExceptions(-1, ERR);
|
||||
}
|
||||
}
|
||||
|
||||
int flowdev_setPressureCoeff(int i, double v)
|
||||
{
|
||||
try {
|
||||
FlowDeviceCabinet::get<PressureController>(i).setPressureCoeff(v);
|
||||
return 0;
|
||||
} catch (...) {
|
||||
return handleAllExceptions(-1, ERR);
|
||||
}
|
||||
}
|
||||
|
||||
int flowdev_setFunction(int i, int n)
|
||||
{
|
||||
/* @deprecated To be removed after Cantera 2.5. */
|
||||
try {
|
||||
FlowDeviceCabinet::item(i).setFunction(&FuncCabinet::item(n));
|
||||
return 0;
|
||||
|
|
@ -448,6 +481,26 @@ extern "C" {
|
|||
}
|
||||
}
|
||||
|
||||
int flowdev_setPressureFunction(int i, int n)
|
||||
{
|
||||
try {
|
||||
FlowDeviceCabinet::item(i).setPressureFunction(&FuncCabinet::item(n));
|
||||
return 0;
|
||||
} catch (...) {
|
||||
return handleAllExceptions(-1, ERR);
|
||||
}
|
||||
}
|
||||
|
||||
int flowdev_setTimeFunction(int i, int n)
|
||||
{
|
||||
try {
|
||||
FlowDeviceCabinet::item(i).setTimeFunction(&FuncCabinet::item(n));
|
||||
return 0;
|
||||
} catch (...) {
|
||||
return handleAllExceptions(-1, ERR);
|
||||
}
|
||||
}
|
||||
|
||||
///////////// Walls ///////////////////////
|
||||
|
||||
int wall_new(int type)
|
||||
|
|
|
|||
|
|
@ -43,17 +43,28 @@ void flowdevicemethods(int nlhs, mxArray* plhs[],
|
|||
iok = flowdev_install(i, int(v), m);
|
||||
break;
|
||||
case 3:
|
||||
// @deprecated To be removed after Cantera 2.5.
|
||||
iok = flowdev_setMassFlowRate(i, v);
|
||||
break;
|
||||
case 4:
|
||||
iok = flowdev_setParameters(i, 1, &v);
|
||||
iok = flowdev_setValveCoeff(i, v);
|
||||
break;
|
||||
case 5:
|
||||
// @deprecated To be removed after Cantera 2.5.
|
||||
iok = flowdev_setFunction(i, int(v));
|
||||
break;
|
||||
case 7:
|
||||
iok = flowdev_setMaster(i, int(v));
|
||||
break;
|
||||
case 8:
|
||||
iok = flowdev_setPressureFunction(i, int(v));
|
||||
break;
|
||||
case 9:
|
||||
iok = flowdev_setTimeFunction(i, int(v));
|
||||
break;
|
||||
case 10:
|
||||
iok = flowdev_setMassFlowCoeff(i, v);
|
||||
break;
|
||||
default:
|
||||
mexErrMsgTxt("unknown job parameter");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@
|
|||
namespace Cantera
|
||||
{
|
||||
|
||||
FlowDevice::FlowDevice() : m_mdot(0.0), m_func(0), m_type(0),
|
||||
FlowDevice::FlowDevice() : m_mdot(0.0), m_pfunc(0), m_tfunc(0),
|
||||
m_coeff(1.0), m_type(0),
|
||||
m_nspin(0), m_nspout(0),
|
||||
m_in(0), m_out(0) {}
|
||||
|
||||
|
|
@ -45,12 +46,17 @@ bool FlowDevice::install(ReactorBase& in, ReactorBase& out)
|
|||
return true;
|
||||
}
|
||||
|
||||
void FlowDevice::setFunction(Func1* f)
|
||||
void FlowDevice::setPressureFunction(Func1* f)
|
||||
{
|
||||
m_func = f;
|
||||
m_pfunc = f;
|
||||
}
|
||||
|
||||
doublereal FlowDevice::outletSpeciesMassFlowRate(size_t k)
|
||||
void FlowDevice::setTimeFunction(Func1* g)
|
||||
{
|
||||
m_tfunc = g;
|
||||
}
|
||||
|
||||
double FlowDevice::outletSpeciesMassFlowRate(size_t k)
|
||||
{
|
||||
if (k >= m_nspout) {
|
||||
return 0.0;
|
||||
|
|
@ -62,7 +68,7 @@ doublereal FlowDevice::outletSpeciesMassFlowRate(size_t k)
|
|||
return m_mdot * m_in->massFraction(ki);
|
||||
}
|
||||
|
||||
doublereal FlowDevice::enthalpy_mass()
|
||||
double FlowDevice::enthalpy_mass()
|
||||
{
|
||||
return m_in->enthalpy_mass();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,15 @@ MassFlowController::MassFlowController() : FlowDevice() {
|
|||
|
||||
void MassFlowController::updateMassFlowRate(double time)
|
||||
{
|
||||
if (m_func) {
|
||||
m_mdot = m_func->eval(time);
|
||||
if (!ready()) {
|
||||
throw CanteraError("MassFlowController::updateMassFlowRate",
|
||||
"Device is not ready; some parameters have not been set.");
|
||||
}
|
||||
m_mdot = std::max(m_mdot, 0.0);
|
||||
double mdot = m_coeff;
|
||||
if (m_tfunc) {
|
||||
mdot *= m_tfunc->eval(time);
|
||||
}
|
||||
m_mdot = std::max(mdot, 0.0);
|
||||
}
|
||||
|
||||
PressureController::PressureController() : FlowDevice(), m_master(0) {
|
||||
|
|
@ -32,9 +37,15 @@ void PressureController::updateMassFlowRate(double time)
|
|||
throw CanteraError("PressureController::updateMassFlowRate",
|
||||
"Device is not ready; some parameters have not been set.");
|
||||
}
|
||||
m_mdot = m_master->massFlowRate(time)
|
||||
+ m_coeffs[0]*(in().pressure() - out().pressure());
|
||||
m_mdot = std::max(m_mdot, 0.0);
|
||||
double mdot = m_coeff;
|
||||
double delta_P = in().pressure() - out().pressure();
|
||||
if (m_pfunc) {
|
||||
mdot *= m_pfunc->eval(delta_P);
|
||||
} else {
|
||||
mdot *= delta_P;
|
||||
}
|
||||
mdot += m_master->massFlowRate(time);
|
||||
m_mdot = std::max(mdot, 0.0);
|
||||
}
|
||||
|
||||
Valve::Valve() : FlowDevice() {
|
||||
|
|
@ -47,13 +58,17 @@ void Valve::updateMassFlowRate(double time)
|
|||
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);
|
||||
} else {
|
||||
m_mdot = m_coeffs[0]*delta_P;
|
||||
double mdot = m_coeff;
|
||||
if (m_tfunc) {
|
||||
mdot *= m_tfunc->eval(time);
|
||||
}
|
||||
m_mdot = std::max(m_mdot, 0.0);
|
||||
double delta_P = in().pressure() - out().pressure();
|
||||
if (m_pfunc) {
|
||||
mdot *= m_pfunc->eval(delta_P);
|
||||
} else {
|
||||
mdot *= delta_P;
|
||||
}
|
||||
m_mdot = std::max(mdot, 0.0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue