From 5d62f3bacc113e97d3c57484b3c2e863826067cb Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Sat, 27 Apr 2019 23:56:24 -0500 Subject: [PATCH] added factories for FlowDevice and Wall objects --- include/cantera/zeroD/FlowDevice.h | 6 +- include/cantera/zeroD/FlowDeviceFactory.h | 72 ++++++ include/cantera/zeroD/FlowReactor.h | 2 +- .../zeroD/IdealGasConstPressureReactor.h | 2 +- include/cantera/zeroD/IdealGasReactor.h | 2 +- include/cantera/zeroD/Reactor.h | 2 +- include/cantera/zeroD/ReactorBase.h | 12 +- include/cantera/zeroD/ReactorFactory.h | 27 +- include/cantera/zeroD/Reservoir.h | 2 +- include/cantera/zeroD/Wall.h | 240 +++++++++++------- include/cantera/zeroD/WallFactory.h | 72 ++++++ include/cantera/zeroD/flowControllers.h | 48 +--- include/cantera/zerodim.h | 37 ++- interfaces/cython/cantera/_cantera.pxd | 62 +++-- interfaces/cython/cantera/reactor.pyx | 186 +++++++------- .../cython/cantera/test/test_reactor.py | 5 + src/clib/ctreactor.cpp | 44 +--- src/zeroD/FlowDevice.cpp | 4 + src/zeroD/FlowDeviceFactory.cpp | 43 ++++ src/zeroD/Reactor.cpp | 4 +- src/zeroD/ReactorBase.cpp | 6 +- src/zeroD/ReactorFactory.cpp | 24 +- src/zeroD/Wall.cpp | 49 ++-- src/zeroD/WallFactory.cpp | 39 +++ src/zeroD/flowControllers.cpp | 59 +++++ 25 files changed, 709 insertions(+), 340 deletions(-) create mode 100644 include/cantera/zeroD/FlowDeviceFactory.h create mode 100644 include/cantera/zeroD/WallFactory.h create mode 100644 src/zeroD/FlowDeviceFactory.cpp create mode 100644 src/zeroD/WallFactory.cpp create mode 100644 src/zeroD/flowControllers.cpp diff --git a/include/cantera/zeroD/FlowDevice.h b/include/cantera/zeroD/FlowDevice.h index e7848a9c0..57aec0711 100644 --- a/include/cantera/zeroD/FlowDevice.h +++ b/include/cantera/zeroD/FlowDevice.h @@ -1,7 +1,7 @@ //! @file FlowDevice.h // 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 CT_FLOWDEVICE_H #define CT_FLOWDEVICE_H @@ -27,9 +27,7 @@ const int Valve_Type = 3; class FlowDevice { public: - FlowDevice() : m_mdot(0.0), m_func(0), m_type(0), - m_nspin(0), m_nspout(0), - m_in(0), m_out(0) {} + FlowDevice(); virtual ~FlowDevice() {} FlowDevice(const FlowDevice&) = delete; diff --git a/include/cantera/zeroD/FlowDeviceFactory.h b/include/cantera/zeroD/FlowDeviceFactory.h new file mode 100644 index 000000000..d519940dd --- /dev/null +++ b/include/cantera/zeroD/FlowDeviceFactory.h @@ -0,0 +1,72 @@ +//! @file FlowDeviceFactory.h + +// 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. + +#ifndef FLOWDEVICE_FACTORY_H +#define FLOWDEVICE_FACTORY_H + +#include "cantera/base/FactoryBase.h" +#include "cantera/zeroD/FlowDevice.h" + +namespace Cantera +{ + +class FlowDeviceFactory : public Factory +{ +public: + static FlowDeviceFactory* factory() { + std::unique_lock lock(flowDevice_mutex); + if (!s_factory) { + s_factory = new FlowDeviceFactory; + } + return s_factory; + } + + virtual void deleteFactory() { + std::unique_lock lock(flowDevice_mutex); + delete s_factory; + s_factory = 0; + } + + //! Create a new flow device by type identifier. + /*! + * @param n the type to be created. + */ + virtual FlowDevice* newFlowDevice(int n); + + //! Create a new flow device by type name. + /*! + * @param flowDeviceType the type to be created. + */ + virtual FlowDevice* newFlowDevice(const std::string& flowDeviceType); + + //! Register a new flow device type identifier. + /*! + * @param name the name of the flow device type. + * @param type the type identifier of the flow device. + * Integer type identifiers are used by clib and matlab interfaces. + */ + void reg_type(const std::string& name, const int type) { + m_types[type] = name; + } + +protected: + //! Map containing flow device type identifier / type name pairs. + std::unordered_map m_types; + +private: + static FlowDeviceFactory* s_factory; + static std::mutex flowDevice_mutex; + FlowDeviceFactory(); +}; + +//! Create a FlowDevice object of the specified type +inline FlowDevice* newFlowDevice(const std::string& model) +{ + return FlowDeviceFactory::factory()->newFlowDevice(model); +} + +} + +#endif diff --git a/include/cantera/zeroD/FlowReactor.h b/include/cantera/zeroD/FlowReactor.h index 2e5164e5d..16a09b568 100644 --- a/include/cantera/zeroD/FlowReactor.h +++ b/include/cantera/zeroD/FlowReactor.h @@ -1,7 +1,7 @@ //! @file FlowReactor.h // 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 CT_FLOWREACTOR_H #define CT_FLOWREACTOR_H diff --git a/include/cantera/zeroD/IdealGasConstPressureReactor.h b/include/cantera/zeroD/IdealGasConstPressureReactor.h index 9ca3b449c..505d6fc0b 100644 --- a/include/cantera/zeroD/IdealGasConstPressureReactor.h +++ b/include/cantera/zeroD/IdealGasConstPressureReactor.h @@ -1,7 +1,7 @@ //! @file ConstPressureReactor.h // 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 CT_IDEALGASCONSTP_REACTOR_H #define CT_IDEALGASCONSTP_REACTOR_H diff --git a/include/cantera/zeroD/IdealGasReactor.h b/include/cantera/zeroD/IdealGasReactor.h index bc128bca0..b9ef027b1 100644 --- a/include/cantera/zeroD/IdealGasReactor.h +++ b/include/cantera/zeroD/IdealGasReactor.h @@ -1,7 +1,7 @@ //! @file IdealGasReactor.h // 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 CT_IDEALGASREACTOR_H #define CT_IDEALGASREACTOR_H diff --git a/include/cantera/zeroD/Reactor.h b/include/cantera/zeroD/Reactor.h index 705af9cac..168a13135 100644 --- a/include/cantera/zeroD/Reactor.h +++ b/include/cantera/zeroD/Reactor.h @@ -1,7 +1,7 @@ //! @file Reactor.h // 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 CT_REACTOR_H #define CT_REACTOR_H diff --git a/include/cantera/zeroD/ReactorBase.h b/include/cantera/zeroD/ReactorBase.h index 2592d51dd..054079c0a 100644 --- a/include/cantera/zeroD/ReactorBase.h +++ b/include/cantera/zeroD/ReactorBase.h @@ -1,7 +1,7 @@ //! @file ReactorBase.h // 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 CT_REACTORBASE_H #define CT_REACTORBASE_H @@ -12,7 +12,7 @@ namespace Cantera { class FlowDevice; -class Wall; +class WallBase; class ReactorNet; class ReactorSurface; @@ -111,12 +111,12 @@ public: /*! * `lr` = 0 if this reactor is to the left of the wall and `lr` = 1 if * this reactor is to the right of the wall. This method is called - * automatically for both the left and right reactors by Wall::install. + * automatically for both the left and right reactors by WallBase::install. */ - void addWall(Wall& w, int lr); + void addWall(WallBase& w, int lr); //! Return a reference to the *n*-th Wall connected to this reactor. - Wall& wall(size_t n); + WallBase& wall(size_t n); void addSurface(ReactorSurface* surf); @@ -239,7 +239,7 @@ protected: doublereal m_pressure; vector_fp m_state; std::vector m_inlet, m_outlet; - std::vector m_wall; + std::vector m_wall; std::vector m_surfaces; vector_int m_lr; std::string m_name; diff --git a/include/cantera/zeroD/ReactorFactory.h b/include/cantera/zeroD/ReactorFactory.h index 3a00bfb94..23b21cd8c 100644 --- a/include/cantera/zeroD/ReactorFactory.h +++ b/include/cantera/zeroD/ReactorFactory.h @@ -1,12 +1,12 @@ //! @file ReactorFactory.h // 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 REACTOR_FACTORY_H #define REACTOR_FACTORY_H -#include "ReactorBase.h" +#include "cantera/zeroD/ReactorBase.h" #include "cantera/base/FactoryBase.h" namespace Cantera @@ -29,13 +29,32 @@ public: s_factory = 0; } - /** - * Create a new reactor. + //! Create a new reactor by type identifier. + /*! * @param n the type to be created. */ virtual ReactorBase* newReactor(int n); + + //! Create a new reactor by type name. + /*! + * @param reactorType the type to be created. + */ virtual ReactorBase* newReactor(const std::string& reactorType); + //! Register a new reactor type identifier. + /*! + * @param name the name of the reactor type. + * @param type the type identifier of the reactor. + * Integer type identifiers are used by clib and matlab interfaces. + */ + void reg_type(const std::string& name, const int type) { + m_types[type] = name; + } + +protected: + //! Map containing reactor type identifier / reactor type name pairs. + std::unordered_map m_types; + private: static ReactorFactory* s_factory; static std::mutex reactor_mutex; diff --git a/include/cantera/zeroD/Reservoir.h b/include/cantera/zeroD/Reservoir.h index 4f3cac813..ed0812b93 100644 --- a/include/cantera/zeroD/Reservoir.h +++ b/include/cantera/zeroD/Reservoir.h @@ -1,7 +1,7 @@ //! @file Reservoir.h // 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 CT_RESERVOIR_H #define CT_RESERVOIR_H diff --git a/include/cantera/zeroD/Wall.h b/include/cantera/zeroD/Wall.h index 2469453fe..ae0996551 100644 --- a/include/cantera/zeroD/Wall.h +++ b/include/cantera/zeroD/Wall.h @@ -1,127 +1,81 @@ -//! @file Wall.h Header file for class Wall. +//! @file Wall.h Header file for base class WallBase. // 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 CT_WALL_H #define CT_WALL_H #include "cantera/base/ctexceptions.h" -#include "cantera/numerics/Func1.h" -#include "cantera/zeroD/ReactorBase.h" #include "cantera/zeroD/ReactorSurface.h" +#include "cantera/zeroD/ReactorBase.h" namespace Cantera { class Kinetics; class SurfPhase; +class Func1; -//! Represents a wall between between two ReactorBase objects. -/*! - * Walls can move (changing the volume of the adjacent reactors) and allow heat - * transfer between reactors. +const int WallType = 1; + +/** + * Base class for 'walls' (walls, pistons, etc.) connecting reactors. + * @ingroup reactor0 */ -class Wall +class WallBase { public: - Wall(); + WallBase(); - virtual ~Wall() {} - Wall(const Wall&) = delete; - Wall& operator=(const Wall&) = delete; + virtual ~WallBase() {} + WallBase(const WallBase&) = delete; + WallBase& operator=(const WallBase&) = delete; + + //! String indicating the wall model implemented. Usually + //! corresponds to the name of the derived class. + virtual std::string type() const { + return "WallBase"; + } //! Rate of volume change (m^3/s) for the adjacent reactors. /*! - * The volume rate of change is given by - * \f[ - * \dot V = K A (P_{left} - P_{right}) + F(t) - * \f] - * where *K* is the specified expansion rate coefficient, *A* is the wall - * area, and *F(t)* is a specified function of time. Positive values for - * `vdot` correspond to increases in the volume of reactor on left, and - * decreases in the volume of the reactor on the right. + * This method is called by Reactor::evalWalls(). Base class method + * does nothing (i.e. constant volume), but may be overloaded. */ - virtual doublereal vdot(doublereal t); + virtual double vdot(double t) { + return 0.0; + } //! Heat flow rate through the wall (W). /*! - * The heat flux is given by - * \f[ - * Q = h A (T_{left} - T_{right}) + A G(t) - * \f] - * where *h* is the heat transfer coefficient, *A* is the wall area, and - * *G(t)* is a specified function of time. Positive values denote a flux - * from left to right. + * This method is called by Reactor::evalWalls(). Base class method + * does nothing (i.e. adiabatic wall), but may be overloaded. */ - virtual doublereal Q(doublereal t); + virtual double Q(double t) { + return 0.0; + } - //! Area in m^2. - doublereal area() { + //! Area in (m^2). + double area() { return m_area; } //! Set the area [m^2]. - void setArea(doublereal a) { - m_area = a; - m_surf[0].setArea(a); - m_surf[1].setArea(a); - } + virtual void setArea(double a); //! Get the area [m^2] + /*! + * Redundant function (same as WallBase::area()). + * @deprecated To be removed after Cantera 2.5. + */ double getArea() const { + warn_deprecated("WallBase::getArea()", + "To be removed after Cantera 2.5. " + "Replace with WallBase::area()."); return m_area; } - void setThermalResistance(doublereal Rth) { - m_rrth = 1.0/Rth; - } - - //! Set the overall heat transfer coefficient [W/m^2/K]. - void setHeatTransferCoeff(doublereal U) { - m_rrth = U; - } - - //! Get the overall heat transfer coefficient [W/m^2/K]. - double getHeatTransferCoeff() const { - return m_rrth; - } - - //! Set the emissivity. - void setEmissivity(doublereal epsilon) { - if (epsilon > 1.0 || epsilon < 0.0) { - throw CanteraError("Wall::setEmissivity", - "emissivity must be between 0.0 and 1.0"); - } - m_emiss = epsilon; - } - - double getEmissivity() const { - return m_emiss; - } - - //! Set the wall velocity to a specified function of time - void setVelocity(Func1* f=0) { - if (f) { - m_vf = f; - } - } - - //! Set the expansion rate coefficient. - void setExpansionRateCoeff(doublereal k) { - m_k = k; - } - - //! Get the expansion rate coefficient - double getExpansionRateCoeff() const { - return m_k; - } - - //! Specify the heat flux function \f$ q_0(t) \f$. - void setHeatFlux(Func1* q) { - m_qf = q; - } - //! Install the wall between two reactors or reservoirs bool install(ReactorBase& leftReactor, ReactorBase& rightReactor); @@ -149,12 +103,118 @@ protected: std::vector m_surf; - doublereal m_area, m_k, m_rrth; - doublereal m_emiss; - Func1* m_vf; - Func1* m_qf; + double m_area; }; +//! Represents a wall between between two ReactorBase objects. +/*! + * Walls can move (changing the volume of the adjacent reactors) and allow heat + * transfer between reactors. + */ +class Wall : public WallBase +{ +public: + Wall(); + + //! String indicating the wall model implemented. Usually + //! corresponds to the name of the derived class. + virtual std::string type() const { + return "Wall"; + } + + //! Set the wall velocity to a specified function of time, i.e. \f$ v(t) \f$. + void setVelocity(Func1* f=0) { + if (f) { + m_vf = f; + } + } + + //! Rate of volume change (m^3/s) for the adjacent reactors. + /*! + * The volume rate of change is given by + * \f[ + * \dot V = K A (P_{left} - P_{right}) + F(t) + * \f] + * where *K* is the specified expansion rate coefficient, *A* is the wall + * area, and *F(t)* is a specified function of time. Positive values for + * `vdot` correspond to increases in the volume of reactor on left, and + * decreases in the volume of the reactor on the right. + */ + virtual double vdot(double t); + + //! Specify the heat flux function \f$ q_0(t) \f$. + void setHeatFlux(Func1* q) { + m_qf = q; + } + + //! Heat flow rate through the wall (W). + /*! + * The heat flux is given by + * \f[ + * Q = h A (T_{left} - T_{right}) + A G(t) + * \f] + * where *h* is the heat transfer coefficient, *A* is the wall area, and + * *G(t)* is a specified function of time. Positive values denote a flux + * from left to right. + */ + virtual double Q(double t); + + void setThermalResistance(double Rth) { + m_rrth = 1.0/Rth; + } + + //! Set the overall heat transfer coefficient [W/m^2/K]. + void setHeatTransferCoeff(double U) { + m_rrth = U; + } + + //! Get the overall heat transfer coefficient [W/m^2/K]. + double getHeatTransferCoeff() const { + return m_rrth; + } + + //! Set the emissivity. + void setEmissivity(double epsilon) { + if (epsilon > 1.0 || epsilon < 0.0) { + throw CanteraError("WallBase::setEmissivity", + "emissivity must be between 0.0 and 1.0"); + } + m_emiss = epsilon; + } + + //! Get the emissivity. + double getEmissivity() const { + return m_emiss; + } + + //! Set the expansion rate coefficient. + void setExpansionRateCoeff(double k) { + m_k = k; + } + + //! Get the expansion rate coefficient + double getExpansionRateCoeff() const { + return m_k; + } + +protected: + + //! expansion rate coefficient + double m_k; + + //! heat transfer coefficient + double m_rrth; + + //! emissivity + double m_emiss; + + //! Velocity function + Func1* m_vf; + + //! Heat flux function + Func1* m_qf; +}; + } #endif diff --git a/include/cantera/zeroD/WallFactory.h b/include/cantera/zeroD/WallFactory.h new file mode 100644 index 000000000..45040cd79 --- /dev/null +++ b/include/cantera/zeroD/WallFactory.h @@ -0,0 +1,72 @@ +//! @file WallFactory.h + +// 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. + +#ifndef WALL_FACTORY_H +#define WALL_FACTORY_H + +#include "cantera/base/FactoryBase.h" +#include "cantera/zeroD/Wall.h" + +namespace Cantera +{ + +class WallFactory : public Factory +{ +public: + static WallFactory* factory() { + std::unique_lock lock(wall_mutex); + if (!s_factory) { + s_factory = new WallFactory; + } + return s_factory; + } + + virtual void deleteFactory() { + std::unique_lock lock(wall_mutex); + delete s_factory; + s_factory = 0; + } + + //! Create a new wall by type identifier. + /*! + * @param n the type to be created. + */ + virtual WallBase* newWall(int n); + + //! Create a new wall by type name. + /*! + * @param wallType the type to be created. + */ + virtual WallBase* newWall(const std::string& wallType); + + //! Register a new wall type identifier. + /*! + * @param name the name of the wall type. + * @param type the type identifier of the wall. + * Integer type identifiers are used by clib and matlab interfaces. + */ + void reg_type(const std::string& name, const int type) { + m_types[type] = name; + } + +protected: + //! Map containing wall type identifier / wall type name pairs. + std::unordered_map m_types; + +private: + static WallFactory* s_factory; + static std::mutex wall_mutex; + WallFactory(); +}; + +//! Create a Wall object of the specified type +inline WallBase* newWall(const std::string& model) +{ + return WallFactory::factory()->newWall(model); +} + +} + +#endif diff --git a/include/cantera/zeroD/flowControllers.h b/include/cantera/zeroD/flowControllers.h index a5b6d2503..72097c438 100644 --- a/include/cantera/zeroD/flowControllers.h +++ b/include/cantera/zeroD/flowControllers.h @@ -1,17 +1,16 @@ //! @file flowControllers.h Some flow devices derived from class FlowDevice. // 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 CT_FLOWCONTR_H #define CT_FLOWCONTR_H #include "FlowDevice.h" -#include "ReactorBase.h" -#include "cantera/numerics/Func1.h" namespace Cantera { + /** * A class for mass flow controllers. The mass flow rate is constant or * specified as a function of time.. @@ -19,9 +18,7 @@ namespace Cantera class MassFlowController : public FlowDevice { public: - MassFlowController() : FlowDevice() { - m_type = MFC_Type; - } + MassFlowController(); virtual bool ready() { return FlowDevice::ready() && m_mdot >= 0.0; @@ -30,12 +27,7 @@ public: /// 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. - virtual void updateMassFlowRate(doublereal time) { - if (m_func) { - m_mdot = m_func->eval(time); - } - m_mdot = std::max(m_mdot, 0.0); - } + virtual void updateMassFlowRate(double time); }; /** @@ -46,9 +38,7 @@ public: class PressureController : public FlowDevice { public: - PressureController() : FlowDevice(), m_master(0) { - m_type = PressureController_Type; - } + PressureController(); virtual bool ready() { return FlowDevice::ready() && m_master != 0 && m_coeffs.size() == 1; @@ -68,15 +58,7 @@ public: m_coeffs = {c}; } - virtual void updateMassFlowRate(doublereal time) { - if (!ready()) { - 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); - } + virtual void updateMassFlowRate(double time); protected: FlowDevice* m_master; @@ -92,9 +74,7 @@ protected: class Valve : public FlowDevice { public: - Valve() : FlowDevice() { - m_type = Valve_Type; - } + Valve(); virtual bool ready() { return FlowDevice::ready() && (m_coeffs.size() == 1 || m_func); @@ -111,19 +91,7 @@ public: } /// 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); - } else { - m_mdot = m_coeffs[0]*delta_P; - } - m_mdot = std::max(m_mdot, 0.0); - } + virtual void updateMassFlowRate(double time); }; } diff --git a/include/cantera/zerodim.h b/include/cantera/zerodim.h index 9a9cc83b1..0a7433373 100644 --- a/include/cantera/zerodim.h +++ b/include/cantera/zerodim.h @@ -1,13 +1,34 @@ +//! @file zerodim.h + +// 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. + #ifndef CT_INCL_ZERODIM_H #define CT_INCL_ZERODIM_H -#include "zeroD/Reactor.h" + +// reactor network #include "zeroD/ReactorNet.h" -#include "zeroD/Reservoir.h" -#include "zeroD/Wall.h" -#include "zeroD/flowControllers.h" -#include "zeroD/FlowReactor.h" -#include "zeroD/ConstPressureReactor.h" -#include "zeroD/IdealGasReactor.h" -#include "zeroD/IdealGasConstPressureReactor.h" + +// reactors +#include "cantera/zeroD/Reservoir.h" +#include "cantera/zeroD/Reactor.h" +#include "cantera/zeroD/FlowReactor.h" +#include "cantera/zeroD/ConstPressureReactor.h" +#include "cantera/zeroD/IdealGasReactor.h" +#include "cantera/zeroD/IdealGasConstPressureReactor.h" + +// flow devices +#include "cantera/zeroD/flowControllers.h" + +// walls +#include "cantera/zeroD/Wall.h" + +// surface +#include "cantera/zeroD/ReactorSurface.h" + +// factories +#include "cantera/zeroD/ReactorFactory.h" +#include "cantera/zeroD/FlowDeviceFactory.h" +#include "cantera/zeroD/WallFactory.h" #endif diff --git a/interfaces/cython/cantera/_cantera.pxd b/interfaces/cython/cantera/_cantera.pxd index 03992e958..1c304ee39 100644 --- a/interfaces/cython/cantera/_cantera.pxd +++ b/interfaces/cython/cantera/_cantera.pxd @@ -1,5 +1,5 @@ # 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. # cython: language_level=3 from libcpp.vector cimport vector @@ -466,11 +466,20 @@ cdef extern from "cantera/equil/MultiPhase.h" namespace "Cantera": double volume() except +translate_exception -cdef extern from "cantera/zeroD/ReactorBase.h" namespace "Cantera": +cdef extern from "cantera/zerodim.h" namespace "Cantera": + cdef cppclass CxxWall "Cantera::Wall" cdef cppclass CxxReactorSurface "Cantera::ReactorSurface" cdef cppclass CxxFlowDevice "Cantera::FlowDevice" + # factories + + cdef CxxReactorBase* newReactor(string) except +translate_exception + cdef CxxFlowDevice* newFlowDevice(string) except +translate_exception + cdef CxxWallBase* newWall(string) except +translate_exception + + # reactors + cdef cppclass CxxReactorBase "Cantera::ReactorBase": CxxReactorBase() void setThermoMgr(CxxThermoPhase&) except +translate_exception @@ -481,8 +490,6 @@ cdef extern from "cantera/zeroD/ReactorBase.h" namespace "Cantera": void setName(string) void setInitialVolume(double) - -cdef extern from "cantera/zeroD/Reactor.h": cdef cppclass CxxReactor "Cantera::Reactor" (CxxReactorBase): CxxReactor() void setKineticsMgr(CxxKinetics&) @@ -500,30 +507,20 @@ cdef extern from "cantera/zeroD/Reactor.h": void addSensitivitySpeciesEnthalpy(size_t) except +translate_exception size_t nSensParams() - -cdef extern from "cantera/zeroD/FlowReactor.h": cdef cppclass CxxFlowReactor "Cantera::FlowReactor" (CxxReactor): CxxFlowReactor() void setMassFlowRate(double) except +translate_exception double speed() double distance() + # walls -cdef extern from "cantera/zeroD/Wall.h": - cdef cppclass CxxWall "Cantera::Wall": - CxxWall() + cdef cppclass CxxWallBase "Cantera::WallBase": + CxxWallBase() + string type() cbool install(CxxReactorBase&, CxxReactorBase&) - void setExpansionRateCoeff(double) - double getExpansionRateCoeff() double area() void setArea(double) - double getArea() - void setHeatTransferCoeff(double) - double getHeatTransferCoeff() - void setEmissivity(double) except +translate_exception - double getEmissivity() - void setVelocity(CxxFunc1*) - void setHeatFlux(CxxFunc1*) void setKinetics(CxxKinetics*, CxxKinetics*) void setCoverages(int, double*) void setCoverages(int, Composition&) except +translate_exception @@ -534,8 +531,19 @@ cdef extern from "cantera/zeroD/Wall.h": void addSensitivityReaction(int, size_t) except +translate_exception size_t nSensParams(int) + cdef cppclass CxxWall "Cantera::Wall" (CxxWallBase): + CxxWall() + void setExpansionRateCoeff(double) + double getExpansionRateCoeff() + void setHeatTransferCoeff(double) + double getHeatTransferCoeff() + void setEmissivity(double) except +translate_exception + double getEmissivity() + void setVelocity(CxxFunc1*) + void setHeatFlux(CxxFunc1*) + + # reactor surface -cdef extern from "cantera/zeroD/ReactorSurface.h": cdef cppclass CxxReactorSurface "Cantera::ReactorSurface": CxxReactorSurface() double area() @@ -547,8 +555,8 @@ cdef extern from "cantera/zeroD/ReactorSurface.h": void addSensitivityReaction(size_t) except +translate_exception size_t nSensParams() + # flow devices -cdef extern from "cantera/zeroD/flowControllers.h": cdef cppclass CxxFlowDevice "Cantera::FlowDevice": CxxFlowDevice() double massFlowRate(double) except +translate_exception @@ -567,8 +575,8 @@ cdef extern from "cantera/zeroD/flowControllers.h": void setPressureCoeff(double) void setMaster(CxxFlowDevice*) + # reactor net -cdef extern from "cantera/zeroD/ReactorNet.h": cdef cppclass CxxReactorNet "Cantera::ReactorNet": CxxReactorNet() void addReactor(CxxReactor&) @@ -612,9 +620,6 @@ cdef extern from "cantera/transport/TransportFactory.h" namespace "Cantera": cdef CxxTransport* newDefaultTransportMgr(CxxThermoPhase*) except +translate_exception cdef CxxTransport* newTransportMgr(string, CxxThermoPhase*) except +translate_exception -cdef extern from "cantera/zeroD/ReactorFactory.h" namespace "Cantera": - cdef CxxReactorBase* newReactor(string) except +translate_exception - cdef extern from "cantera/oneD/Domain1D.h": cdef cppclass CxxDomain1D "Cantera::Domain1D": size_t domainIndex() @@ -974,13 +979,13 @@ cdef class ReactorSurface: cdef Kinetics _kinetics cdef class WallSurface: - cdef CxxWall* cxxwall + cdef CxxWallBase* cxxwall cdef object wall cdef int side cdef Kinetics _kinetics -cdef class Wall: - cdef CxxWall wall +cdef class WallBase: + cdef CxxWallBase* wall cdef WallSurface left_surface cdef WallSurface right_surface cdef object _velocity_func @@ -989,6 +994,9 @@ cdef class Wall: cdef ReactorBase _right_reactor cdef str name +cdef class Wall(WallBase): + pass + cdef class FlowDevice: cdef CxxFlowDevice* dev cdef Func1 _rate_func diff --git a/interfaces/cython/cantera/reactor.pyx b/interfaces/cython/cantera/reactor.pyx index db7730f1f..92302359b 100644 --- a/interfaces/cython/cantera/reactor.pyx +++ b/interfaces/cython/cantera/reactor.pyx @@ -1,5 +1,5 @@ # 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. from collections import defaultdict as _defaultdict import numbers as _numbers @@ -450,33 +450,13 @@ cdef class ReactorSurface: self.surface.addSensitivityReaction(m) -cdef class Wall: - r""" - A Wall separates two reactors, or a reactor and a reservoir. A wall has a - finite area, may conduct or radiate heat between the two reactors on either - side, and may move like a piston. - - Walls are stateless objects in Cantera, meaning that no differential - equation is integrated to determine any wall property. Since it is the wall - (piston) velocity that enters the energy equation, this means that it is - the velocity, not the acceleration or displacement, that is specified. - The wall velocity is computed from - - .. math:: v = K(P_{\rm left} - P_{\rm right}) + v_0(t), - - where :math:`K` is a non-negative constant, and :math:`v_0(t)` is a - specified function of time. The velocity is positive if the wall is - moving to the right. - - The heat flux through the wall is computed from - - .. math:: q = U(T_{\rm left} - T_{\rm right}) + \epsilon\sigma (T_{\rm left}^4 - T_{\rm right}^4) + q_0(t), - - where :math:`U` is the overall heat transfer coefficient for - conduction/convection, and :math:`\epsilon` is the emissivity. The function - :math:`q_0(t)` is a specified function of time. The heat flux is positive - when heat flows from the reactor on the left to the reactor on the right. +cdef class WallBase: """ + Common base class for walls. + """ + wall_type = "None" + def __cinit__(self, *args, **kwargs): + self.wall = newWall(stringify(self.wall_type)) # The signature of this function causes warnings for Sphinx documentation def __init__(self, left, right, *, name=None, A=None, K=None, U=None, @@ -540,6 +520,11 @@ cdef class Wall: self._left_reactor = left self._right_reactor = right + property type: + """ The left surface of this wall. """ + def __get__(self): + return pystr(self.wall.type()) + property left: """ The left surface of this wall. """ def __get__(self): @@ -550,16 +535,6 @@ cdef class Wall: def __get__(self): return self.right_surface - property expansion_rate_coeff: - """ - The coefficient *K* [m/s/Pa] that determines the velocity of the wall - as a function of the pressure difference between the adjacent reactors. - """ - def __get__(self): - return self.wall.getExpansionRateCoeff() - def __set__(self, double val): - self.wall.setExpansionRateCoeff(val) - property area: """ The wall area [m^2]. """ def __get__(self): @@ -567,48 +542,6 @@ cdef class Wall: def __set__(self, double value): self.wall.setArea(value) - property heat_transfer_coeff: - """the overall heat transfer coefficient [W/m^2/K]""" - def __get__(self): - return self.wall.getHeatTransferCoeff() - def __set__(self, double value): - self.wall.setHeatTransferCoeff(value) - - property emissivity: - """The emissivity (nondimensional)""" - def __get__(self): - return self.wall.getEmissivity() - def __set__(self, double value): - self.wall.setEmissivity(value) - - def set_velocity(self, v): - """ - The wall velocity [m/s]. May be either a constant or an arbitrary - function of time. See `Func1`. - """ - cdef Func1 f - if isinstance(v, Func1): - f = v - else: - f = Func1(v) - - self._velocity_func = f - self.wall.setVelocity(f.func) - - def set_heat_flux(self, q): - """ - Heat flux [W/m^2] across the wall. May be either a constant or - an arbitrary function of time. See `Func1`. - """ - cdef Func1 f - if isinstance(q, Func1): - f = q - else: - f = Func1(q) - - self._heat_flux_func = f - self.wall.setHeatFlux(f.func) - def vdot(self, double t): """ The rate of volumetric change [m^3/s] associated with the wall @@ -626,6 +559,88 @@ cdef class Wall: return self.wall.Q(t) +cdef class Wall(WallBase): + r""" + A Wall separates two reactors, or a reactor and a reservoir. A wall has a + finite area, may conduct or radiate heat between the two reactors on either + side, and may move like a piston. + + Walls are stateless objects in Cantera, meaning that no differential + equation is integrated to determine any wall property. Since it is the wall + (piston) velocity that enters the energy equation, this means that it is + the velocity, not the acceleration or displacement, that is specified. + The wall velocity is computed from + + .. math:: v = K(P_{\rm left} - P_{\rm right}) + v_0(t), + + where :math:`K` is a non-negative constant, and :math:`v_0(t)` is a + specified function of time. The velocity is positive if the wall is + moving to the right. + + The heat flux through the wall is computed from + + .. math:: q = U(T_{\rm left} - T_{\rm right}) + \epsilon\sigma (T_{\rm left}^4 - T_{\rm right}^4) + q_0(t), + + where :math:`U` is the overall heat transfer coefficient for + conduction/convection, and :math:`\epsilon` is the emissivity. The function + :math:`q_0(t)` is a specified function of time. The heat flux is positive + when heat flows from the reactor on the left to the reactor on the right. + """ + wall_type = "Wall" + + property expansion_rate_coeff: + """ + The coefficient *K* [m/s/Pa] that determines the velocity of the wall + as a function of the pressure difference between the adjacent reactors. + """ + def __get__(self): + return ((self.wall)).getExpansionRateCoeff() + def __set__(self, double val): + ((self.wall)).setExpansionRateCoeff(val) + + property heat_transfer_coeff: + """the overall heat transfer coefficient [W/m^2/K]""" + def __get__(self): + return ((self.wall)).getHeatTransferCoeff() + def __set__(self, double value): + ((self.wall)).setHeatTransferCoeff(value) + + property emissivity: + """The emissivity (nondimensional)""" + def __get__(self): + return ((self.wall)).getEmissivity() + def __set__(self, double value): + ((self.wall)).setEmissivity(value) + + def set_velocity(self, v): + """ + The wall velocity [m/s]. May be either a constant or an arbitrary + function of time. See `Func1`. + """ + cdef Func1 f + if isinstance(v, Func1): + f = v + else: + f = Func1(v) + + self._velocity_func = f + ((self.wall)).setVelocity(f.func) + + def set_heat_flux(self, q): + """ + Heat flux [W/m^2] across the wall. May be either a constant or + an arbitrary function of time. See `Func1`. + """ + cdef Func1 f + if isinstance(q, Func1): + f = q + else: + f = Func1(q) + + self._heat_flux_func = f + (self.wall).setHeatFlux(f.func) + + cdef class FlowDevice: """ Base class for devices that allow flow between reactors. @@ -637,9 +652,9 @@ cdef class FlowDevice: across a FlowDevice, and the pressure difference equals the difference in pressure between the upstream and downstream reactors. """ + flowdevice_type = "None" def __cinit__(self, *args, **kwargs): - # Children of this abstract class are responsible for allocating dev - self.dev = NULL + self.dev = newFlowDevice(stringify(self.flowdevice_type)) # The signature of this function causes warnings for Sphinx documentation def __init__(self, upstream, downstream, *, name=None): @@ -698,8 +713,7 @@ cdef class MassFlowController(FlowDevice): that this capability should be used with caution, since no account is taken of the work required to do this. """ - def __cinit__(self, *args, **kwargs): - self.dev = new CxxMassFlowController() + flowdevice_type = "MassFlowController" # The signature of this function causes warnings for Sphinx documentation def __init__(self, upstream, downstream, *, name=None, mdot=None): @@ -751,8 +765,7 @@ cdef class Valve(FlowDevice): value, very small pressure differences will result in flow between the reactors that counteracts the pressure difference. """ - def __cinit__(self, *args, **kwargs): - self.dev = new CxxValve() + flowdevice_type = "Valve" # The signature of this function causes warnings for Sphinx documentation def __init__(self, upstream, downstream, *, name=None, K=None): @@ -797,8 +810,7 @@ cdef class PressureController(FlowDevice): .. math:: \dot m = \dot m_{\rm master} + K_v(P_1 - P_2). """ - def __cinit__(self, *args, **kwargs): - self.dev = new CxxPressureController() + flowdevice_type = "PressureController" # The signature of this function causes warnings for Sphinx documentation def __init__(self, upstream, downstream, *, name=None, master=None, K=None): diff --git a/interfaces/cython/cantera/test/test_reactor.py b/interfaces/cython/cantera/test/test_reactor.py index 2e0e67f09..a7f7f201e 100644 --- a/interfaces/cython/cantera/test/test_reactor.py +++ b/interfaces/cython/cantera/test/test_reactor.py @@ -156,6 +156,11 @@ class TestReactor(utilities.CanteraTest): self.assertLessEqual(self.net.time, max_steps * max_step_size) self.assertEqual(self.net.max_steps, max_steps) + def test_wall_type(self): + self.make_reactors(P1=101325, P2=300000) + self.add_wall(K=0.1, A=1.0) + self.assertEqual(self.w.type, "Wall") + def test_equalize_pressure(self): self.make_reactors(P1=101325, P2=300000) self.add_wall(K=0.1, A=1.0) diff --git a/src/clib/ctreactor.cpp b/src/clib/ctreactor.cpp index 7938174e1..80221cf91 100644 --- a/src/clib/ctreactor.cpp +++ b/src/clib/ctreactor.cpp @@ -3,18 +3,14 @@ */ // 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. #define CANTERA_USE_INTERNAL #include "cantera/clib/ctreactor.h" // Cantera includes -#include "cantera/zeroD/Reactor.h" -#include "cantera/zeroD/FlowReactor.h" -#include "cantera/zeroD/ReactorNet.h" -#include "cantera/zeroD/ReactorFactory.h" -#include "cantera/zeroD/Wall.h" -#include "cantera/zeroD/flowControllers.h" +#include "cantera/numerics/Func1.h" +#include "cantera/zerodim.h" #include "Cabinet.h" using namespace Cantera; @@ -23,7 +19,7 @@ using namespace std; typedef Cabinet ReactorCabinet; typedef Cabinet NetworkCabinet; typedef Cabinet FlowDeviceCabinet; -typedef Cabinet WallCabinet; +typedef Cabinet WallCabinet; typedef Cabinet FuncCabinet; typedef Cabinet ThermoCabinet; typedef Cabinet KineticsCabinet; @@ -351,21 +347,8 @@ extern "C" { int flowdev_new(int type) { try { - FlowDevice* r; - switch (type) { - case MFC_Type: - r = new MassFlowController(); - break; - case PressureController_Type: - r = new PressureController(); - break; - case Valve_Type: - r = new Valve(); - break; - default: - r = new FlowDevice(); - } - return FlowDeviceCabinet::add(r); + FlowDevice* f = FlowDeviceFactory::factory()->newFlowDevice(type); + return FlowDeviceCabinet::add(f); } catch (...) { return handleAllExceptions(-1, ERR); } @@ -450,7 +433,8 @@ extern "C" { int wall_new(int type) { try { - return WallCabinet::add(new Wall()); + WallBase* w = WallFactory::factory()->newWall(type); + return WallCabinet::add(w); } catch (...) { return handleAllExceptions(-1, ERR); } @@ -517,7 +501,7 @@ extern "C" { int wall_setThermalResistance(int i, double rth) { try { - WallCabinet::item(i).setThermalResistance(rth); + WallCabinet::get(i).setThermalResistance(rth); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -527,7 +511,7 @@ extern "C" { int wall_setHeatTransferCoeff(int i, double u) { try { - WallCabinet::item(i).setHeatTransferCoeff(u); + WallCabinet::get(i).setHeatTransferCoeff(u); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -537,7 +521,7 @@ extern "C" { int wall_setHeatFlux(int i, int n) { try { - WallCabinet::item(i).setHeatFlux(&FuncCabinet::item(n)); + WallCabinet::get(i).setHeatFlux(&FuncCabinet::item(n)); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -547,7 +531,7 @@ extern "C" { int wall_setExpansionRateCoeff(int i, double k) { try { - WallCabinet::item(i).setExpansionRateCoeff(k); + WallCabinet::get(i).setExpansionRateCoeff(k); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -557,7 +541,7 @@ extern "C" { int wall_setVelocity(int i, int n) { try { - WallCabinet::item(i).setVelocity(&FuncCabinet::item(n)); + WallCabinet::get(i).setVelocity(&FuncCabinet::item(n)); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -567,7 +551,7 @@ extern "C" { int wall_setEmissivity(int i, double epsilon) { try { - WallCabinet::item(i).setEmissivity(epsilon); + WallCabinet::get(i).setEmissivity(epsilon); return 0; } catch (...) { return handleAllExceptions(-1, ERR); diff --git a/src/zeroD/FlowDevice.cpp b/src/zeroD/FlowDevice.cpp index 1d9267501..9a894f79d 100644 --- a/src/zeroD/FlowDevice.cpp +++ b/src/zeroD/FlowDevice.cpp @@ -10,6 +10,10 @@ namespace Cantera { +FlowDevice::FlowDevice() : m_mdot(0.0), m_func(0), m_type(0), + m_nspin(0), m_nspout(0), + m_in(0), m_out(0) {} + bool FlowDevice::install(ReactorBase& in, ReactorBase& out) { if (m_in || m_out) { diff --git a/src/zeroD/FlowDeviceFactory.cpp b/src/zeroD/FlowDeviceFactory.cpp new file mode 100644 index 000000000..5d2743db8 --- /dev/null +++ b/src/zeroD/FlowDeviceFactory.cpp @@ -0,0 +1,43 @@ +//! @file FlowDeviceFactory.cpp + +// 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. + +#include "cantera/zeroD/FlowDeviceFactory.h" +#include "cantera/zeroD/flowControllers.h" + +using namespace std; +namespace Cantera +{ + +FlowDeviceFactory* FlowDeviceFactory::s_factory = 0; +std::mutex FlowDeviceFactory::flowDevice_mutex; + +FlowDeviceFactory::FlowDeviceFactory() +{ + reg("MassFlowController", []() { return new MassFlowController(); }); + reg("PressureController", []() { return new PressureController(); }); + reg("Valve", []() { return new Valve(); }); + + // only used by clib + reg_type("MassFlowController", MFC_Type); + reg_type("PressureController", PressureController_Type); + reg_type("Valve", Valve_Type); +} + +FlowDevice* FlowDeviceFactory::newFlowDevice(const std::string& flowDeviceType) +{ + return create(flowDeviceType); +} + +FlowDevice* FlowDeviceFactory::newFlowDevice(int ir) +{ + try { + return create(m_types.at(ir)); + } catch (out_of_range&) { + throw CanteraError("FlowDeviceFactory::newFlowDevice", + "unknown flowDevice type!"); + } +} + +} diff --git a/src/zeroD/Reactor.cpp b/src/zeroD/Reactor.cpp index 50d3b005c..3ea29d7b9 100644 --- a/src/zeroD/Reactor.cpp +++ b/src/zeroD/Reactor.cpp @@ -1,7 +1,7 @@ //! @file Reactor.cpp A zero-dimensional reactor // 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. #include "cantera/zeroD/Reactor.h" #include "cantera/zeroD/FlowDevice.h" @@ -87,7 +87,7 @@ void Reactor::initialize(doublereal t0) m_intEnergy = m_thermo->intEnergy_mass(); for (size_t n = 0; n < m_wall.size(); n++) { - Wall* W = m_wall[n]; + WallBase* W = m_wall[n]; W->initialize(); } diff --git a/src/zeroD/ReactorBase.cpp b/src/zeroD/ReactorBase.cpp index f0c41850a..edcb7e153 100644 --- a/src/zeroD/ReactorBase.cpp +++ b/src/zeroD/ReactorBase.cpp @@ -1,7 +1,7 @@ //! @file ReactorBase.cpp // 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. #include "cantera/zeroD/ReactorBase.h" #include "cantera/zeroD/FlowDevice.h" @@ -54,7 +54,7 @@ void ReactorBase::addOutlet(FlowDevice& outlet) m_outlet.push_back(&outlet); } -void ReactorBase::addWall(Wall& w, int lr) +void ReactorBase::addWall(WallBase& w, int lr) { m_wall.push_back(&w); if (lr == 0) { @@ -64,7 +64,7 @@ void ReactorBase::addWall(Wall& w, int lr) } } -Wall& ReactorBase::wall(size_t n) +WallBase& ReactorBase::wall(size_t n) { return *m_wall[n]; } diff --git a/src/zeroD/ReactorFactory.cpp b/src/zeroD/ReactorFactory.cpp index d30a08651..771ece1bc 100644 --- a/src/zeroD/ReactorFactory.cpp +++ b/src/zeroD/ReactorFactory.cpp @@ -1,7 +1,7 @@ //! @file ReactorFactory.cpp // 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. #include "cantera/zeroD/ReactorFactory.h" #include "cantera/zeroD/Reservoir.h" @@ -15,6 +15,8 @@ using namespace std; namespace Cantera { +class Reservoir; + ReactorFactory* ReactorFactory::s_factory = 0; std::mutex ReactorFactory::reactor_mutex; @@ -26,6 +28,14 @@ ReactorFactory::ReactorFactory() reg("FlowReactor", []() { return new FlowReactor(); }); reg("IdealGasReactor", []() { return new IdealGasReactor(); }); reg("IdealGasConstPressureReactor", []() { return new IdealGasConstPressureReactor(); }); + + // only used by clib + reg_type("Reservoir", ReservoirType); + reg_type("Reactor", ReactorType); + reg_type("ConstPressureReactor", ConstPressureReactorType); + reg_type("FlowReactor", FlowReactorType); + reg_type("IdealGasReactor", IdealGasReactorType); + reg_type("IdealGasConstPressureReactor", IdealGasConstPressureReactorType); } ReactorBase* ReactorFactory::newReactor(const std::string& reactorType) @@ -33,20 +43,10 @@ ReactorBase* ReactorFactory::newReactor(const std::string& reactorType) return create(reactorType); } - ReactorBase* ReactorFactory::newReactor(int ir) { - static const unordered_map types { - {ReservoirType, "Reservoir"}, - {ReactorType, "Reactor"}, - {ConstPressureReactorType, "ConstPressureReactor"}, - {FlowReactorType, "FlowReactor"}, - {IdealGasReactorType, "IdealGasReactor"}, - {IdealGasConstPressureReactorType, "IdealGasConstPressureReactor"} - }; - try { - return create(types.at(ir)); + return create(m_types.at(ir)); } catch (out_of_range&) { throw CanteraError("ReactorFactory::newReactor", "unknown reactor type!"); diff --git a/src/zeroD/Wall.cpp b/src/zeroD/Wall.cpp index a39251c6d..b43b793bd 100644 --- a/src/zeroD/Wall.cpp +++ b/src/zeroD/Wall.cpp @@ -1,24 +1,19 @@ -//! @file Wall.cpp +//! @file WallBase.cpp // 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. -#include "cantera/zeroD/Wall.h" -#include "cantera/zeroD/ReactorNet.h" -#include "cantera/numerics/Func1.h" -#include "cantera/thermo/SurfPhase.h" #include "cantera/base/stringUtils.h" +#include "cantera/numerics/Func1.h" +#include "cantera/zeroD/Wall.h" +#include "cantera/thermo/SurfPhase.h" namespace Cantera { -Wall::Wall() : m_left(0), m_right(0), - m_surf(2), - m_area(1.0), m_k(0.0), m_rrth(0.0), m_emiss(0.0), - m_vf(0), m_qf(0) -{ -} -bool Wall::install(ReactorBase& rleft, ReactorBase& rright) +WallBase::WallBase() : m_left(0), m_right(0), m_surf(2), m_area(1.0) {} + +bool WallBase::install(ReactorBase& rleft, ReactorBase& rright) { // check if wall is already installed if (m_left || m_right) { @@ -33,16 +28,25 @@ bool Wall::install(ReactorBase& rleft, ReactorBase& rright) return true; } -doublereal Wall::vdot(doublereal t) -{ - double rate1 = m_k * m_area * (m_left->pressure() - m_right->pressure()); - if (m_vf) { - rate1 += m_area * m_vf->eval(t); - } - return rate1; +void WallBase::setArea(double a) { + m_area = a; + m_surf[0].setArea(a); + m_surf[1].setArea(a); } -doublereal Wall::Q(doublereal t) +Wall::Wall() : WallBase(), m_k(0.0), m_rrth(0.0), m_emiss(0.0), m_vf(0), m_qf(0) {} + +double Wall::vdot(double t) +{ + double rate = m_k * m_area * (m_left->pressure() - m_right->pressure()); + + if (m_vf) { + rate += m_area * m_vf->eval(t); + } + return rate; +} + +double Wall::Q(double t) { double q1 = (m_area * m_rrth) * (m_left->temperature() - m_right->temperature()); @@ -51,10 +55,11 @@ doublereal Wall::Q(doublereal t) double tr = m_right->temperature(); q1 += m_emiss * m_area * StefanBoltz * (tl*tl*tl*tl - tr*tr*tr*tr); } + if (m_qf) { q1 += m_area * m_qf->eval(t); } return q1; } - + } diff --git a/src/zeroD/WallFactory.cpp b/src/zeroD/WallFactory.cpp new file mode 100644 index 000000000..decac1b0b --- /dev/null +++ b/src/zeroD/WallFactory.cpp @@ -0,0 +1,39 @@ +//! @file WallFactory.cpp + +// 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. + +#include "cantera/zeroD/WallFactory.h" +#include "cantera/zeroD/Wall.h" + +using namespace std; +namespace Cantera +{ + +WallFactory* WallFactory::s_factory = 0; +std::mutex WallFactory::wall_mutex; + +WallFactory::WallFactory() +{ + reg("Wall", []() { return new Wall(); }); + + // only used by clib + reg_type("Wall", WallType); +} + +WallBase* WallFactory::newWall(const std::string& wallType) +{ + return create(wallType); +} + +WallBase* WallFactory::newWall(int ir) +{ + try { + return create(m_types.at(ir)); + } catch (out_of_range&) { + throw CanteraError("WallFactory::newWall", + "unknown wall type!"); + } +} + +} diff --git a/src/zeroD/flowControllers.cpp b/src/zeroD/flowControllers.cpp new file mode 100644 index 000000000..43b521826 --- /dev/null +++ b/src/zeroD/flowControllers.cpp @@ -0,0 +1,59 @@ +//! @file flowControllers.cpp + +// 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. + +#include "cantera/zeroD/flowControllers.h" +#include "cantera/zeroD/ReactorBase.h" +#include "cantera/numerics/Func1.h" + +namespace Cantera +{ + +MassFlowController::MassFlowController() : FlowDevice() { + m_type = MFC_Type; +} + +void MassFlowController::updateMassFlowRate(double time) +{ + if (m_func) { + m_mdot = m_func->eval(time); + } + m_mdot = std::max(m_mdot, 0.0); +} + +PressureController::PressureController() : FlowDevice(), m_master(0) { + m_type = PressureController_Type; +} + +void PressureController::updateMassFlowRate(double time) +{ + if (!ready()) { + 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); +} + +Valve::Valve() : FlowDevice() { + m_type = Valve_Type; +} + +void Valve::updateMassFlowRate(double 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); + } else { + m_mdot = m_coeffs[0]*delta_P; + } + m_mdot = std::max(m_mdot, 0.0); +} + +}