From f9578bbedd3e3d2531a7943dcbcc6101b43a45ca Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Thu, 22 Aug 2024 08:40:49 -0500 Subject: [PATCH 01/18] [zeroD] Implement Connector base class --- include/cantera/zeroD/ConnectorNode.h | 74 +++++++++++++++++++++++++++ include/cantera/zeroD/FlowDevice.h | 29 ++--------- include/cantera/zeroD/Wall.h | 33 +++--------- src/zeroD/ConnectorNode.cpp | 25 +++++++++ src/zeroD/FlowDevice.cpp | 14 ----- src/zeroD/Wall.cpp | 13 ----- 6 files changed, 109 insertions(+), 79 deletions(-) create mode 100644 include/cantera/zeroD/ConnectorNode.h create mode 100644 src/zeroD/ConnectorNode.cpp diff --git a/include/cantera/zeroD/ConnectorNode.h b/include/cantera/zeroD/ConnectorNode.h new file mode 100644 index 000000000..077c6219a --- /dev/null +++ b/include/cantera/zeroD/ConnectorNode.h @@ -0,0 +1,74 @@ +//! @file ConnectorNode.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_CONNECTOR_H +#define CT_CONNECTOR_H + +#include "cantera/base/ct_defs.h" +#include "cantera/base/global.h" + +namespace Cantera +{ +class ReactorBase; + +/** + * Base class for walls and flow devices connecting reactors. + * In a reactor network, walls and flow devices (e.g., valves, pressure regulators) + * represent nodes in a directed bipartite graph - a graph whose vertices can be + * divided into two disjoint sets such that no two vertices within the same set are + * adjacent - with reactors forming the second set of nodes. + * + * @since New in %Cantera 3.2. + * + * @ingroup connectorGroup + */ +class ConnectorNode +{ +public: + //! Transitional constructor. + //! @todo Implement deprecation warning. + ConnectorNode(const string& name="(none)") : m_name(name) {} + + //! Instantiate a ConnectorNode object with associated ReactorBase objects. + //! @param r0 First reactor. + //! @param r1 Second reactor. + //! @param name Name of the connector. + ConnectorNode(shared_ptr r0, shared_ptr r1, + const string& name="(none)") : m_nodes({r0, r1}), m_name(name) {} + + virtual ~ConnectorNode() = default; + ConnectorNode(const ConnectorNode&) = delete; + ConnectorNode& operator=(const ConnectorNode&) = delete; + + //! String indicating the connector implemented. Usually + //! corresponds to the name of the derived class. + virtual string type() const { + return "ConnectorNode"; + } + + //! Retrieve connector name. + string name() const { + return m_name; + } + + //! Set connector name. + void setName(const string& name) { + m_name = name; + } + + //! Set the default name of a connector. Returns `false` if it was previously set. + void setDefaultName(map& counts); + +protected: + //! Pair of reactors forming end points of the connector. + pair, shared_ptr> m_nodes; + + string m_name; //!< ConnectorNode name. + bool m_defaultNameSet = false; //!< `true` if default name has been previously set. +}; + +} + +#endif diff --git a/include/cantera/zeroD/FlowDevice.h b/include/cantera/zeroD/FlowDevice.h index 00e622b2b..2f53b26af 100644 --- a/include/cantera/zeroD/FlowDevice.h +++ b/include/cantera/zeroD/FlowDevice.h @@ -9,6 +9,7 @@ #include "cantera/base/ct_defs.h" #include "cantera/base/global.h" #include "cantera/base/ctexceptions.h" +#include "ConnectorNode.h" namespace Cantera { @@ -20,34 +21,15 @@ class ReactorBase; * connecting reactors. * @ingroup flowDeviceGroup */ -class FlowDevice +class FlowDevice : public ConnectorNode { public: - FlowDevice(const string& name="(none)") : m_name(name) {} + using ConnectorNode::ConnectorNode; // inherit constructors - virtual ~FlowDevice() = default; - FlowDevice(const FlowDevice&) = delete; - FlowDevice& operator=(const FlowDevice&) = delete; - - //! String indicating the flow device implemented. Usually - //! corresponds to the name of the derived class. - virtual string type() const { + string type() const override { return "FlowDevice"; } - //! Retrieve flow device name. - string name() const { - return m_name; - } - - //! Set flow device name. - void setName(const string& name) { - m_name = name; - } - - //! Set the default name of a flow device. Returns `false` if it was previously set. - bool setDefaultName(map& counts); - //! Mass flow rate (kg/s). double massFlowRate() { if (m_mdot == Undef) { @@ -133,9 +115,6 @@ public: } protected: - string m_name; //!< Flow device name. - bool m_defaultNameSet = false; //!< `true` if default name has been previously set. - double m_mdot = Undef; //! Function set by setPressureFunction; used by updateMassFlowRate diff --git a/include/cantera/zeroD/Wall.h b/include/cantera/zeroD/Wall.h index 14b9dbd03..f5a941ef2 100644 --- a/include/cantera/zeroD/Wall.h +++ b/include/cantera/zeroD/Wall.h @@ -8,6 +8,7 @@ #include "cantera/base/ctexceptions.h" #include "cantera/zeroD/ReactorBase.h" +#include "ConnectorNode.h" namespace Cantera { @@ -16,36 +17,17 @@ class Func1; /** * Base class for 'walls' (walls, pistons, etc.) connecting reactors. - * @ingroup wallGroup + * @ingroup connectorGroup */ -class WallBase +class WallBase : public ConnectorNode { public: - WallBase(const string& name="(none)") : m_name(name) {} + using ConnectorNode::ConnectorNode; // inherit constructors - 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 string type() const { + string type() const override { return "WallBase"; } - //! Retrieve wall name. - string name() const { - return m_name; - } - - //! Set wall name. - void setName(const string& name) { - m_name = name; - } - - //! Set the default name of a wall. Returns `false` if it was previously set. - bool setDefaultName(map& counts); - //! Rate of volume change (m^3/s) for the adjacent reactors at current reactor //! network time. /*! @@ -105,9 +87,6 @@ public: } protected: - string m_name; //!< Wall name. - bool m_defaultNameSet = false; //!< `true` if default name has been previously set. - ReactorBase* m_left = nullptr; ReactorBase* m_right = nullptr; @@ -121,7 +100,7 @@ protected: /*! * Walls can move (changing the volume of the adjacent reactors) and allow heat * transfer between reactors. - * @ingroup wallGroup + * @ingroup connectorGroup */ class Wall : public WallBase { diff --git a/src/zeroD/ConnectorNode.cpp b/src/zeroD/ConnectorNode.cpp new file mode 100644 index 000000000..8dc33d292 --- /dev/null +++ b/src/zeroD/ConnectorNode.cpp @@ -0,0 +1,25 @@ +//! @file ConnectorNode.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/ConnectorNode.h" +#include "cantera/zeroD/ReactorBase.h" + +namespace Cantera +{ + +void ConnectorNode::setDefaultName(map& counts) +{ + if (m_defaultNameSet) { + return; + } + m_defaultNameSet = true; + string typ(type()); + if (m_name == "(none)" || m_name == "") { + m_name = fmt::format("{}_{}", type(), counts[type()]); + } + counts[type()]++; +} + +} diff --git a/src/zeroD/FlowDevice.cpp b/src/zeroD/FlowDevice.cpp index 225d19a44..d298a933c 100644 --- a/src/zeroD/FlowDevice.cpp +++ b/src/zeroD/FlowDevice.cpp @@ -11,20 +11,6 @@ namespace Cantera { -bool FlowDevice::setDefaultName(map& counts) -{ - if (m_defaultNameSet) { - return false; - } - m_defaultNameSet = true; - string typ(type()); - if (m_name == "(none)" || m_name == "") { - m_name = fmt::format("{}_{}", type(), counts[type()]); - } - counts[type()]++; - return true; -} - bool FlowDevice::install(ReactorBase& in, ReactorBase& out) { if (m_in || m_out) { diff --git a/src/zeroD/Wall.cpp b/src/zeroD/Wall.cpp index 2d1d61a81..519e80f85 100644 --- a/src/zeroD/Wall.cpp +++ b/src/zeroD/Wall.cpp @@ -10,19 +10,6 @@ namespace Cantera { -bool WallBase::setDefaultName(map& counts) -{ - if (m_defaultNameSet) { - return false; - } - m_defaultNameSet = true; - if (m_name == "(none)" || m_name == "") { - m_name = fmt::format("{}_{}", type(), counts[type()]); - } - counts[type()]++; - return true; -} - bool WallBase::install(ReactorBase& rleft, ReactorBase& rright) { // check if wall is already installed From 9a9f378334bb8e143bb7c128e2ac8864a29236f0 Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Thu, 22 Aug 2024 09:16:25 -0500 Subject: [PATCH 02/18] [zeroD] Implement ConnectorFactory --- include/cantera/zeroD/ConnectorFactory.h | 68 ++++++++++++++++++++++++ src/zeroD/ConnectorFactory.cpp | 54 +++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 include/cantera/zeroD/ConnectorFactory.h create mode 100644 src/zeroD/ConnectorFactory.cpp diff --git a/include/cantera/zeroD/ConnectorFactory.h b/include/cantera/zeroD/ConnectorFactory.h new file mode 100644 index 000000000..f96f2cd65 --- /dev/null +++ b/include/cantera/zeroD/ConnectorFactory.h @@ -0,0 +1,68 @@ +//! @file ConnectorFactory.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 CONNECTOR_FACTORY_H +#define CONNECTOR_FACTORY_H + +#include "cantera/base/FactoryBase.h" +#include "cantera/zeroD/ConnectorNode.h" + +namespace Cantera +{ + +//! Factory class to create ConnectorNode objects. +//! +//! This class is mainly used via the newConnectorNode() function, for example: +//! +//! ```cpp +//! shared_ptr valve = newConnectorNode("Valve", r0, r1, "my_valve"); +//! ``` +//! +//! where `r0` and `r1` are reactor objects. +class ConnectorFactory : + public Factory, shared_ptr, const string&> +{ +public: + static ConnectorFactory* factory(); + + void deleteFactory() override; + +private: + static ConnectorFactory* s_factory; + static std::mutex connector_mutex; + ConnectorFactory(); +}; + +//! @defgroup connectorGroup Connectors +//! %ConnectorNode objects connect zero-dimensional reactors. +//! ConnectorNode objects should be instantiated via the newConnectorNode() function, +//! for example: +//! +//! ```cpp +//! shared_ptr valve = newConnectorNode("Valve", r0, r1, "my_valve"); +//! ``` +//! +//! where `r0` and `r1` are reactor objects. +//! +//! @since New in %Cantera 3.1. +//! +//! @ingroup zerodGroup +//! @{ + +//! Create a %ConnectorNode object of the specified type +//! @param model String specifying reactor type. +//! @param r0 First reactor. +//! @param r1 Second reactor. +//! @param name Name of the connector. +//! @since New in %Cantera 3.1. +shared_ptr newConnectorNode(const string& model, + shared_ptr r0, + shared_ptr r1, + const string& name="(none)"); + +//! @} +} + +#endif diff --git a/src/zeroD/ConnectorFactory.cpp b/src/zeroD/ConnectorFactory.cpp new file mode 100644 index 000000000..93feb1962 --- /dev/null +++ b/src/zeroD/ConnectorFactory.cpp @@ -0,0 +1,54 @@ +//! @file ConnectorFactory.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/ConnectorFactory.h" +#include "cantera/zeroD/flowControllers.h" +#include "cantera/zeroD/Wall.h" + +namespace Cantera +{ + +ConnectorFactory* ConnectorFactory::s_factory = 0; +std::mutex ConnectorFactory::connector_mutex; + +ConnectorFactory::ConnectorFactory() +{ + reg("MassFlowController", + [](shared_ptr r0, shared_ptr r1, const string& name) + { return new MassFlowController(r0, r1, name); }); + reg("PressureController", + [](shared_ptr r0, shared_ptr r1, const string& name) + { return new PressureController(r0, r1, name); }); + reg("Valve", + [](shared_ptr r0, shared_ptr r1, const string& name) + { return new Valve(r0, r1, name); }); + reg("Wall", + [](shared_ptr r0, shared_ptr r1, const string& name) + { return new Wall(r0, r1, name); }); +} + +ConnectorFactory* ConnectorFactory::factory() { + std::unique_lock lock(connector_mutex); + if (!s_factory) { + s_factory = new ConnectorFactory; + } + return s_factory; +} + +void ConnectorFactory::deleteFactory() { + std::unique_lock lock(connector_mutex); + delete s_factory; + s_factory = 0; +} + +shared_ptr newConnectorNode( + const string& model, + shared_ptr r0, shared_ptr r1, const string& name) +{ + return shared_ptr( + ConnectorFactory::factory()->create(model, r0, r1, name)); +} + +} From 3eba65055095564da5fba5615b826efe0db22329 Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Thu, 22 Aug 2024 09:29:47 -0500 Subject: [PATCH 03/18] [zeroD] Move newFlowDevice to ConnectorFactory --- include/cantera/zeroD/ConnectorFactory.h | 19 +++++--- include/cantera/zeroD/FlowDeviceFactory.h | 53 ----------------------- include/cantera/zerodim.h | 2 +- src/zeroD/ConnectorFactory.cpp | 7 +++ src/zeroD/FlowDeviceFactory.cpp | 47 -------------------- 5 files changed, 21 insertions(+), 107 deletions(-) delete mode 100644 include/cantera/zeroD/FlowDeviceFactory.h delete mode 100644 src/zeroD/FlowDeviceFactory.cpp diff --git a/include/cantera/zeroD/ConnectorFactory.h b/include/cantera/zeroD/ConnectorFactory.h index f96f2cd65..5916b3a6c 100644 --- a/include/cantera/zeroD/ConnectorFactory.h +++ b/include/cantera/zeroD/ConnectorFactory.h @@ -12,6 +12,8 @@ namespace Cantera { +class FlowDevice; + //! Factory class to create ConnectorNode objects. //! //! This class is mainly used via the newConnectorNode() function, for example: @@ -22,7 +24,8 @@ namespace Cantera //! //! where `r0` and `r1` are reactor objects. class ConnectorFactory : - public Factory, shared_ptr, const string&> + public Factory, shared_ptr, const string&> { public: static ConnectorFactory* factory(); @@ -46,7 +49,7 @@ private: //! //! where `r0` and `r1` are reactor objects. //! -//! @since New in %Cantera 3.1. +//! @since New in %Cantera 3.2. //! //! @ingroup zerodGroup //! @{ @@ -56,11 +59,15 @@ private: //! @param r0 First reactor. //! @param r1 Second reactor. //! @param name Name of the connector. -//! @since New in %Cantera 3.1. +//! @since New in %Cantera 3.2. shared_ptr newConnectorNode(const string& model, - shared_ptr r0, - shared_ptr r1, - const string& name="(none)"); + shared_ptr r0, + shared_ptr r1, + const string& name="(none)"); + +//! Create a FlowDevice object of the specified type +//! @since Starting in %Cantera 3.1, this method returns a `shared_ptr` +shared_ptr newFlowDevice(const string& model, const string& name="(none)"); //! @} } diff --git a/include/cantera/zeroD/FlowDeviceFactory.h b/include/cantera/zeroD/FlowDeviceFactory.h deleted file mode 100644 index 28a01bd5f..000000000 --- a/include/cantera/zeroD/FlowDeviceFactory.h +++ /dev/null @@ -1,53 +0,0 @@ -//! @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 -{ - -//! Factory class to create FlowDevice objects. -//! -//! This class is mainly used via the newFlowDevice() function, for example: -//! -//! ```cpp -//! shared_ptr mfc = newFlowDevice("MassFlowController"); -//! ``` -class FlowDeviceFactory : public Factory -{ -public: - static FlowDeviceFactory* factory(); - - void deleteFactory() override; - -private: - static FlowDeviceFactory* s_factory; - static std::mutex flowDevice_mutex; - FlowDeviceFactory(); -}; - -//! @defgroup flowDeviceGroup Flow Devices -//! Flow device objects connect zero-dimensional reactors. -//! FlowDevice objects should be instantiated via the newFlowDevice function, for -//! example: -//! -//! ```cpp -//! shared_ptr mfc = newFlowDevice("MassFlowController", "my_mfc"); -//! ``` -//! @ingroup zerodGroup -//! @{ - -//! Create a FlowDevice object of the specified type -//! @since Starting in %Cantera 3.1, this method returns a `shared_ptr` -shared_ptr newFlowDevice(const string& model, const string& name="(none)"); - -//! @} -} - -#endif diff --git a/include/cantera/zerodim.h b/include/cantera/zerodim.h index eb80929fe..d3111509b 100644 --- a/include/cantera/zerodim.h +++ b/include/cantera/zerodim.h @@ -33,7 +33,7 @@ // factories #include "cantera/zeroD/ReactorFactory.h" -#include "cantera/zeroD/FlowDeviceFactory.h" +#include "cantera/zeroD/ConnectorFactory.h" #include "cantera/zeroD/WallFactory.h" // func1 diff --git a/src/zeroD/ConnectorFactory.cpp b/src/zeroD/ConnectorFactory.cpp index 93feb1962..46376c756 100644 --- a/src/zeroD/ConnectorFactory.cpp +++ b/src/zeroD/ConnectorFactory.cpp @@ -4,6 +4,7 @@ // at https://cantera.org/license.txt for license and copyright information. #include "cantera/zeroD/ConnectorFactory.h" +#include "cantera/zeroD/FlowDevice.h" #include "cantera/zeroD/flowControllers.h" #include "cantera/zeroD/Wall.h" @@ -51,4 +52,10 @@ shared_ptr newConnectorNode( ConnectorFactory::factory()->create(model, r0, r1, name)); } +shared_ptr newFlowDevice(const string& model, const string& name) +{ + return std::dynamic_pointer_cast( + newConnectorNode(model, nullptr, nullptr, name)); +} + } diff --git a/src/zeroD/FlowDeviceFactory.cpp b/src/zeroD/FlowDeviceFactory.cpp deleted file mode 100644 index 9d58a25c3..000000000 --- a/src/zeroD/FlowDeviceFactory.cpp +++ /dev/null @@ -1,47 +0,0 @@ -//! @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" - -namespace Cantera -{ - -FlowDeviceFactory* FlowDeviceFactory::s_factory = 0; -std::mutex FlowDeviceFactory::flowDevice_mutex; - -FlowDeviceFactory::FlowDeviceFactory() -{ - reg("MassFlowController", [](const string& name) { - return new MassFlowController(name); - }); - reg("PressureController", [](const string& name) { - return new PressureController(name); - }); - reg("Valve", [](const string& name) { - return new Valve(name); - }); -} - -FlowDeviceFactory* FlowDeviceFactory::factory() { - std::unique_lock lock(flowDevice_mutex); - if (!s_factory) { - s_factory = new FlowDeviceFactory; - } - return s_factory; -} - -void FlowDeviceFactory::deleteFactory() { - std::unique_lock lock(flowDevice_mutex); - delete s_factory; - s_factory = 0; -} - -shared_ptr newFlowDevice(const string& model, const string& name) -{ - return shared_ptr(FlowDeviceFactory::factory()->create(model, name)); -} - -} From 7659c1e9b4b3c11fd0180d55fc63581faaae65ab Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Thu, 22 Aug 2024 09:44:20 -0500 Subject: [PATCH 04/18] [zeroD] Move newWall to ConnectorFactory fix doxygen for flowdeviceGroup --- include/cantera/zeroD/ConnectorFactory.h | 5 +++ include/cantera/zeroD/FlowDevice.h | 2 +- include/cantera/zeroD/WallFactory.h | 54 ------------------------ include/cantera/zeroD/flowControllers.h | 6 +-- include/cantera/zerodim.h | 1 - src/zeroD/ConnectorFactory.cpp | 18 +++++++- src/zeroD/WallFactory.cpp | 39 ----------------- 7 files changed, 26 insertions(+), 99 deletions(-) delete mode 100644 include/cantera/zeroD/WallFactory.h delete mode 100644 src/zeroD/WallFactory.cpp diff --git a/include/cantera/zeroD/ConnectorFactory.h b/include/cantera/zeroD/ConnectorFactory.h index 5916b3a6c..3a60c8f14 100644 --- a/include/cantera/zeroD/ConnectorFactory.h +++ b/include/cantera/zeroD/ConnectorFactory.h @@ -13,6 +13,7 @@ namespace Cantera { class FlowDevice; +class WallBase; //! Factory class to create ConnectorNode objects. //! @@ -69,6 +70,10 @@ shared_ptr newConnectorNode(const string& model, //! @since Starting in %Cantera 3.1, this method returns a `shared_ptr` shared_ptr newFlowDevice(const string& model, const string& name="(none)"); +//! Create a WallBase object of the specified type +//! @since Starting in %Cantera 3.1, this method returns a `shared_ptr` +shared_ptr newWall(const string& model, const string& name="(none)"); + //! @} } diff --git a/include/cantera/zeroD/FlowDevice.h b/include/cantera/zeroD/FlowDevice.h index 2f53b26af..f4a62e20d 100644 --- a/include/cantera/zeroD/FlowDevice.h +++ b/include/cantera/zeroD/FlowDevice.h @@ -19,7 +19,7 @@ class ReactorBase; /** * Base class for 'flow devices' (valves, pressure regulators, etc.) * connecting reactors. - * @ingroup flowDeviceGroup + * @ingroup connectorGroup */ class FlowDevice : public ConnectorNode { diff --git a/include/cantera/zeroD/WallFactory.h b/include/cantera/zeroD/WallFactory.h deleted file mode 100644 index 13b3c4af4..000000000 --- a/include/cantera/zeroD/WallFactory.h +++ /dev/null @@ -1,54 +0,0 @@ -//! @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 -{ - -//! Factory class to create WallBase objects -//! -//! This class is mainly used via the newWall() function, for example: -//! -//! ```cpp -//! shared_ptr piston = newWall("Wall"); -//! ``` -class WallFactory : public Factory -{ -public: - static WallFactory* factory(); - - void deleteFactory() override; - -private: - static WallFactory* s_factory; - static std::mutex wall_mutex; - WallFactory(); -}; - -//! @defgroup wallGroup Walls -//! Zero-dimensional objects adjacent to reactors. -//! Wall objects should be instantiated via the newWall function, for -//! example: -//! -//! ```cpp -//! shared_ptr piston = newWall("Wall", "my_piston"); -//! ``` -//! @ingroup zerodGroup -//! @{ - -//! Create a WallBase object of the specified type -//! @since Starting in %Cantera 3.1, this method returns a `shared_ptr` -shared_ptr newWall(const string& model, const string& name="(none)"); - -//! @} - -} - -#endif diff --git a/include/cantera/zeroD/flowControllers.h b/include/cantera/zeroD/flowControllers.h index 16c4d4231..2d6c9defc 100644 --- a/include/cantera/zeroD/flowControllers.h +++ b/include/cantera/zeroD/flowControllers.h @@ -15,7 +15,7 @@ namespace Cantera /** * A class for mass flow controllers. The mass flow rate is constant or * specified as a function of time. - * @ingroup flowDeviceGroup + * @ingroup connectorGroup */ class MassFlowController : public FlowDevice { @@ -60,7 +60,7 @@ public: * A class for flow controllers where the flow rate is equal to the flow rate * of a primary mass flow controller plus a correction proportional to the * pressure difference between the inlet and outlet. - * @ingroup flowDeviceGroup + * @ingroup connectorGroup */ class PressureController : public FlowDevice { @@ -118,7 +118,7 @@ protected: * The default behavior is a linearly proportional to the pressure difference. * Note that real valves do not have this behavior, so this class does not * model real, physical valves. - * @ingroup flowDeviceGroup + * @ingroup connectorGroup */ class Valve : public FlowDevice { diff --git a/include/cantera/zerodim.h b/include/cantera/zerodim.h index d3111509b..c62e064d9 100644 --- a/include/cantera/zerodim.h +++ b/include/cantera/zerodim.h @@ -34,7 +34,6 @@ // factories #include "cantera/zeroD/ReactorFactory.h" #include "cantera/zeroD/ConnectorFactory.h" -#include "cantera/zeroD/WallFactory.h" // func1 #include "cantera/numerics/Func1.h" diff --git a/src/zeroD/ConnectorFactory.cpp b/src/zeroD/ConnectorFactory.cpp index 46376c756..b947fbf6a 100644 --- a/src/zeroD/ConnectorFactory.cpp +++ b/src/zeroD/ConnectorFactory.cpp @@ -54,8 +54,24 @@ shared_ptr newConnectorNode( shared_ptr newFlowDevice(const string& model, const string& name) { - return std::dynamic_pointer_cast( + auto dev = std::dynamic_pointer_cast( newConnectorNode(model, nullptr, nullptr, name)); + if (!dev) { + throw CanteraError("newFlowDevice", + "Detected incompatible ConnectorNode type '{}'", model); + } + return dev; +} + +shared_ptr newWall(const string& model, const string& name) +{ + auto wall = std::dynamic_pointer_cast( + newConnectorNode(model, nullptr, nullptr, name)); + if (!wall) { + throw CanteraError("newWall", + "Detected incompatible ConnectorNode type '{}'", model); + } + return wall; } } diff --git a/src/zeroD/WallFactory.cpp b/src/zeroD/WallFactory.cpp deleted file mode 100644 index 1c2b0ac06..000000000 --- a/src/zeroD/WallFactory.cpp +++ /dev/null @@ -1,39 +0,0 @@ -//! @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" - -namespace Cantera -{ - -WallFactory* WallFactory::s_factory = 0; -std::mutex WallFactory::wall_mutex; - -WallFactory::WallFactory() -{ - reg("Wall", [](const string& name) { return new Wall(name); }); -} - -WallFactory* WallFactory::factory() { - std::unique_lock lock(wall_mutex); - if (!s_factory) { - s_factory = new WallFactory; - } - return s_factory; -} - -void WallFactory::deleteFactory() { - std::unique_lock lock(wall_mutex); - delete s_factory; - s_factory = 0; -} - -shared_ptr newWall(const string& model, const string& name) -{ - return shared_ptr(WallFactory::factory()->create(model, name)); -} - -} From f5455271c228ac8a635b4a7af5b1ccc67dd587fb Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Thu, 22 Aug 2024 10:19:49 -0500 Subject: [PATCH 05/18] [clib] Switch to ConnectorCabinet --- src/clib/ctreactor.cpp | 73 +++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/src/clib/ctreactor.cpp b/src/clib/ctreactor.cpp index 493b459b0..804faae8d 100644 --- a/src/clib/ctreactor.cpp +++ b/src/clib/ctreactor.cpp @@ -19,8 +19,7 @@ using namespace Cantera; typedef Cabinet ReactorCabinet; typedef Cabinet NetworkCabinet; -typedef Cabinet FlowDeviceCabinet; -typedef Cabinet WallCabinet; +typedef Cabinet ConnectorCabinet; typedef Cabinet FuncCabinet; typedef Cabinet ThermoCabinet; typedef Cabinet KineticsCabinet; @@ -29,8 +28,7 @@ typedef Cabinet ReactorSurfaceCabinet; template<> ReactorCabinet* ReactorCabinet::s_storage = 0; template<> NetworkCabinet* NetworkCabinet::s_storage = 0; -template<> FlowDeviceCabinet* FlowDeviceCabinet::s_storage = 0; -template<> WallCabinet* WallCabinet::s_storage = 0; +template<> ConnectorCabinet* ConnectorCabinet::s_storage = 0; template<> ReactorSurfaceCabinet* ReactorSurfaceCabinet::s_storage = 0; template<> FuncCabinet* FuncCabinet::s_storage; // defined in ctfunc.cpp template<> ThermoCabinet* ThermoCabinet::s_storage; // defined in ct.cpp @@ -353,7 +351,7 @@ extern "C" { int flowdev_new(const char* type, const char* name) { try { - return FlowDeviceCabinet::add(newFlowDevice(type, name)); + return ConnectorCabinet::add(newFlowDevice(type, name)); } catch (...) { return handleAllExceptions(-1, ERR); } @@ -362,7 +360,7 @@ extern "C" { int flowdev_del(int i) { try { - FlowDeviceCabinet::del(i); + ConnectorCabinet::del(i); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -373,7 +371,7 @@ extern "C" { { try { return static_cast( - copyString(FlowDeviceCabinet::at(i)->name(), nbuf, len)); + copyString(ConnectorCabinet::at(i)->name(), nbuf, len)); } catch (...) { return handleAllExceptions(-1, ERR); } @@ -382,7 +380,7 @@ extern "C" { int flowdev_setName(int i, const char* name) { try { - FlowDeviceCabinet::at(i)->setName(name); + ConnectorCabinet::at(i)->setName(name); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -392,8 +390,8 @@ extern "C" { int flowdev_install(int i, int n, int m) { try { - bool ok = FlowDeviceCabinet::at(i)->install(*ReactorCabinet::at(n), - *ReactorCabinet::at(m)); + bool ok = ConnectorCabinet::as(i)->install( + *ReactorCabinet::at(n), *ReactorCabinet::at(m)); if (!ok) { throw CanteraError("flowdev_install", "Could not install flow device."); @@ -407,8 +405,8 @@ extern "C" { int flowdev_setPrimary(int i, int n) { try { - FlowDeviceCabinet::as(i)->setPrimary( - FlowDeviceCabinet::at(n).get()); + ConnectorCabinet::as(i)->setPrimary( + ConnectorCabinet::as(n).get()); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -418,7 +416,7 @@ extern "C" { double flowdev_massFlowRate(int i) { try { - return FlowDeviceCabinet::at(i)->massFlowRate(); + return ConnectorCabinet::as(i)->massFlowRate(); } catch (...) { return handleAllExceptions(DERR, DERR); } @@ -427,7 +425,7 @@ extern "C" { int flowdev_setMassFlowCoeff(int i, double v) { try { - FlowDeviceCabinet::as(i)->setMassFlowCoeff(v); + ConnectorCabinet::as(i)->setMassFlowCoeff(v); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -437,7 +435,7 @@ extern "C" { int flowdev_setValveCoeff(int i, double v) { try { - FlowDeviceCabinet::as(i)->setValveCoeff(v); + ConnectorCabinet::as(i)->setValveCoeff(v); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -447,7 +445,7 @@ extern "C" { int flowdev_setPressureCoeff(int i, double v) { try { - FlowDeviceCabinet::as(i)->setPressureCoeff(v); + ConnectorCabinet::as(i)->setPressureCoeff(v); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -457,7 +455,8 @@ extern "C" { int flowdev_setPressureFunction(int i, int n) { try { - FlowDeviceCabinet::at(i)->setPressureFunction(FuncCabinet::at(n).get()); + ConnectorCabinet::as(i)->setPressureFunction( + FuncCabinet::at(n).get()); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -467,7 +466,8 @@ extern "C" { int flowdev_setTimeFunction(int i, int n) { try { - FlowDeviceCabinet::at(i)->setTimeFunction(FuncCabinet::at(n).get()); + ConnectorCabinet::as(i)->setTimeFunction( + FuncCabinet::at(n).get()); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -479,7 +479,7 @@ extern "C" { int wall_new(const char* type, const char* name) { try { - return WallCabinet::add(newWall(type, name)); + return ConnectorCabinet::add(newWall(type, name)); } catch (...) { return handleAllExceptions(-1, ERR); } @@ -488,7 +488,7 @@ extern "C" { int wall_del(int i) { try { - WallCabinet::del(i); + ConnectorCabinet::del(i); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -499,7 +499,7 @@ extern "C" { { try { return static_cast( - copyString(WallCabinet::at(i)->name(), nbuf, len)); + copyString(ConnectorCabinet::at(i)->name(), nbuf, len)); } catch (...) { return handleAllExceptions(-1, ERR); } @@ -508,7 +508,7 @@ extern "C" { int wall_setName(int i, const char* name) { try { - WallCabinet::at(i)->setName(name); + ConnectorCabinet::at(i)->setName(name); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -518,8 +518,8 @@ extern "C" { int wall_install(int i, int n, int m) { try { - WallCabinet::at(i)->install(*ReactorCabinet::at(n), - *ReactorCabinet::at(m)); + ConnectorCabinet::as(i)->install( + *ReactorCabinet::at(n), *ReactorCabinet::at(m)); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -529,7 +529,7 @@ extern "C" { double wall_expansionRate(int i) { try { - return WallCabinet::at(i)->expansionRate(); + return ConnectorCabinet::as(i)->expansionRate(); } catch (...) { return handleAllExceptions(DERR, DERR); } @@ -538,7 +538,7 @@ extern "C" { double wall_heatRate(int i) { try { - return WallCabinet::at(i)->heatRate(); + return ConnectorCabinet::as(i)->heatRate(); } catch (...) { return handleAllExceptions(DERR, DERR); } @@ -547,7 +547,7 @@ extern "C" { double wall_area(int i) { try { - return WallCabinet::at(i)->area(); + return ConnectorCabinet::as(i)->area(); } catch (...) { return handleAllExceptions(DERR, DERR); } @@ -556,7 +556,7 @@ extern "C" { int wall_setArea(int i, double v) { try { - WallCabinet::at(i)->setArea(v); + ConnectorCabinet::as(i)->setArea(v); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -566,7 +566,7 @@ extern "C" { int wall_setThermalResistance(int i, double rth) { try { - WallCabinet::as(i)->setThermalResistance(rth); + ConnectorCabinet::as(i)->setThermalResistance(rth); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -576,7 +576,7 @@ extern "C" { int wall_setHeatTransferCoeff(int i, double u) { try { - WallCabinet::as(i)->setHeatTransferCoeff(u); + ConnectorCabinet::as(i)->setHeatTransferCoeff(u); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -586,7 +586,7 @@ extern "C" { int wall_setHeatFlux(int i, int n) { try { - WallCabinet::as(i)->setHeatFlux(FuncCabinet::at(n).get()); + ConnectorCabinet::as(i)->setHeatFlux(FuncCabinet::at(n).get()); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -596,7 +596,7 @@ extern "C" { int wall_setExpansionRateCoeff(int i, double k) { try { - WallCabinet::as(i)->setExpansionRateCoeff(k); + ConnectorCabinet::as(i)->setExpansionRateCoeff(k); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -606,7 +606,7 @@ extern "C" { int wall_setVelocity(int i, int n) { try { - WallCabinet::as(i)->setVelocity(FuncCabinet::at(n).get()); + ConnectorCabinet::as(i)->setVelocity(FuncCabinet::at(n).get()); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -616,7 +616,7 @@ extern "C" { int wall_setEmissivity(int i, double epsilon) { try { - WallCabinet::as(i)->setEmissivity(epsilon); + ConnectorCabinet::as(i)->setEmissivity(epsilon); return 0; } catch (...) { return handleAllExceptions(-1, ERR); @@ -626,7 +626,7 @@ extern "C" { int wall_ready(int i) { try { - return int(WallCabinet::at(i)->ready()); + return int(ConnectorCabinet::as(i)->ready()); } catch (...) { return handleAllExceptions(-1, ERR); } @@ -727,8 +727,7 @@ extern "C" { try { ReactorCabinet::clear(); NetworkCabinet::clear(); - FlowDeviceCabinet::clear(); - WallCabinet::clear(); + ConnectorCabinet::clear(); ReactorSurfaceCabinet::clear(); return 0; } catch (...) { From ad81e209e7baf7d724263d3358f31ab95de41c7a Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Thu, 22 Aug 2024 17:05:47 -0500 Subject: [PATCH 06/18] [zeroD] Add deprecations --- include/cantera/zeroD/ReactorBase.h | 2 ++ src/zeroD/ConnectorFactory.cpp | 4 ++++ src/zeroD/Reactor.cpp | 8 +------- src/zeroD/ReactorBase.cpp | 15 +++++++++++++-- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/include/cantera/zeroD/ReactorBase.h b/include/cantera/zeroD/ReactorBase.h index c04847127..b343a8889 100644 --- a/include/cantera/zeroD/ReactorBase.h +++ b/include/cantera/zeroD/ReactorBase.h @@ -80,6 +80,8 @@ public: //! Set the Solution specifying the ReactorBase content. //! @param sol Solution object to be set. //! @since New in %Cantera 3.1. + //! @deprecated To be removed after %Cantera 3.2. Superseded by instantiation of + //! ReactorBase with Solution object. void setSolution(shared_ptr sol); //! @name Methods to set up a simulation diff --git a/src/zeroD/ConnectorFactory.cpp b/src/zeroD/ConnectorFactory.cpp index b947fbf6a..e48012810 100644 --- a/src/zeroD/ConnectorFactory.cpp +++ b/src/zeroD/ConnectorFactory.cpp @@ -48,6 +48,10 @@ shared_ptr newConnectorNode( const string& model, shared_ptr r0, shared_ptr r1, const string& name) { + if (!r0 || !r1) { + warn_deprecated("newConnectorNode", + "Instantiation of empty connector nodes to be removed after Cantera 3.2."); + } return shared_ptr( ConnectorFactory::factory()->create(model, r0, r1, name)); } diff --git a/src/zeroD/Reactor.cpp b/src/zeroD/Reactor.cpp index 8777010d9..7fac0ecba 100644 --- a/src/zeroD/Reactor.cpp +++ b/src/zeroD/Reactor.cpp @@ -23,14 +23,8 @@ namespace Cantera { Reactor::Reactor(shared_ptr sol, const string& name) - : ReactorBase(name) + : ReactorBase(sol, name) { - if (!sol || !(sol->thermo())) { - throw CanteraError("Reactor::Reactor", - "Reactor contents must be provided as constructor arguments"); - } - setSolution(sol); - setThermo(*sol->thermo()); setKinetics(*sol->kinetics()); } diff --git a/src/zeroD/ReactorBase.cpp b/src/zeroD/ReactorBase.cpp index 45d4a86ca..6fa0a13d8 100644 --- a/src/zeroD/ReactorBase.cpp +++ b/src/zeroD/ReactorBase.cpp @@ -24,7 +24,14 @@ ReactorBase::ReactorBase(shared_ptr sol, const string& name) throw CanteraError("ReactorBase::ReactorBase", "Missing or incomplete Solution object."); } - setSolution(sol); + m_solution = sol; + setThermo(*sol->thermo()); + try { + setKinetics(*sol->kinetics()); + } catch (NotImplementedError&) { + // kinetics not used (example: Reservoir) + } + m_solution->thermo()->addSpeciesLock(); } ReactorBase::~ReactorBase() @@ -47,7 +54,11 @@ bool ReactorBase::setDefaultName(map& counts) return true; } -void ReactorBase::setSolution(shared_ptr sol) { +void ReactorBase::setSolution(shared_ptr sol) +{ + warn_deprecated("ReactorBase::setSolution", + "After Cantera 3.2, a change of reactor contents after instantiation " + "will be disabled."); if (!sol || !(sol->thermo())) { throw CanteraError("ReactorBase::setSolution", "Missing or incomplete Solution object."); From 7a6cc9a28f142b9e7dd6bb5aa55c7c0896dbe77d Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Thu, 22 Aug 2024 17:37:44 -0500 Subject: [PATCH 07/18] [zeroD] Install Reactors when instantiating connectors --- include/cantera/zeroD/FlowDevice.h | 4 ++++ include/cantera/zeroD/Wall.h | 4 ++++ src/zeroD/ConnectorFactory.cpp | 4 ---- src/zeroD/FlowDevice.cpp | 37 ++++++++++++++++++++++++++++++ src/zeroD/Wall.cpp | 18 +++++++++++++++ 5 files changed, 63 insertions(+), 4 deletions(-) diff --git a/include/cantera/zeroD/FlowDevice.h b/include/cantera/zeroD/FlowDevice.h index f4a62e20d..aac16f58f 100644 --- a/include/cantera/zeroD/FlowDevice.h +++ b/include/cantera/zeroD/FlowDevice.h @@ -24,6 +24,8 @@ class ReactorBase; class FlowDevice : public ConnectorNode { public: + FlowDevice(shared_ptr r0, shared_ptr r1, + const string& name="(none)"); using ConnectorNode::ConnectorNode; // inherit constructors string type() const override { @@ -55,6 +57,8 @@ public: /*! * @param in Upstream reactor. * @param out Downstream reactor. + * @deprecated To be removed after Cantera 3.2. Reactors should be provided to + * constructor instead. */ bool install(ReactorBase& in, ReactorBase& out); diff --git a/include/cantera/zeroD/Wall.h b/include/cantera/zeroD/Wall.h index f5a941ef2..3e5269077 100644 --- a/include/cantera/zeroD/Wall.h +++ b/include/cantera/zeroD/Wall.h @@ -22,6 +22,8 @@ class Func1; class WallBase : public ConnectorNode { public: + WallBase(shared_ptr r0, shared_ptr r1, + const string& name="(none)"); using ConnectorNode::ConnectorNode; // inherit constructors string type() const override { @@ -58,6 +60,8 @@ public: virtual void setArea(double a); //! Install the wall between two reactors or reservoirs + //! @deprecated To be removed after Cantera 3.2. Reactors should be provided to + //! constructor instead. bool install(ReactorBase& leftReactor, ReactorBase& rightReactor); //! Called just before the start of integration diff --git a/src/zeroD/ConnectorFactory.cpp b/src/zeroD/ConnectorFactory.cpp index e48012810..b947fbf6a 100644 --- a/src/zeroD/ConnectorFactory.cpp +++ b/src/zeroD/ConnectorFactory.cpp @@ -48,10 +48,6 @@ shared_ptr newConnectorNode( const string& model, shared_ptr r0, shared_ptr r1, const string& name) { - if (!r0 || !r1) { - warn_deprecated("newConnectorNode", - "Instantiation of empty connector nodes to be removed after Cantera 3.2."); - } return shared_ptr( ConnectorFactory::factory()->create(model, r0, r1, name)); } diff --git a/src/zeroD/FlowDevice.cpp b/src/zeroD/FlowDevice.cpp index d298a933c..34903390e 100644 --- a/src/zeroD/FlowDevice.cpp +++ b/src/zeroD/FlowDevice.cpp @@ -11,8 +11,45 @@ namespace Cantera { +FlowDevice::FlowDevice(shared_ptr r0, shared_ptr r1, + const string& name) : ConnectorNode(r0, r1, name) +{ + if (!m_nodes.first || !m_nodes.second) { + warn_deprecated("FlowDevice::FlowDevice", + "After Cantera 3.1, Reactors must be provided to a FlowDevice " + "constructor."); + return; + } + m_in = r0.get(); + m_out = r1.get(); + m_in->addOutlet(*this); + m_out->addInlet(*this); + + // construct adapters between inlet and outlet species + const ThermoPhase& mixin = m_in->contents(); + const ThermoPhase& mixout = m_out->contents(); + + m_nspin = mixin.nSpecies(); + m_nspout = mixout.nSpecies(); + string nm; + size_t ki, ko; + for (ki = 0; ki < m_nspin; ki++) { + nm = mixin.speciesName(ki); + ko = mixout.speciesIndex(nm); + m_in2out.push_back(ko); + } + for (ko = 0; ko < m_nspout; ko++) { + nm = mixout.speciesName(ko); + ki = mixin.speciesIndex(nm); + m_out2in.push_back(ki); + } +} + bool FlowDevice::install(ReactorBase& in, ReactorBase& out) { + warn_deprecated("FlowDevice::install", + "To be removed after Cantera 3.1. Reactors should be provided to constructor " + "instead."); if (m_in || m_out) { throw CanteraError("FlowDevice::install", "Already installed"); } diff --git a/src/zeroD/Wall.cpp b/src/zeroD/Wall.cpp index 519e80f85..9d638c328 100644 --- a/src/zeroD/Wall.cpp +++ b/src/zeroD/Wall.cpp @@ -10,8 +10,26 @@ namespace Cantera { +WallBase::WallBase(shared_ptr r0, shared_ptr r1, + const string& name) : ConnectorNode(r0, r1, name) +{ + if (!m_nodes.first || !m_nodes.second) { + warn_deprecated("FlowDevice::FlowDevice", + "After Cantera 3.2, Reactors must be provided to a FlowDevice " + "constructor."); + return; + } + m_left = r0.get(); + m_right = r1.get(); + m_left->addWall(*this, 0); + m_right->addWall(*this, 1); +} + bool WallBase::install(ReactorBase& rleft, ReactorBase& rright) { + warn_deprecated("WallBase::install", + "To be removed after Cantera 3.2. Reactors should be provided to constructor " + "instead."); // check if wall is already installed if (m_left || m_right) { return false; From b057dab41c57640267f9b22fc25eb4451b1b25b8 Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Thu, 22 Aug 2024 16:01:19 -0500 Subject: [PATCH 08/18] [Python] Derive Wall/FlowDevice from ConnectorNode --- interfaces/cython/cantera/reactor.pxd | 123 ++++++++++++------------- interfaces/cython/cantera/reactor.pyx | 126 +++++++++++++------------- 2 files changed, 122 insertions(+), 127 deletions(-) diff --git a/interfaces/cython/cantera/reactor.pxd b/interfaces/cython/cantera/reactor.pxd index 670cd4373..442c95156 100644 --- a/interfaces/cython/cantera/reactor.pxd +++ b/interfaces/cython/cantera/reactor.pxd @@ -32,12 +32,11 @@ cdef extern from "cantera/zerodim.h" namespace "Cantera": # factories cdef shared_ptr[CxxReactorBase] newReactor(string) except +translate_exception cdef shared_ptr[CxxReactorBase] newReactor(string, shared_ptr[CxxSolution], string) except +translate_exception - cdef shared_ptr[CxxFlowDevice] newFlowDevice(string, string) except +translate_exception - cdef shared_ptr[CxxWallBase] newWall(string, string) except +translate_exception + cdef shared_ptr[CxxConnectorNode] newConnectorNode(string, shared_ptr[CxxReactorBase], shared_ptr[CxxReactorBase], string) except +translate_exception # reactors cdef cppclass CxxReactorBase "Cantera::ReactorBase": - CxxReactorBase() + CxxReactorBase() except +translate_exception string type() void setSolution(shared_ptr[CxxSolution]) except +translate_exception void restoreState() except +translate_exception @@ -48,7 +47,7 @@ cdef extern from "cantera/zerodim.h" namespace "Cantera": void setInitialVolume(double) cdef cppclass CxxReactor "Cantera::Reactor" (CxxReactorBase): - CxxReactor() + CxxReactor() except +translate_exception void setChemistry(cbool) cbool chemistryEnabled() void setEnergy(int) @@ -59,7 +58,7 @@ cdef extern from "cantera/zerodim.h" namespace "Cantera": void getState(double*) except +translate_exception CxxSparseMatrix jacobian() except +translate_exception CxxSparseMatrix finiteDifferenceJacobian() except +translate_exception - void addSurface(CxxReactorSurface*) + void addSurface(CxxReactorSurface*) except +translate_exception void setAdvanceLimit(string&, double) except +translate_exception void addSensitivityReaction(size_t) except +translate_exception void addSensitivitySpeciesEnthalpy(size_t) except +translate_exception @@ -82,40 +81,6 @@ cdef extern from "cantera/zerodim.h" namespace "Cantera": int inletSurfaceMaxErrorFailures() void setInletSurfaceMaxErrorFailures(int) except +translate_exception - # walls - cdef cppclass CxxWallBase "Cantera::WallBase": - CxxWallBase() - string type() - string name() - void setName(string) except +translate_exception - cbool install(CxxReactorBase&, CxxReactorBase&) - double area() - void setArea(double) - void setKinetics(CxxKinetics*, CxxKinetics*) - void setCoverages(int, double*) - void setCoverages(int, Composition&) except +translate_exception - void syncCoverages(int) - double expansionRate() except +translate_exception - double vdot(double) except +translate_exception - double heatRate() except +translate_exception - double Q(double) except +translate_exception - - 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() - double velocity() - void setVelocity(CxxFunc1*) - double heatFlux() - void setHeatFlux(CxxFunc1*) - # reactor surface cdef cppclass CxxReactorSurface "Cantera::ReactorSurface": @@ -132,25 +97,59 @@ cdef extern from "cantera/zerodim.h" namespace "Cantera": void addSensitivityReaction(size_t) except +translate_exception size_t nSensParams() - # flow devices + # connectors - cdef cppclass CxxFlowDevice "Cantera::FlowDevice": - CxxFlowDevice() + cdef cppclass CxxConnectorNode "Cantera::ConnectorNode": + CxxConnectorNode() except +translate_exception string type() string name() void setName(string) except +translate_exception + + # walls + cdef cppclass CxxWallBase "Cantera::WallBase" (CxxConnectorNode ): + CxxWallBase() except +translate_exception + double area() + void setArea(double) + void setKinetics(CxxKinetics*, CxxKinetics*) + void setCoverages(int, double*) + void setCoverages(int, Composition&) except +translate_exception + void syncCoverages(int) + double expansionRate() except +translate_exception + double vdot(double) except +translate_exception + double heatRate() except +translate_exception + double Q(double) except +translate_exception + + void addSensitivityReaction(int, size_t) except +translate_exception + size_t nSensParams(int) + + cdef cppclass CxxWall "Cantera::Wall" (CxxWallBase): + CxxWall() except +translate_exception + void setExpansionRateCoeff(double) + double getExpansionRateCoeff() + void setHeatTransferCoeff(double) + double getHeatTransferCoeff() + void setEmissivity(double) except +translate_exception + double getEmissivity() + double velocity() + void setVelocity(CxxFunc1*) + double heatFlux() + void setHeatFlux(CxxFunc1*) + + # flow devices + + cdef cppclass CxxFlowDevice "Cantera::FlowDevice" (CxxConnectorNode): + CxxFlowDevice() except +translate_exception double massFlowRate() except +translate_exception double massFlowRate(double) except +translate_exception - cbool install(CxxReactorBase&, CxxReactorBase&) except +translate_exception double evalPressureFunction() except +translate_exception void setPressureFunction(CxxFunc1*) except +translate_exception double evalTimeFunction() except +translate_exception void setTimeFunction(CxxFunc1*) except +translate_exception cdef cppclass CxxMassFlowController "Cantera::MassFlowController" (CxxFlowDevice): - CxxMassFlowController() - void setMassFlowRate(double) - void setMassFlowCoeff(double) + CxxMassFlowController() except +translate_exception + void setMassFlowRate(double) except +translate_exception + void setMassFlowCoeff(double) except +translate_exception double getMassFlowCoeff() cdef cppclass CxxValve "Cantera::Valve" (CxxFlowDevice): @@ -289,14 +288,9 @@ cdef class ReactorSurface: .. versionadded:: 3.1 """ -cdef class WallBase: - cdef shared_ptr[CxxWallBase] _wall - cdef CxxWallBase* wall - cdef object _velocity_func - cdef object _heat_flux_func - cdef ReactorBase _left_reactor - cdef ReactorBase _right_reactor - cdef str name +cdef class ConnectorNode: + cdef shared_ptr[CxxConnectorNode] _node + cdef CxxConnectorNode* node cdef public dict edge_attr """ A dictionary containing draw attributes for the representation of the `WallBase` as @@ -306,25 +300,24 @@ cdef class WallBase: .. versionadded:: 3.1 """ +cdef class WallBase(ConnectorNode): + # cdef shared_ptr[CxxWallBase] _wall + cdef CxxWallBase* wall + cdef object _velocity_func + cdef object _heat_flux_func + cdef ReactorBase _left_reactor + cdef ReactorBase _right_reactor + cdef class Wall(WallBase): pass -cdef class FlowDevice: - cdef shared_ptr[CxxFlowDevice] _dev +cdef class FlowDevice(ConnectorNode): + # cdef shared_ptr[CxxFlowDevice] _dev cdef CxxFlowDevice* dev cdef Func1 _rate_func cdef Func1 _time_func - cdef str name cdef ReactorBase _upstream cdef ReactorBase _downstream - cdef public dict edge_attr - """ - A dictionary containing draw attributes for the representation of the `FlowDevice` - as a graphviz edge.See https://graphviz.org/docs/edges/ for a list of all usable - attributes. - - .. versionadded:: 3.1 - """ cdef class MassFlowController(FlowDevice): pass diff --git a/interfaces/cython/cantera/reactor.pyx b/interfaces/cython/cantera/reactor.pyx index 1da8be2e9..03a057946 100644 --- a/interfaces/cython/cantera/reactor.pyx +++ b/interfaces/cython/cantera/reactor.pyx @@ -28,7 +28,7 @@ cdef class ReactorBase: self._walls = [] self._surfaces = [] if isinstance(contents, _SolutionBase): - self.insert(contents) # leave insert for the time being + self._thermo = contents if volume is not None: self.volume = volume @@ -39,9 +39,14 @@ cdef class ReactorBase: """ Set ``solution`` to be the object used to compute thermodynamic properties and kinetic rates for this reactor. + + .. deprecated:: 3.2 + + After Cantera 3.2, a change of reactor contents after instantiation + will be disabled. """ self._thermo = solution - self.rbase.setSolution(solution._base) + self.rbase.setSolution(solution._base) # raises warning in C++ core property type: """The type of the reactor.""" @@ -939,14 +944,52 @@ cdef class ReactorSurface: self.surface.addSensitivityReaction(m) -cdef class WallBase: +cdef class ConnectorNode: + """ + Common base class for walls and flow devices. + """ + node_type = "none" + + def __cinit__(self, ReactorBase left=None, ReactorBase right=None, *, + ReactorBase upstream=None, ReactorBase downstream=None, + name="(none)", **kwargs): + # ensure that both naming conventions (Wall and FlowDevice) are covered + cdef ReactorBase r0 = left or upstream + cdef ReactorBase r1 = right or downstream + if isinstance(r0, ReactorBase) and isinstance(r1, ReactorBase): + self._node = newConnectorNode(stringify(self.node_type), + r0._reactor, r1._reactor, stringify(name)) + self.node = self._node.get() + return + raise TypeError(f"Invalid reactor types: {r0} and {r1}.") + + @property + def type(self): + """The type of the connector.""" + return pystr(self.node.type()) + + @property + def name(self): + """The name of the connector.""" + return pystr(self.node.name()) + + @name.setter + def name(self, name): + self.node.setName(stringify(name)) + + def __reduce__(self): + raise NotImplementedError('Reactor object is not picklable') + + def __copy__(self): + raise NotImplementedError('Reactor object is not copyable') + + +cdef class WallBase(ConnectorNode): """ Common base class for walls. """ - wall_type = "none" - def __cinit__(self, *args, name="(none)", **kwargs): - self._wall = newWall(stringify(self.wall_type), stringify(name)) - self.wall = self._wall.get() + def __cinit__(self, *args, **kwargs): + self.wall = (self.node) def __init__(self, left, right, *, name="(none)", A=None, K=None, U=None, Q=None, velocity=None, edge_attr=None): @@ -985,8 +1028,6 @@ cdef class WallBase: self._velocity_func = None self._heat_flux_func = None - self._install(left, right) - if A is not None: self.area = A if K is not None: @@ -999,30 +1040,12 @@ cdef class WallBase: self.velocity = velocity self.edge_attr = edge_attr or {} - def _install(self, ReactorBase left, ReactorBase right): - """ - Install this Wall between two `Reactor` objects or between a - `Reactor` and a `Reservoir`. - """ left._add_wall(self) right._add_wall(self) - self.wall.install(deref(left.rbase), deref(right.rbase)) # Keep references to prevent premature garbage collection self._left_reactor = left self._right_reactor = right - property type: - """The type of the wall.""" - def __get__(self): - return pystr(self.wall.type()) - - property name: - """The name of the wall.""" - def __get__(self): - return pystr(self.wall.name()) - def __set__(self, name): - self.wall.setName(stringify(name)) - property area: """ The wall area [m^2]. """ def __get__(self): @@ -1138,7 +1161,7 @@ cdef class Wall(WallBase): :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" + node_type = "Wall" property expansion_rate_coeff: """ @@ -1207,7 +1230,7 @@ cdef class Wall(WallBase): (self.wall).setHeatFlux(f.func) -cdef class FlowDevice: +cdef class FlowDevice(ConnectorNode): """ Base class for devices that allow flow between reactors. @@ -1218,37 +1241,15 @@ 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, name="(none)", **kwargs): - self._dev = newFlowDevice(stringify(self.flowdevice_type), stringify(name)) - self.dev = self._dev.get() + def __cinit__(self, *args, **kwargs): + self.dev = (self.node) def __init__(self, upstream, downstream, *, name="(none)", edge_attr=None): assert self.dev != NULL self._rate_func = None self.edge_attr = edge_attr or {} - self._install(upstream, downstream) - - property type: - """The type of the flow device.""" - def __get__(self): - return pystr(self.dev.type()) - - property name: - """The name of the flow device.""" - def __get__(self): - return pystr(self.dev.name()) - def __set__(self, name): - self.dev.setName(stringify(name)) - - def _install(self, ReactorBase upstream, ReactorBase downstream): - """ - Install the device between the ``upstream`` (source) and ``downstream`` - (destination) reactors or reservoirs. - """ upstream._add_outlet(self) downstream._add_inlet(self) - self.dev.install(deref(upstream.rbase), deref(downstream.rbase)) # Keep references to prevent premature garbage collection self._upstream = upstream self._downstream = downstream @@ -1387,10 +1388,10 @@ cdef class MassFlowController(FlowDevice): that this capability should be used with caution, since no account is taken of the work required to do this. """ - flowdevice_type = "MassFlowController" + node_type = "MassFlowController" - def __init__(self, upstream, downstream, *, name="(none)", mdot=1., **kwargs): - super().__init__(upstream, downstream, name=name, **kwargs) + def __init__(self, upstream, downstream, *, name="(none)", mdot=1., edge_attr=None): + super().__init__(upstream, downstream, name=name, edge_attr=edge_attr) self.mass_flow_rate = mdot property mass_flow_coeff: @@ -1461,10 +1462,10 @@ cdef class Valve(FlowDevice): value, very small pressure differences will result in flow between the reactors that counteracts the pressure difference. """ - flowdevice_type = "Valve" + node_type = "Valve" - def __init__(self, upstream, downstream, *, name="(none)", K=1., **kwargs): - super().__init__(upstream, downstream, name=name, **kwargs) + def __init__(self, upstream, downstream, *, name="(none)", K=1., edge_attr=None): + super().__init__(upstream, downstream, name=name, edge_attr=edge_attr) if isinstance(K, _numbers.Real): self.valve_coeff = K else: @@ -1504,10 +1505,11 @@ cdef class PressureController(FlowDevice): where :math:`f` is the arbitrary function of a single argument. """ - flowdevice_type = "PressureController" + node_type = "PressureController" - def __init__(self, upstream, downstream, *, name="(none)", primary=None, K=1.): - super().__init__(upstream, downstream, name=name) + def __init__(self, upstream, downstream, *, + name="(none)", primary=None, K=1., edge_attr=None): + super().__init__(upstream, downstream, name=name, edge_attr=edge_attr) if primary is not None: self.primary = primary if isinstance(K, _numbers.Real): From d0e96223a28ea855bd49930e1315232ee3518e69 Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Sun, 16 Feb 2025 10:15:21 -0600 Subject: [PATCH 09/18] [zeroD] Add alternative Connector instantiations Add newWall and newFlowDevice with reactors as parameters, and deprecate old versions. --- include/cantera/zeroD/ConnectorFactory.h | 20 +++++++++++++++++- include/cantera/zeroD/FlowDevice.h | 2 +- include/cantera/zeroD/Wall.h | 2 +- src/zeroD/ConnectorFactory.cpp | 26 ++++++++++++++++++++---- 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/include/cantera/zeroD/ConnectorFactory.h b/include/cantera/zeroD/ConnectorFactory.h index 3a60c8f14..e68a7486f 100644 --- a/include/cantera/zeroD/ConnectorFactory.h +++ b/include/cantera/zeroD/ConnectorFactory.h @@ -55,7 +55,7 @@ private: //! @ingroup zerodGroup //! @{ -//! Create a %ConnectorNode object of the specified type +//! Create a ConnectorNode object of the specified type //! @param model String specifying reactor type. //! @param r0 First reactor. //! @param r1 Second reactor. @@ -68,12 +68,30 @@ shared_ptr newConnectorNode(const string& model, //! Create a FlowDevice object of the specified type //! @since Starting in %Cantera 3.1, this method returns a `shared_ptr` +//! @deprecated To be removed after %Cantera 3.2. Use version that provides reactors +//! as parameter instead. shared_ptr newFlowDevice(const string& model, const string& name="(none)"); +//! Create a FlowDevice object of the specified type. +//! @copydetails newConnectorNode +shared_ptr newFlowDevice(const string& model, + shared_ptr r0, + shared_ptr r1, + const string& name="(none)"); + //! Create a WallBase object of the specified type //! @since Starting in %Cantera 3.1, this method returns a `shared_ptr` +//! @deprecated To be removed after %Cantera 3.2. Use version that provides reactors +//! as parameter instead. shared_ptr newWall(const string& model, const string& name="(none)"); +//! Create a WallBase object of the specified type. +//! @copydetails newConnectorNode +shared_ptr newWall(const string& model, + shared_ptr r0, + shared_ptr r1, + const string& name="(none)"); + //! @} } diff --git a/include/cantera/zeroD/FlowDevice.h b/include/cantera/zeroD/FlowDevice.h index aac16f58f..908e4930c 100644 --- a/include/cantera/zeroD/FlowDevice.h +++ b/include/cantera/zeroD/FlowDevice.h @@ -57,7 +57,7 @@ public: /*! * @param in Upstream reactor. * @param out Downstream reactor. - * @deprecated To be removed after Cantera 3.2. Reactors should be provided to + * @deprecated To be removed after %Cantera 3.2. Reactors should be provided to * constructor instead. */ bool install(ReactorBase& in, ReactorBase& out); diff --git a/include/cantera/zeroD/Wall.h b/include/cantera/zeroD/Wall.h index 3e5269077..bd12703b8 100644 --- a/include/cantera/zeroD/Wall.h +++ b/include/cantera/zeroD/Wall.h @@ -60,7 +60,7 @@ public: virtual void setArea(double a); //! Install the wall between two reactors or reservoirs - //! @deprecated To be removed after Cantera 3.2. Reactors should be provided to + //! @deprecated To be removed after %Cantera 3.2. Reactors should be provided to //! constructor instead. bool install(ReactorBase& leftReactor, ReactorBase& rightReactor); diff --git a/src/zeroD/ConnectorFactory.cpp b/src/zeroD/ConnectorFactory.cpp index b947fbf6a..973d90633 100644 --- a/src/zeroD/ConnectorFactory.cpp +++ b/src/zeroD/ConnectorFactory.cpp @@ -52,10 +52,12 @@ shared_ptr newConnectorNode( ConnectorFactory::factory()->create(model, r0, r1, name)); } -shared_ptr newFlowDevice(const string& model, const string& name) +shared_ptr newFlowDevice( + const string& model, + shared_ptr r0, shared_ptr r1, const string& name) { auto dev = std::dynamic_pointer_cast( - newConnectorNode(model, nullptr, nullptr, name)); + newConnectorNode(model, r0, r1, name)); if (!dev) { throw CanteraError("newFlowDevice", "Detected incompatible ConnectorNode type '{}'", model); @@ -63,10 +65,19 @@ shared_ptr newFlowDevice(const string& model, const string& name) return dev; } -shared_ptr newWall(const string& model, const string& name) +shared_ptr newFlowDevice(const string& model, const string& name) +{ + warn_deprecated("newFlowDevice", + "After Cantera 3.1, Reactors must be provided as parameters."); + return newFlowDevice(model, nullptr, nullptr, name); +} + +shared_ptr newWall( + const string& model, + shared_ptr r0, shared_ptr r1, const string& name) { auto wall = std::dynamic_pointer_cast( - newConnectorNode(model, nullptr, nullptr, name)); + newConnectorNode(model, r0, r1, name)); if (!wall) { throw CanteraError("newWall", "Detected incompatible ConnectorNode type '{}'", model); @@ -74,4 +85,11 @@ shared_ptr newWall(const string& model, const string& name) return wall; } +shared_ptr newWall(const string& model, const string& name) +{ + warn_deprecated("newWall", + "After Cantera 3.1, Reactors must be provided as parameters."); + return newWall(model, nullptr, nullptr, name); +} + } From 27f4ff261a3d811f6498b8fa1842d46b1254a6e5 Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Thu, 22 Aug 2024 15:34:58 -0500 Subject: [PATCH 10/18] [unittests] Improve test-zeroD coverage --- test/python/test_reactor.py | 7 --- test/zeroD/test_zeroD.cpp | 101 ++++++++++++++++++++++++++++++++++-- 2 files changed, 96 insertions(+), 12 deletions(-) diff --git a/test/python/test_reactor.py b/test/python/test_reactor.py index 15de152b7..108cbb10d 100644 --- a/test/python/test_reactor.py +++ b/test/python/test_reactor.py @@ -728,13 +728,6 @@ class TestReactor: assert self.r1.name.startswith(f"{self.r1.type}_") # default name assert res.name.startswith(f"{res.type}_") # default name - def test_valve_errors(self): - self.make_reactors() - v = ct.Valve(self.r1, self.r2) - with pytest.raises(ct.CanteraError, match='Already installed'): - # inlet and outlet cannot be reassigned - v._install(self.r2, self.r1) - def test_pressure_controller1(self): self.make_reactors(n_reactors=1) g = ct.Solution('h2o2.yaml', transport_model=None) diff --git a/test/zeroD/test_zeroD.cpp b/test/zeroD/test_zeroD.cpp index 78e5780ce..044631b6a 100644 --- a/test/zeroD/test_zeroD.cpp +++ b/test/zeroD/test_zeroD.cpp @@ -19,16 +19,16 @@ TEST(zerodim, simple) auto sol = newSolution("gri30.yaml", "gri30", "none"); sol->thermo()->setState_TPX(T, P, X); - auto cppReactor = newReactor("IdealGasReactor", sol, "simple"); - ASSERT_EQ(cppReactor->name(), "simple"); - cppReactor->initialize(); + auto reactor = newReactor("IdealGasReactor", sol, "simple"); + ASSERT_EQ(reactor->name(), "simple"); + reactor->initialize(); ReactorNet network; - network.addReactor(dynamic_cast(*cppReactor)); + network.addReactor(dynamic_cast(*reactor)); network.initialize(); double t = 0.0; while (t < 0.1) { - ASSERT_GE(cppReactor->temperature(), T); + ASSERT_GE(reactor->temperature(), T); t = network.time() + 5e-3; network.advance(t); } @@ -56,6 +56,97 @@ TEST(zerodim, test_guards) EXPECT_THROW(Valve().updateMassFlowRate(0.), CanteraError); } +TEST(zerodim, flowdevice) +{ + auto gas = newSolution("gri30.yaml", "gri30", "none"); + + auto node0 = newReactor("IdealGasReactor", gas, "upstream"); + auto node1 = newReactor("IdealGasReactor", gas, "downstream"); + + auto valve = newFlowDevice("Valve", node0, node1, "valve"); + ASSERT_EQ(valve->name(), "valve"); + ASSERT_EQ(valve->in().name(), "upstream"); + ASSERT_EQ(valve->out().name(), "downstream"); + + ASSERT_EQ(node0->nInlets(), 0); + ASSERT_EQ(node0->nOutlets(), 1); + ASSERT_EQ(node1->nInlets(), 1); + ASSERT_EQ(node1->nOutlets(), 0); +} + +TEST(zerodim, wall) +{ + auto gas = newSolution("gri30.yaml", "gri30", "none"); + + auto node0 = newReactor("IdealGasReactor", gas, "left"); + auto node1 = newReactor("IdealGasReactor", gas, "right"); + + auto wall = newWall("Wall", node0, node1, "wall"); + ASSERT_EQ(wall->name(), "wall"); + ASSERT_EQ(wall->left().name(), "left"); + ASSERT_EQ(wall->right().name(), "right"); + + ASSERT_EQ(node0->nWalls(), 1); + ASSERT_EQ(node1->nWalls(), 1); +} + +TEST(zerodim, mole_reactor) +{ + // simplified version of continuous_reactor.py + auto gas = newSolution("h2o2.yaml", "ohmech", "none"); + + auto tank = make_shared(gas, "fuel-air-tank"); + auto exhaust = make_shared(gas, "exhaust"); + + auto stirred = make_shared(gas, "stirred-reactor"); + stirred->setEnergy(0); + stirred->setInitialVolume(30.5 * 1e-6); + + auto mfc = make_shared(tank, stirred, "mass-flow-controller"); + double residenceTime = 2.; + double mass = stirred->mass(); + mfc->setMassFlowRate(mass/residenceTime); + + auto preg = make_shared(stirred, exhaust, "pressure-regulator"); + preg->setPrimary(mfc.get()); + preg->setPressureCoeff(1e-3); + + auto net = ReactorNet(); + net.addReactor(*stirred); + net.initialize(); +} + +TEST(zerodim, mole_reactor_2) +{ + // simplified version of continuous_reactor.py + auto gas = newSolution("h2o2.yaml", "ohmech", "none"); + + auto tank = std::dynamic_pointer_cast( + newReactor("Reservoir", gas, "fuel-air-tank")); + auto exhaust = std::dynamic_pointer_cast( + newReactor("Reservoir", gas, "exhaust")); + + auto stirred = std::dynamic_pointer_cast( + newReactor("IdealGasMoleReactor", gas, "stirred-reactor")); + stirred->setEnergy(0); + stirred->setInitialVolume(30.5 * 1e-6); + + auto mfc = std::dynamic_pointer_cast( + newConnectorNode("MassFlowController", tank, stirred, "mass-flow-controller")); + double residenceTime = 2.; + double mass = stirred->mass(); + mfc->setMassFlowRate(mass/residenceTime); + + auto preg = std::dynamic_pointer_cast( + newConnectorNode("PressureController", stirred, exhaust, "pressure-regulator")); + preg->setPrimary(mfc.get()); + preg->setPressureCoeff(1e-3); + + auto net = ReactorNet(); + net.addReactor(*stirred); + net.initialize(); +} + // This test ensures that prior reactor initialization of a reactor does // not affect later integration within a network. This example was // adapted from test_reactor.py::test_equilibrium_HP. From bd5b2e29e8f79ed7138b539dc6430794478cbd72 Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Thu, 22 Aug 2024 21:26:00 -0500 Subject: [PATCH 11/18] [clib] Add new Connector functions --- include/cantera/clib/ctreactor.h | 7 ++++ src/clib/ctreactor.cpp | 63 ++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/include/cantera/clib/ctreactor.h b/include/cantera/clib/ctreactor.h index 85e5061db..e1b426d4b 100644 --- a/include/cantera/clib/ctreactor.h +++ b/include/cantera/clib/ctreactor.h @@ -19,6 +19,7 @@ extern "C" { CANTERA_CAPI int reactor_new(const char* type, int n, const char* name); CANTERA_CAPI int reactor_del(int i); + CANTERA_CAPI int reactor_type(int i, int len, char* nbuf); CANTERA_CAPI int reactor_name(int i, int len, char* nbuf); CANTERA_CAPI int reactor_setName(int i, const char* name); CANTERA_CAPI int reactor_setInitialVolume(int i, double v); @@ -51,6 +52,12 @@ extern "C" { CANTERA_CAPI double reactornet_atol(int i); CANTERA_CAPI double reactornet_sensitivity(int i, const char* v, int p, int r); + CANTERA_CAPI int connector_new(const char* type, int r0, int r1, const char* name); + CANTERA_CAPI int connector_del(int i); + CANTERA_CAPI int connector_type(int i, int len, char* nbuf); + CANTERA_CAPI int connector_name(int i, int len, char* nbuf); + CANTERA_CAPI int connector_setName(int i, const char* name); + CANTERA_CAPI int flowdev_new(const char* type, const char* name); CANTERA_CAPI int flowdev_del(int i); CANTERA_CAPI int flowdev_name(int i, int len, char* nbuf); diff --git a/src/clib/ctreactor.cpp b/src/clib/ctreactor.cpp index 804faae8d..bc19b11cb 100644 --- a/src/clib/ctreactor.cpp +++ b/src/clib/ctreactor.cpp @@ -58,6 +58,16 @@ extern "C" { } } + int reactor_type(int i, int len, char* nbuf) + { + try { + return static_cast( + copyString(ReactorCabinet::at(i)->type(), nbuf, len)); + } catch (...) { + return handleAllExceptions(-1, ERR); + } + } + int reactor_name(int i, int len, char* nbuf) { try { @@ -346,6 +356,59 @@ extern "C" { } } + // connectors + + int connector_new(const char* type, int n, int m, const char* name) + { + try { + + return ConnectorCabinet::add( + newConnector(type, ReactorCabinet::at(n), ReactorCabinet::at(m), name)); + } catch (...) { + return handleAllExceptions(-1, ERR); + } + } + + int connector_del(int i) + { + try { + ConnectorCabinet::del(i); + return 0; + } catch (...) { + return handleAllExceptions(-1, ERR); + } + } + + int connector_type(int i, int len, char* nbuf) + { + try { + return static_cast( + copyString(ConnectorCabinet::at(i)->type(), nbuf, len)); + } catch (...) { + return handleAllExceptions(-1, ERR); + } + } + + int connector_name(int i, int len, char* nbuf) + { + try { + return static_cast( + copyString(ConnectorCabinet::at(i)->name(), nbuf, len)); + } catch (...) { + return handleAllExceptions(-1, ERR); + } + } + + int connector_setName(int i, const char* name) + { + try { + ConnectorCabinet::at(i)->setName(name); + return 0; + } catch (...) { + return handleAllExceptions(-1, ERR); + } + } + // flow devices int flowdev_new(const char* type, const char* name) From 0ce3a7c3e1abd274f9985d0051069386bea9307f Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Thu, 22 Aug 2024 22:13:26 -0500 Subject: [PATCH 12/18] [MATLAB] Use CLib connector functions --- .../matlab_experimental/Base/Interface.m | 21 +---- .../matlab_experimental/Reactor/Connector.m | 84 +++++++++++++++++++ .../matlab_experimental/Reactor/FlowDevice.m | 76 +++-------------- .../Reactor/MassFlowController.m | 3 +- .../matlab_experimental/Reactor/Reactor.m | 9 +- .../matlab_experimental/Reactor/Valve.m | 3 +- interfaces/matlab_experimental/Reactor/Wall.m | 40 +-------- samples/matlab_experimental/periodic_cstr.m | 6 +- 8 files changed, 110 insertions(+), 132 deletions(-) create mode 100644 interfaces/matlab_experimental/Reactor/Connector.m diff --git a/interfaces/matlab_experimental/Base/Interface.m b/interfaces/matlab_experimental/Base/Interface.m index ecf1cc055..05e607b16 100644 --- a/interfaces/matlab_experimental/Base/Interface.m +++ b/interfaces/matlab_experimental/Base/Interface.m @@ -1,4 +1,4 @@ -classdef Interface < handle & ThermoPhase & Kinetics +classdef Interface < Solution % Interface Class :: % % >> s = Interface(src, name, p1, p2) @@ -13,11 +13,6 @@ classdef Interface < handle & ThermoPhase & Kinetics % :return: % Instance of class :mat:class:`Interface`. - properties (SetAccess = immutable) - solnID % ID of the interface. - interfaceName % Name of the interface. - end - properties (SetAccess = public) % Surface coverages of the species on an interface. @@ -50,11 +45,8 @@ classdef Interface < handle & ThermoPhase & Kinetics ID = ctFunc('soln_newInterface', src, name, na, adj); - % Inherit methods and properties from ThermoPhase and Kinetics - s@ThermoPhase(ID); - s@Kinetics(ID); - s.solnID = ID; - s.interfaceName = name; + % Inherit methods and properties from Solution + s@Solution(ID); s.nAdjacent = ctFunc('soln_nAdjacent', ID); s.adjacentNames = {}; for i = 1:s.nAdjacent @@ -62,13 +54,6 @@ classdef Interface < handle & ThermoPhase & Kinetics end end - %% Interface Class Destructor - - function delete(s) - % Delete :mat:class:`Interface` object. - ctFunc('soln_del', s.solnID); - end - %% Interface Get Methods function adj = adjacent(s, name) diff --git a/interfaces/matlab_experimental/Reactor/Connector.m b/interfaces/matlab_experimental/Reactor/Connector.m new file mode 100644 index 000000000..6d54b281e --- /dev/null +++ b/interfaces/matlab_experimental/Reactor/Connector.m @@ -0,0 +1,84 @@ +classdef Connector < handle + % Connector Class :: + % + % >> c = Connector(typ, r1, r2, name) + % + % Base class for walls and flow devices. + % + % See also: :mat:class:`FlowDevice`, :mat:class:`Wall` + % + % :param typ: + % Type of connector. + % :param r1: + % Reactor one. + % :param r2: + % Reactor two. + % :param name: + % Connector name (optional; default is ``(none)``). + % :return: + % Instance of class :mat:class:`Connector`. + + properties (SetAccess = immutable) + + id % ID of Connector object. + + end + + properties (SetAccess = public) + + type % Name of connector. + + name % Name of connector. + + end + + methods + %% Connector Class Constructor + + function c = Connector(typ, r1, r2, name) + % Create a :mat:class:`Connector` object. + + ctIsLoaded; + + if nargin < 3 + error('please specify type and reactors'); + end + if nargin < 4 + name = '(none)'; + end + + if ~isa(r1, 'Reactor') || ~isa(r1, 'Reactor') + error(['Connectors can only be installed between', ... + 'reactors or reservoirs']); + end + + c.id = ctFunc('connector_new', typ, r1.id, r2.id, name); + end + + %% Connector Class Destructor + + function delete(c) + % Delete the :mat:class:`Connector` object. + + ctFunc('connector_del', c.id); + end + + %% Connector Get Methods + + function typ = get.type(c) + typ = ctString('connector_type', c.id); + end + + function name = get.name(c) + name = ctString('connector_name', c.id); + end + + %% Connector Set Methods + + function set.name(c, name) + ctFunc('connector_setName', c.id, name); + end + + end + +end diff --git a/interfaces/matlab_experimental/Reactor/FlowDevice.m b/interfaces/matlab_experimental/Reactor/FlowDevice.m index 4dfd8438b..9072cf1ea 100644 --- a/interfaces/matlab_experimental/Reactor/FlowDevice.m +++ b/interfaces/matlab_experimental/Reactor/FlowDevice.m @@ -1,4 +1,4 @@ -classdef FlowDevice < handle +classdef FlowDevice < Connector % FlowDevice Class :: % % >> x = FlowDevice(typ, name) @@ -25,21 +25,16 @@ classdef FlowDevice < handle properties (SetAccess = immutable) - type % Type of flow device. - id % ID of FlowDevice object. - - end - - properties (SetAccess = public) - - name % Name of flow device. - % Upstream object of type :mat:class:`Reactor` or :mat:class:`Reservoir`. upstream % Downstream object of type :mat:class:`Reactor` or :mat:class:`Reservoir`. downstream + end + + properties (SetAccess = public) + % The mass flow rate through the :mat:class:`FlowDevice` at the current time. % % The setter method can either take a double value or a function represented by @@ -60,79 +55,28 @@ classdef FlowDevice < handle methods %% FlowDevice Class Constructor - function x = FlowDevice(typ, name) + function x = FlowDevice(typ, upstream, downstream, name) % Create a :mat:class:`FlowDevice` object. ctIsLoaded; - if nargin == 0 - error('please specify the type of flow device to be created'); - end - if nargin < 2 + if nargin < 4 name = '(none)'; end - x.type = typ; - x.id = ctFunc('flowdev_new', typ, name); - x.upstream = -1; - x.downstream = -1; - end - - %% FlowDevice Class Destructor - - function delete(f) - % Delete the :mat:class:`FlowDevice` object. - - ctFunc('flowdev_del', f.id); - end - - %% Utility Methods - - function install(f, upstream, downstream) - % Install a flow device between reactors or reservoirs. :: - % - % >> f.install(upstream, downstream) - % - % :param f: - % Instance of class :mat:class:`FlowDevice` to install. - % :param upstream: - % Upstream :mat:class:`Reactor` or :mat:class:`Reservoir`. - % :param downstream: - % Downstream :mat:class:`Reactor` or :mat:class:`Reservoir`. - % :return: - % Instance of class :mat:class:`FlowDevice`. - - if nargin == 3 - - if ~isa(upstream, 'Reactor') || ~isa(downstream, 'Reactor') - error(['Flow devices can only be installed between', ... - 'reactors or reservoirs']); - end - - i = upstream.id; - j = downstream.id; - ctFunc('flowdev_install', f.id, i, j); - else error('install requires 3 arguments'); - end - + x@Connector(typ, upstream, downstream, name) + x.upstream = upstream; + x.downstream = downstream; end %% FlowDevice Get Methods - function name = get.name(f) - name = ctString('flowdev_name', f.id); - end - function mdot = get.massFlowRate(f) mdot = ctFunc('flowdev_massFlowRate2', f.id); end %% FlowDevice Set Methods - function set.name(f, name) - ctFunc('flowdev_setName', f.id, name); - end - function set.massFlowRate(f, mdot) if strcmp(f.type, 'MassFlowController') diff --git a/interfaces/matlab_experimental/Reactor/MassFlowController.m b/interfaces/matlab_experimental/Reactor/MassFlowController.m index fe8d9a134..c3b72a43b 100644 --- a/interfaces/matlab_experimental/Reactor/MassFlowController.m +++ b/interfaces/matlab_experimental/Reactor/MassFlowController.m @@ -31,8 +31,7 @@ classdef MassFlowController < FlowDevice name = '(none)'; end - m@FlowDevice('MassFlowController', name); - m.install(upstream, downstream) + m@FlowDevice('MassFlowController', upstream, downstream, name); end end diff --git a/interfaces/matlab_experimental/Reactor/Reactor.m b/interfaces/matlab_experimental/Reactor/Reactor.m index 140438689..d330bd24b 100644 --- a/interfaces/matlab_experimental/Reactor/Reactor.m +++ b/interfaces/matlab_experimental/Reactor/Reactor.m @@ -2,13 +2,14 @@ classdef Reactor < handle properties (SetAccess = immutable) - type % Type of Reactor. id % ID of Reactor. end properties (SetAccess = public) + type % Reactor type. + name % Name of reactor. contents @@ -131,8 +132,8 @@ classdef Reactor < handle error('Reactor contents must be an object of type "Solution"'); end - r.type = char(typ); r.id = ctFunc('reactor_new', typ, content.solnID, name); + r.contents = content; end %% Reactor Class Destructor @@ -160,6 +161,10 @@ classdef Reactor < handle %% Reactor Get Methods + function typ = get.type(r) + typ = ctString('reactor_type', r.id); + end + function name = get.name(r) name = ctString('reactor_name', r.id); end diff --git a/interfaces/matlab_experimental/Reactor/Valve.m b/interfaces/matlab_experimental/Reactor/Valve.m index 36ca248f8..a2d7492ec 100644 --- a/interfaces/matlab_experimental/Reactor/Valve.m +++ b/interfaces/matlab_experimental/Reactor/Valve.m @@ -40,8 +40,7 @@ classdef Valve < FlowDevice name = '(none)'; end - v@FlowDevice('Valve', name); - v.install(upstream, downstream) + v@FlowDevice('Valve', upstream, downstream, name); end end diff --git a/interfaces/matlab_experimental/Reactor/Wall.m b/interfaces/matlab_experimental/Reactor/Wall.m index 3557a81a8..0b6b98c16 100644 --- a/interfaces/matlab_experimental/Reactor/Wall.m +++ b/interfaces/matlab_experimental/Reactor/Wall.m @@ -1,4 +1,4 @@ -classdef Wall < handle +classdef Wall < Connector % Wall Class :: % % >> x = Wall(l, r, name) @@ -47,15 +47,6 @@ classdef Wall < handle properties (SetAccess = immutable) - id - type - - end - - properties (SetAccess = protected) - - name % Name of wall. - left % Reactor on the left. right % Reactor on the right. @@ -93,49 +84,26 @@ classdef Wall < handle function w = Wall(l, r, name) % Create a :mat:class:`Wall` object. - ctIsLoaded; % At the moment, only one wall type is implemented - typ = 'Wall'; if nargin < 3 name = '(none)'; end - w.type = char(typ); - w.id = ctFunc('wall_new', w.type, name); - % Install the wall between left and right reactors + w@Connector('Wall', l, r, name) w.left = l; w.right = r; - ctFunc('wall_install', w.id, l.id, r.id); % Set default values. w.area = 1.0; w.expansionRateCoeff = 0.0; w.heatTransferCoeff = 0.0; - % Check whether the wall is ready. - ok = ctFunc('wall_ready', w.id); - if ~ok - error('The wall object is not ready.'); - end - - end - - %% Wall Class Destructor - - function delete(w) - % Clear the :mat:class:`Wall` object. - - ctFunc('wall_del', w.id); end %% ReactorNet get methods - function name = get.name(w) - name = ctString('wall_name', w.id); - end - function a = get.area(w) a = ctFunc('wall_area', w.id); end @@ -150,10 +118,6 @@ classdef Wall < handle %% ReactorNet set methods - function set.name(w, name) - ctFunc('wall_setName', w.id, name); - end - function set.area(w, a) ctFunc('wall_setArea', w.id, a); end diff --git a/samples/matlab_experimental/periodic_cstr.m b/samples/matlab_experimental/periodic_cstr.m index 4e9690bc3..380bc5130 100644 --- a/samples/matlab_experimental/periodic_cstr.m +++ b/samples/matlab_experimental/periodic_cstr.m @@ -73,8 +73,7 @@ function periodic_cstr sccm = 1.25; vdot = sccm * 1.0e-6/60.0 * ((OneAtm / gas.P) * (gas.T / 273.15)); % m^3/s mdot = gas.D * vdot; % kg/s - mfc = MassFlowController; - mfc.install(upstream, cstr); + mfc = MassFlowController(upstream, cstr); mfc.massFlowRate = mdot; % now create a downstream reservoir to exhaust into. @@ -83,8 +82,7 @@ function periodic_cstr % connect the reactor to the downstream reservoir with a valve, and % set the coefficient sufficiently large to keep the reactor pressure % close to the downstream pressure of 60 Torr. - v = Valve; - v.install(cstr, downstream); + v = Valve(cstr, downstream); v.valveCoeff = 1.0e-9; % create the network From 7809c7355ac25fa4eaf3fbe46564906e551986e1 Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Thu, 22 Aug 2024 22:25:26 -0500 Subject: [PATCH 13/18] [clib] Remove obsolete functions --- include/cantera/clib/ctreactor.h | 12 --- src/clib/ctreactor.cpp | 129 +------------------------------ 2 files changed, 4 insertions(+), 137 deletions(-) diff --git a/include/cantera/clib/ctreactor.h b/include/cantera/clib/ctreactor.h index e1b426d4b..ca50ed87c 100644 --- a/include/cantera/clib/ctreactor.h +++ b/include/cantera/clib/ctreactor.h @@ -25,7 +25,6 @@ extern "C" { CANTERA_CAPI int reactor_setInitialVolume(int i, double v); CANTERA_CAPI int reactor_setChemistry(int i, int cflag); CANTERA_CAPI int reactor_setEnergy(int i, int eflag); - CANTERA_CAPI int reactor_setSolution(int i, int n); CANTERA_CAPI double reactor_mass(int i); CANTERA_CAPI double reactor_volume(int i); CANTERA_CAPI double reactor_density(int i); @@ -58,11 +57,6 @@ extern "C" { CANTERA_CAPI int connector_name(int i, int len, char* nbuf); CANTERA_CAPI int connector_setName(int i, const char* name); - CANTERA_CAPI int flowdev_new(const char* type, const char* name); - CANTERA_CAPI int flowdev_del(int i); - CANTERA_CAPI int flowdev_name(int i, int len, char* nbuf); - CANTERA_CAPI int flowdev_setName(int i, const char* name); - CANTERA_CAPI int flowdev_install(int i, int n, int m); CANTERA_CAPI int flowdev_setPrimary(int i, int n); CANTERA_CAPI double flowdev_massFlowRate(int i); CANTERA_CAPI int flowdev_setMassFlowCoeff(int i, double v); @@ -71,11 +65,6 @@ extern "C" { CANTERA_CAPI int flowdev_setPressureFunction(int i, int n); CANTERA_CAPI int flowdev_setTimeFunction(int i, int n); - CANTERA_CAPI int wall_new(const char* type, const char* name); - CANTERA_CAPI int wall_del(int i); - CANTERA_CAPI int wall_name(int i, int len, char* nbuf); - CANTERA_CAPI int wall_setName(int i, const char* name); - CANTERA_CAPI int wall_install(int i, int n, int m); CANTERA_CAPI double wall_expansionRate(int i); CANTERA_CAPI double wall_heatRate(int i); CANTERA_CAPI double wall_area(int i); @@ -86,7 +75,6 @@ extern "C" { CANTERA_CAPI int wall_setExpansionRateCoeff(int i, double k); CANTERA_CAPI int wall_setVelocity(int i, int n); CANTERA_CAPI int wall_setEmissivity(int i, double epsilon); - CANTERA_CAPI int wall_ready(int i); CANTERA_CAPI int reactorsurface_new(const char* name); CANTERA_CAPI int reactorsurface_del(int i); diff --git a/src/clib/ctreactor.cpp b/src/clib/ctreactor.cpp index bc19b11cb..900758ba2 100644 --- a/src/clib/ctreactor.cpp +++ b/src/clib/ctreactor.cpp @@ -42,7 +42,8 @@ extern "C" { int reactor_new(const char* type, int n, const char* name) { try { - return ReactorCabinet::add(newReactor(type, SolutionCabinet::at(n), name)); + return ReactorCabinet::add( + newReactor(type, SolutionCabinet::at(n), name)); } catch (...) { return handleAllExceptions(-1, ERR); } @@ -98,16 +99,6 @@ extern "C" { } } - int reactor_setSolution(int i, int n) - { - try { - ReactorCabinet::as(i)->setSolution(SolutionCabinet::at(n)); - return 0; - } catch (...) { - return handleAllExceptions(-1, ERR); - } - } - double reactor_mass(int i) { try { @@ -363,7 +354,8 @@ extern "C" { try { return ConnectorCabinet::add( - newConnector(type, ReactorCabinet::at(n), ReactorCabinet::at(m), name)); + newConnectorNode(type, + ReactorCabinet::at(n), ReactorCabinet::at(m), name)); } catch (...) { return handleAllExceptions(-1, ERR); } @@ -411,60 +403,6 @@ extern "C" { // flow devices - int flowdev_new(const char* type, const char* name) - { - try { - return ConnectorCabinet::add(newFlowDevice(type, name)); - } catch (...) { - return handleAllExceptions(-1, ERR); - } - } - - int flowdev_del(int i) - { - try { - ConnectorCabinet::del(i); - return 0; - } catch (...) { - return handleAllExceptions(-1, ERR); - } - } - - int flowdev_name(int i, int len, char* nbuf) - { - try { - return static_cast( - copyString(ConnectorCabinet::at(i)->name(), nbuf, len)); - } catch (...) { - return handleAllExceptions(-1, ERR); - } - } - - int flowdev_setName(int i, const char* name) - { - try { - ConnectorCabinet::at(i)->setName(name); - return 0; - } catch (...) { - return handleAllExceptions(-1, ERR); - } - } - - int flowdev_install(int i, int n, int m) - { - try { - bool ok = ConnectorCabinet::as(i)->install( - *ReactorCabinet::at(n), *ReactorCabinet::at(m)); - if (!ok) { - throw CanteraError("flowdev_install", - "Could not install flow device."); - } - return 0; - } catch (...) { - return handleAllExceptions(-1, ERR); - } - } - int flowdev_setPrimary(int i, int n) { try { @@ -539,56 +477,6 @@ extern "C" { ///////////// Walls /////////////////////// - int wall_new(const char* type, const char* name) - { - try { - return ConnectorCabinet::add(newWall(type, name)); - } catch (...) { - return handleAllExceptions(-1, ERR); - } - } - - int wall_del(int i) - { - try { - ConnectorCabinet::del(i); - return 0; - } catch (...) { - return handleAllExceptions(-1, ERR); - } - } - - int wall_name(int i, int len, char* nbuf) - { - try { - return static_cast( - copyString(ConnectorCabinet::at(i)->name(), nbuf, len)); - } catch (...) { - return handleAllExceptions(-1, ERR); - } - } - - int wall_setName(int i, const char* name) - { - try { - ConnectorCabinet::at(i)->setName(name); - return 0; - } catch (...) { - return handleAllExceptions(-1, ERR); - } - } - - int wall_install(int i, int n, int m) - { - try { - ConnectorCabinet::as(i)->install( - *ReactorCabinet::at(n), *ReactorCabinet::at(m)); - return 0; - } catch (...) { - return handleAllExceptions(-1, ERR); - } - } - double wall_expansionRate(int i) { try { @@ -686,15 +574,6 @@ extern "C" { } } - int wall_ready(int i) - { - try { - return int(ConnectorCabinet::as(i)->ready()); - } catch (...) { - return handleAllExceptions(-1, ERR); - } - } - // ReactorSurface int reactorsurface_new(const char* name) From 7bd0303a72e72f1ee08f112721b5e035bf1cade3 Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Fri, 23 Aug 2024 07:15:51 -0500 Subject: [PATCH 14/18] [sourcegen] Add Connector crosswalk --- interfaces/sourcegen/sourcegen/csharp/config.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interfaces/sourcegen/sourcegen/csharp/config.yaml b/interfaces/sourcegen/sourcegen/csharp/config.yaml index 7107d0b2f..2395d8661 100644 --- a/interfaces/sourcegen/sourcegen/csharp/config.yaml +++ b/interfaces/sourcegen/sourcegen/csharp/config.yaml @@ -24,6 +24,7 @@ class_crosswalk: trans: Transport wall: Wall func: Func1 + connector: Connector # Provides information on instance methods that return instances # of other C# classes. @@ -42,6 +43,8 @@ class_accessors: # Derived: Base derived_handles: SurfaceHandle: ThermoPhaseHandle + WallHandle: ConnectorHandle + FlowDeviceHandle: ConnectorHandle # Provides info for scaffolding higher-level idiomatic C# classes # At this stage, we can scaffold simple properties that follow the From 1d749a279456dd84a94a142ced97520acfcda8cc Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Mon, 3 Feb 2025 21:12:32 -0600 Subject: [PATCH 15/18] [zeroD] Remove ReactorSurface from wallGroup The C++ class does not inherit from WallBase. --- include/cantera/zeroD/ReactorSurface.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/cantera/zeroD/ReactorSurface.h b/include/cantera/zeroD/ReactorSurface.h index 676c4637e..d8acc8d06 100644 --- a/include/cantera/zeroD/ReactorSurface.h +++ b/include/cantera/zeroD/ReactorSurface.h @@ -16,7 +16,6 @@ class SurfPhase; //! A surface where reactions can occur that is in contact with the bulk fluid of a //! Reactor. -//! @ingroup wallGroup class ReactorSurface { public: From 6d36d9416e76e0f7ee5cd891b38c8919ac40a2c7 Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Mon, 3 Feb 2025 21:38:50 -0600 Subject: [PATCH 16/18] [zeroD] Deprecate Wall/FlowDevice factories --- include/cantera/zeroD/FlowDeviceFactory.h | 14 ++++++++++++++ include/cantera/zeroD/WallFactory.h | 14 ++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 include/cantera/zeroD/FlowDeviceFactory.h create mode 100644 include/cantera/zeroD/WallFactory.h diff --git a/include/cantera/zeroD/FlowDeviceFactory.h b/include/cantera/zeroD/FlowDeviceFactory.h new file mode 100644 index 000000000..e7051b99e --- /dev/null +++ b/include/cantera/zeroD/FlowDeviceFactory.h @@ -0,0 +1,14 @@ +//! @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 + +#pragma message("warning: FlowDeviceFactory.h is deprecated and will be removed " \ + "after Cantera 3.2. Use ConnectorFactory.h instead.") + +#include "ConnectorFactory.h" + +#endif diff --git a/include/cantera/zeroD/WallFactory.h b/include/cantera/zeroD/WallFactory.h new file mode 100644 index 000000000..8fabf5325 --- /dev/null +++ b/include/cantera/zeroD/WallFactory.h @@ -0,0 +1,14 @@ +//! @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 + +#pragma message("warning: WallFactory.h is deprecated and will be removed " \ + "after Cantera 3.2. Use ConnectorFactory.h instead.") + +#include "ConnectorFactory.h" + +#endif From 1d86759140fb7fed6e3a22b6128b07ca032668e1 Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Tue, 4 Feb 2025 07:06:55 -0600 Subject: [PATCH 17/18] [Python] Clarifiy reactor content nomenclature --- interfaces/cython/cantera/reactor.pxd | 3 +-- interfaces/cython/cantera/reactor.pyx | 22 ++++++++-------------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/interfaces/cython/cantera/reactor.pxd b/interfaces/cython/cantera/reactor.pxd index 442c95156..3db427435 100644 --- a/interfaces/cython/cantera/reactor.pxd +++ b/interfaces/cython/cantera/reactor.pxd @@ -224,7 +224,7 @@ ctypedef CxxReactorAccessor* CxxReactorAccessorPtr cdef class ReactorBase: cdef shared_ptr[CxxReactorBase] _reactor cdef CxxReactorBase* rbase - cdef object _thermo + cdef object _contents cdef list _inlets cdef list _outlets cdef list _walls @@ -240,7 +240,6 @@ cdef class ReactorBase: cdef class Reactor(ReactorBase): cdef CxxReactor* reactor - cdef object _kinetics cdef public str group_name """ Optional name of a grouping of reactors that will be drawn as a cluster in the diff --git a/interfaces/cython/cantera/reactor.pyx b/interfaces/cython/cantera/reactor.pyx index 03a057946..84c381d01 100644 --- a/interfaces/cython/cantera/reactor.pyx +++ b/interfaces/cython/cantera/reactor.pyx @@ -28,7 +28,7 @@ cdef class ReactorBase: self._walls = [] self._surfaces = [] if isinstance(contents, _SolutionBase): - self._thermo = contents + self._contents = contents if volume is not None: self.volume = volume @@ -43,10 +43,10 @@ cdef class ReactorBase: .. deprecated:: 3.2 After Cantera 3.2, a change of reactor contents after instantiation - will be disabled. + will be disabled and this method will be removed. """ - self._thermo = solution self.rbase.setSolution(solution._base) # raises warning in C++ core + self._contents = solution property type: """The type of the reactor.""" @@ -69,10 +69,12 @@ cdef class ReactorBase: self.rbase.syncState() property thermo: - """The `ThermoPhase` object representing the reactor's contents.""" + """ + The `ThermoPhase` object representing the reactor's contents. + """ def __get__(self): self.rbase.restoreState() - return self._thermo + return self._contents property volume: """The volume [m^3] of the reactor.""" @@ -244,14 +246,6 @@ cdef class Reactor(ReactorBase): self.group_name = group_name - def insert(self, _SolutionBase solution): - """ - Set ``solution`` to be the object used to compute thermodynamic - properties and kinetic rates for this reactor. - """ - ReactorBase.insert(self, solution) - self._kinetics = solution - property kinetics: """ The `Kinetics` object used for calculating kinetic rates in @@ -259,7 +253,7 @@ cdef class Reactor(ReactorBase): """ def __get__(self): self.rbase.restoreState() - return self._kinetics + return self._contents property chemistry_enabled: """ From c7910524da1388898f81d33b25ba81a1876144a1 Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Fri, 23 Aug 2024 12:56:07 -0500 Subject: [PATCH 18/18] [samples] Add plt.show() to Python samples --- samples/python/reactors/PorousMediaBurner.py | 3 ++- samples/python/reactors/continuous_reactor.py | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/samples/python/reactors/PorousMediaBurner.py b/samples/python/reactors/PorousMediaBurner.py index c08b2ab7e..9650e1f34 100644 --- a/samples/python/reactors/PorousMediaBurner.py +++ b/samples/python/reactors/PorousMediaBurner.py @@ -131,7 +131,7 @@ class SolidProperties: def effectiveConductivitySiC(Ts): # for silicon carbide return (1 - 0.84) * 1857.0 * Ts**(-0.5332) -# YZA: Thermal conductivity of zirconia–alumina composites, N.P. Bansal, D. Zhu, +# YZA: Thermal conductivity of zirconia–alumina composites, N.P. Bansal, D. Zhu, # Ceramics International, 31(7), pp 911-916 (2015) def effectiveConductivityYZA(Ts): # for yittria-stabilized zirconia alumina return 0.3 @@ -409,3 +409,4 @@ plt.legend() plt.xlabel("x (m)") plt.ylabel("T (K)") plt.savefig("T.png") +plt.show() diff --git a/samples/python/reactors/continuous_reactor.py b/samples/python/reactors/continuous_reactor.py index b2c42ebc9..7c748571d 100644 --- a/samples/python/reactors/continuous_reactor.py +++ b/samples/python/reactors/continuous_reactor.py @@ -162,6 +162,7 @@ plt.figure() plt.semilogx(time_history.t, time_history("CO").X, "-o") plt.xlabel("Time (s)") plt.ylabel("Mole Fraction : $X_{CO}$") +plt.show() # %% # Illustration : Modeling experimental data @@ -288,6 +289,7 @@ plt.ylabel(r"Mole Fractions") plt.xlim([650, 1100]) plt.legend(loc=1) +plt.show() # %% # References