Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-empty Reactor and Connector Objects #1788

Draft
wants to merge 32 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
4d98163
[zeroD] Implement Connector base class
ischoegl Aug 22, 2024
5222f02
[zeroD] Implement ConnectorFactory
ischoegl Aug 22, 2024
6a950d6
[zeroD] Move newFlowDevice to ConnectorFactory
ischoegl Aug 22, 2024
19cab10
[zeroD] Move newWall to ConnectorFactory
ischoegl Aug 22, 2024
daf97be
[clib] Switch to ConnectorCabinet
ischoegl Aug 22, 2024
fc2b7a2
[zeroD] Create ReactorNode base class
ischoegl Aug 22, 2024
0ce74a9
[zeroD] Derive SurfaceReactor from ReactorNode
ischoegl Aug 22, 2024
7c84086
[zeroD] Switch ReactorFactory to ReactorNode
ischoegl Aug 22, 2024
9aebe1d
[zeroD] Switch Connector to use ReactorNode
ischoegl Aug 22, 2024
5991e64
[clib] Switch ReactorCabinet to ReactorNode
ischoegl Aug 22, 2024
4a31647
[zeroD] Add deprecations
ischoegl Aug 22, 2024
4200a93
[Python] Switch to ReactorNode as base class
ischoegl Aug 22, 2024
1efd22b
[Python] Use Connector as base for edges
ischoegl Aug 22, 2024
57b0730
[zeroD] Install Reactors when instantiating Connectors
ischoegl Aug 22, 2024
e6cfb73
[CI] Improve test-zeroD coverage
ischoegl Aug 22, 2024
d3b1bf0
[Python] Remove _install methods
ischoegl Aug 23, 2024
6ec380a
[clib] Add new Connector functions
ischoegl Aug 23, 2024
7b8be61
[MATLAB] Use CLib connector functions
ischoegl Aug 23, 2024
5777803
[clib] Remove obsolete functions
ischoegl Aug 23, 2024
af1e8d6
[sourcegen] Add Connector crosswalk
ischoegl Aug 23, 2024
21205c0
[zeroD] Update deprecation warnings
ischoegl Aug 23, 2024
add6b91
[zeroD] Move syncState to ReactorNode
ischoegl Aug 23, 2024
60a9ed9
[samples] Add plt.show() to Python samples
ischoegl Aug 23, 2024
e108bae
Change return type of newReactor with contents
ischoegl Aug 23, 2024
313e78d
[base] Implement SharedFactory
ischoegl Aug 24, 2024
4cc6e77
[zeroD] Make Connector constructors protected
ischoegl Aug 24, 2024
b61c7b2
[zeroD] Switch ReactorFactory to shared pointers
ischoegl Aug 24, 2024
fbcd9e9
[zeroD] Protect Reactor constructors
ischoegl Aug 24, 2024
c923449
[zeroD] Deprecate methods using raw pointers
ischoegl Aug 24, 2024
d5e6751
[zeroD] Access reactor contents via ReactorNode
ischoegl Sep 15, 2024
f778d3e
[CI] Update zeroD googletests
ischoegl Aug 24, 2024
c17b309
[samples] Update cxx samples
ischoegl Aug 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 75 additions & 2 deletions include/cantera/base/FactoryBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
static vector<FactoryBase*> s_vFactoryRegistry;
};

//! Factory class that supports registering functions to create objects
//! Factory class that supports registering functions to create objects.
//!
//! Template arguments for the class are the base type created by the factory,
//! followed by the types of any arguments which need to be passed to the
Expand Down Expand Up @@ -97,7 +97,7 @@
} else if (m_synonyms.count(name)) {
return m_synonyms.at(name);
} else if (m_deprecated_names.count(name)) {
warn_deprecated("FactoryBase::canonicalize",
warn_deprecated("Factory::canonicalize",
fmt::format("Model name '{}' is deprecated. Use '{}' instead.",
name, m_deprecated_names.at(name)));
return m_deprecated_names.at(name);
Expand Down Expand Up @@ -133,6 +133,79 @@
std::unordered_map<string, string> m_deprecated_names;
};


//! Factory class that supports registering functions to create shared objects.
//!
//! Template arguments for the class are the base type created by the factory,
//! followed by the types of any arguments which need to be passed to the
//! functions used to create objects, that is, arguments to the constructor.
template <class T, typename ... Args>
class SharedFactory : public FactoryBase {
public:
virtual ~SharedFactory() {}

//! Create an object using the object construction function corresponding to
//! "name" and the provided constructor arguments
shared_ptr<T> create(const string& name, Args... args) {
return m_creators.at(canonicalize(name))(args...);
}

//! Register a new object construction function
void reg(const string& name, function<shared_ptr<T>(Args...)> f) {
m_creators[name] = f;
}

//! Add an alias for an existing registered type
void addAlias(const string& original, const string& alias) {
if (!m_creators.count(original)) {
throw CanteraError("SharedFactory::addAlias",
"Name '{}' not registered", original);
}
m_synonyms[alias] = original;
}

//! Get the canonical name registered for a type
string canonicalize(const string& name) {
if (m_creators.count(name)) {
return name;
} else if (m_synonyms.count(name)) {
return m_synonyms.at(name);
} else if (m_deprecated_names.count(name)) {
warn_deprecated("SharedFactory::canonicalize",

Check warning on line 174 in include/cantera/base/FactoryBase.h

View check run for this annotation

Codecov / codecov/patch

include/cantera/base/FactoryBase.h#L171-L174

Added lines #L171 - L174 were not covered by tests
fmt::format("Model name '{}' is deprecated. Use '{}' instead.",
name, m_deprecated_names.at(name)));
return m_deprecated_names.at(name);

Check warning on line 177 in include/cantera/base/FactoryBase.h

View check run for this annotation

Codecov / codecov/patch

include/cantera/base/FactoryBase.h#L176-L177

Added lines #L176 - L177 were not covered by tests
} else {
throw CanteraError("SharedFactory::canonicalize", "No such type: '{}'", name);

Check warning on line 179 in include/cantera/base/FactoryBase.h

View check run for this annotation

Codecov / codecov/patch

include/cantera/base/FactoryBase.h#L179

Added line #L179 was not covered by tests
}
}

//! Returns true if `name` is registered with this factory
bool exists(const string& name) const {
return m_creators.count(name) || m_synonyms.count(name);
}

protected:
//! Add a deprecated alias for an existing registered type
void addDeprecatedAlias(const string& original, const string& alias) {
if (!m_creators.count(original)) {
throw CanteraError("SharedFactory::addDeprecatedAlias",
"Name '{}' not registered", original);
}
m_deprecated_names[alias] = original;
}

private:
std::unordered_map<string, function<shared_ptr<T>(Args...)>> m_creators;

//! Map of synonyms to canonical names
std::unordered_map<string, string> m_synonyms;

//! Map of deprecated synonyms to canonical names. Use of these names will
//! show a deprecation warning.
std::unordered_map<string, string> m_deprecated_names;
};

}

#endif
24 changes: 7 additions & 17 deletions include/cantera/clib/ctreactor.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ 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);
CANTERA_CAPI int reactor_setChemistry(int i, int cflag);
CANTERA_CAPI int reactor_setEnergy(int i, int eflag);
CANTERA_CAPI int reactor_insert(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);
Expand All @@ -51,11 +51,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 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 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_setPrimary(int i, int n);
CANTERA_CAPI double flowdev_massFlowRate(int i);
CANTERA_CAPI int flowdev_setMassFlowCoeff(int i, double v);
Expand All @@ -64,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);
Expand All @@ -79,14 +75,8 @@ 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);
CANTERA_CAPI int reactorsurface_name(int i, int len, char* nbuf);
CANTERA_CAPI int reactorsurface_setName(int i, const char* name);
CANTERA_CAPI int reactorsurface_install(int i, int n);
CANTERA_CAPI int reactorsurface_setkinetics(int i, int n);
CANTERA_CAPI double reactorsurface_area(int i);
CANTERA_CAPI int reactorsurface_setArea(int i, double v);
CANTERA_CAPI int reactorsurface_addSensitivityReaction(int i, int rxn);
Expand Down
70 changes: 70 additions & 0 deletions include/cantera/zeroD/Connector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//! @file Connector.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 ReactorNode;

/**
* Base class for walls and flow devices connecting reactors.
* In a reactor network, walls and flow devices (valves, pressure regulators, etc.)
* form edges of a directed graph that connect reactors that form nodes.
*
* @since New in %Cantera 3.1.
*
* @ingroup connectorGroup
*/
class Connector : public std::enable_shared_from_this<Connector>
{
protected:
//! Instantiate a Connector object with associated ReactorNode objects.
//! @param r0 First reactor.
//! @param r1 Second reactor.
//! @param name Name of the connector.
Connector(shared_ptr<ReactorNode> r0, shared_ptr<ReactorNode> r1,
const string& name="(none)") : m_nodes({r0, r1}), m_name(name) {}

public:
Connector() = default;
virtual ~Connector() = default;
Connector(const Connector&) = delete;
Connector& operator=(const Connector&) = delete;

//! String indicating the connector implemented. Usually
//! corresponds to the name of the derived class.
virtual string type() const {
return "Connector";

Check warning on line 44 in include/cantera/zeroD/Connector.h

View check run for this annotation

Codecov / codecov/patch

include/cantera/zeroD/Connector.h#L43-L44

Added lines #L43 - L44 were not covered by tests
}

//! 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<string, int>& counts);

protected:
//! Pair of reactors forming end points of the connector.
pair<shared_ptr<ReactorNode>, shared_ptr<ReactorNode>> m_nodes;

string m_name; //!< Connector name.
bool m_defaultNameSet = false; //!< `true` if default name has been previously set.
};

}

#endif
81 changes: 81 additions & 0 deletions include/cantera/zeroD/ConnectorFactory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//! @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/Connector.h"

namespace Cantera
{

class FlowDevice;
class WallBase;

//! Factory class to create Connector objects.
//!
//! This class is mainly used via the newConnector() function, for example:
//!
//! ```cpp
//! shared_ptr<Connector> valve = newConnector("Valve", r0, r1, "my_valve");
//! ```
//!
//! where `r0` and `r1` are reactor objects.
class ConnectorFactory :
public SharedFactory<Connector, shared_ptr<ReactorNode>, shared_ptr<ReactorNode>, const string&>
{
public:
static ConnectorFactory* factory();

void deleteFactory() override;

private:
static ConnectorFactory* s_factory;
static std::mutex connector_mutex;
ConnectorFactory();
};

//! @defgroup connectorGroup Connectors
//! %Connector objects connect zero-dimensional reactors.
//! Connector objects should be instantiated via the newConnector() function, for
//! example:
//!
//! ```cpp
//! shared_ptr<Connector> valve = newConnector("Valve", r0, r1, "my_valve");
//! ```
//!
//! where `r0` and `r1` are reactor objects.
//!
//! @since New in %Cantera 3.1.
//!
//! @ingroup zerodGroup
//! @{

//! Create a Connector 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<Connector> newConnector(const string& model,
shared_ptr<ReactorNode> r0,
shared_ptr<ReactorNode> r1,
const string& name="(none)");

//! Create a FlowDevice object of the specified type
//! @since New in %Cantera 3.0.
//! @deprecated Replaced by newConnector. To be removed after %Cantera 3.1.
shared_ptr<FlowDevice> newFlowDevice3(const string& model);

//! Create a WallBase object of the specified type
//! @since New in %Cantera 3.0.
//! @deprecated Replaced by Wall::create. To be removed after %Cantera 3.1.
shared_ptr<WallBase> newWall3(const string& model);

//! @}
}

#endif
11 changes: 11 additions & 0 deletions include/cantera/zeroD/ConstPressureMoleReactor.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ class ConstPressureMoleReactor : public MoleReactor
public:
using MoleReactor::MoleReactor; // inherit constructors

//! Create a new ConstPressureMoleReactor.
//! @param contents Solution object describing contents.
//! @param name Name of the reactor. Optional; if left empty, a default name will
//! be assigned when the reactor is integrated into a ReactorNet.
static shared_ptr<ConstPressureMoleReactor> create(
shared_ptr<Solution> contents, const string& name="")
{
return shared_ptr<ConstPressureMoleReactor>(
new ConstPressureMoleReactor(contents, name) );
}

string type() const override {
return "ConstPressureMoleReactor";
};
Expand Down
11 changes: 11 additions & 0 deletions include/cantera/zeroD/ConstPressureReactor.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ class ConstPressureReactor : public Reactor
public:
using Reactor::Reactor; // inherit constructors

//! Create a new ConstPressureReactor.
//! @param contents Solution object describing contents.
//! @param name Name of the reactor. Optional; if left empty, a default name will
//! be assigned when the reactor is integrated into a ReactorNet.
static shared_ptr<ConstPressureReactor> create(
shared_ptr<Solution> contents, const string& name="")
{
return shared_ptr<ConstPressureReactor>(
new ConstPressureReactor(contents, name) );
}

string type() const override {
return "ConstPressureReactor";
}
Expand Down
Loading
Loading