mirror of
https://github.com/Cantera/cantera.git
synced 2025-02-25 18:55:29 -06:00
Allow Solution to hold references to external wrappers
This commit is contained in:
parent
760b0fb4b0
commit
2e65ab1ed5
@ -31,6 +31,8 @@ public:
|
||||
class ExternalHandle
|
||||
{
|
||||
public:
|
||||
ExternalHandle() {}
|
||||
ExternalHandle(const ExternalHandle&) = delete;
|
||||
virtual ~ExternalHandle() = default;
|
||||
};
|
||||
|
||||
|
@ -15,9 +15,10 @@ namespace Cantera
|
||||
class ThermoPhase;
|
||||
class Kinetics;
|
||||
class Transport;
|
||||
class ExternalHandle;
|
||||
|
||||
//! A container class holding managers for all pieces defining a phase
|
||||
class Solution
|
||||
class Solution : public std::enable_shared_from_this<Solution>
|
||||
{
|
||||
protected:
|
||||
Solution();
|
||||
@ -98,6 +99,15 @@ public:
|
||||
//! Overwrite source (only required if object is not created using newSolution)
|
||||
void setSource(const std::string& source);
|
||||
|
||||
//! Store a handle to a wrapper for this Solution object from an external
|
||||
//! language interface (for example, a Python Solution object)
|
||||
void holdExternalHandle(const std::string& name, shared_ptr<ExternalHandle> handle);
|
||||
|
||||
//! Get the handle for a wrapper for this Solution object from an external
|
||||
//! language interface.
|
||||
//! Returns a null pointer if the requested handle does not exist.
|
||||
shared_ptr<ExternalHandle> getExternalHandle(const std::string& name) const;
|
||||
|
||||
protected:
|
||||
shared_ptr<ThermoPhase> m_thermo; //!< ThermoPhase manager
|
||||
shared_ptr<Kinetics> m_kinetics; //!< Kinetics manager
|
||||
@ -110,6 +120,10 @@ protected:
|
||||
std::map<std::string, shared_ptr<Solution>> m_adjacentByName;
|
||||
|
||||
AnyMap m_header; //!< Additional input fields; usually from a YAML input file
|
||||
|
||||
//! Wrappers for this Kinetics object in extension languages, for evaluation
|
||||
//! of user-defined reaction rates
|
||||
std::map<std::string, shared_ptr<ExternalHandle>> m_externalHandles;
|
||||
};
|
||||
|
||||
//! Create and initialize a new Solution from an input file
|
||||
|
@ -11,6 +11,7 @@
|
||||
namespace Cantera
|
||||
{
|
||||
|
||||
|
||||
//! Class for managing user-defined Cantera extensions written in Python
|
||||
//!
|
||||
//! Handles Python initialization if the main application is not the Python interpreter.
|
||||
|
34
include/cantera/extensions/PythonHandle.h
Normal file
34
include/cantera/extensions/PythonHandle.h
Normal file
@ -0,0 +1,34 @@
|
||||
//! @file PythonHandle.h
|
||||
|
||||
#ifndef CT_PYTHONHANDLE_H
|
||||
#define CT_PYTHONHANDLE_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.
|
||||
|
||||
#include "Python.h"
|
||||
#include "cantera/base/ExtensionManager.h"
|
||||
|
||||
namespace Cantera
|
||||
{
|
||||
|
||||
//! Class that holds an owned or weak (borrowed) reference to a Python object
|
||||
class PythonHandle : public ExternalHandle
|
||||
{
|
||||
public:
|
||||
PythonHandle(PyObject* obj, bool weak) : m_obj(obj), m_weak(weak) {}
|
||||
|
||||
~PythonHandle() {
|
||||
if (!m_weak) {
|
||||
Py_XDECREF(m_obj);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
PyObject* m_obj;
|
||||
bool m_weak;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -29,6 +29,14 @@ cdef extern from "cantera/base/Interface.h" namespace "Cantera":
|
||||
string, string, vector[string]) except +translate_exception
|
||||
|
||||
|
||||
cdef extern from "cantera/extensions/PythonHandle.h" namespace "Cantera":
|
||||
cdef cppclass CxxExternalHandle "Cantera::ExternalHandle":
|
||||
pass
|
||||
|
||||
cdef cppclass CxxPythonHandle "Cantera::PythonHandle" (CxxExternalHandle):
|
||||
CxxPythonHandle(PyObject*, cbool)
|
||||
|
||||
|
||||
cdef extern from "cantera/base/Solution.h" namespace "Cantera":
|
||||
cdef cppclass CxxKinetics "Cantera::Kinetics"
|
||||
cdef cppclass CxxTransport "Cantera::Transport"
|
||||
@ -50,6 +58,7 @@ cdef extern from "cantera/base/Solution.h" namespace "Cantera":
|
||||
CxxAnyMap parameters(cbool) except +translate_exception
|
||||
size_t nAdjacent()
|
||||
shared_ptr[CxxSolution] adjacent(size_t)
|
||||
void holdExternalHandle(string&, shared_ptr[CxxExternalHandle])
|
||||
|
||||
cdef shared_ptr[CxxSolution] CxxNewSolution "Cantera::Solution::create" ()
|
||||
cdef shared_ptr[CxxSolution] newSolution (
|
||||
|
@ -88,17 +88,20 @@ cdef class _SolutionBase:
|
||||
# Transport model: "" is a sentinel value to use the default model
|
||||
transport = kwargs.get("transport_model", "")
|
||||
|
||||
# Parse YAML input
|
||||
if infile or yaml:
|
||||
# Parse YAML input
|
||||
self._init_yaml(infile, name, adjacent, yaml, transport)
|
||||
self._selected_species = np.ndarray(0, dtype=np.uint64)
|
||||
return
|
||||
else:
|
||||
# Assign base and set managers
|
||||
_assign_Solution(self, CxxNewSolution(), True)
|
||||
self._init_parts(thermo, species, kinetics, transport, adjacent, reactions)
|
||||
|
||||
# Assign base and set managers
|
||||
_assign_Solution(self, CxxNewSolution(), True)
|
||||
self._init_parts(thermo, species, kinetics, transport, adjacent, reactions)
|
||||
self._selected_species = np.ndarray(0, dtype=np.uint64)
|
||||
|
||||
cdef shared_ptr[CxxExternalHandle] handle
|
||||
handle.reset(new CxxPythonHandle(<PyObject*>self, True))
|
||||
self.base.holdExternalHandle(stringify("python-Solution"), handle)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if isinstance(self, Transport) and kwargs.get("init", True):
|
||||
assert self.transport is not NULL
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "cantera/base/Solution.h"
|
||||
#include "cantera/base/Interface.h"
|
||||
#include "cantera/base/ExtensionManager.h"
|
||||
#include "cantera/thermo/ThermoPhase.h"
|
||||
#include "cantera/thermo/ThermoFactory.h"
|
||||
#include "cantera/kinetics/Kinetics.h"
|
||||
@ -45,6 +46,9 @@ void Solution::setThermo(shared_ptr<ThermoPhase> thermo) {
|
||||
|
||||
void Solution::setKinetics(shared_ptr<Kinetics> kinetics) {
|
||||
m_kinetics = kinetics;
|
||||
if (m_kinetics) {
|
||||
m_kinetics->setRoot(shared_from_this());
|
||||
}
|
||||
}
|
||||
|
||||
void Solution::setTransport(shared_ptr<Transport> transport) {
|
||||
@ -133,6 +137,21 @@ void Solution::setSource(const std::string& source) {
|
||||
m_header.setMetadata("filename", filename);
|
||||
}
|
||||
|
||||
void Solution::holdExternalHandle(const std::string& name,
|
||||
shared_ptr<ExternalHandle> handle)
|
||||
{
|
||||
m_externalHandles[name] = handle;
|
||||
}
|
||||
|
||||
shared_ptr<ExternalHandle> Solution::getExternalHandle(const std::string& name) const
|
||||
{
|
||||
if (m_externalHandles.count(name)) {
|
||||
return m_externalHandles.at(name);
|
||||
} else {
|
||||
return shared_ptr<ExternalHandle>();
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<Solution> newSolution(const std::string& infile,
|
||||
const std::string& name,
|
||||
const std::string& transport,
|
||||
|
@ -4,6 +4,7 @@
|
||||
// at https://cantera.org/license.txt for license and copyright information.
|
||||
|
||||
#include "cantera/extensions/PythonExtensionManager.h"
|
||||
#include "cantera/extensions/PythonHandle.h"
|
||||
|
||||
#include "cantera/kinetics/ReactionRateFactory.h"
|
||||
#include "cantera/kinetics/ReactionRateDelegator.h"
|
||||
@ -21,19 +22,6 @@ using namespace std;
|
||||
|
||||
namespace {
|
||||
|
||||
class PythonHandle : public Cantera::ExternalHandle
|
||||
{
|
||||
public:
|
||||
explicit PythonHandle(PyObject* obj) : m_obj(obj) {}
|
||||
|
||||
~PythonHandle() {
|
||||
Py_XDECREF(m_obj);
|
||||
}
|
||||
|
||||
private:
|
||||
PyObject* m_obj;
|
||||
};
|
||||
|
||||
|
||||
std::string getPythonExceptionInfo()
|
||||
{
|
||||
@ -80,6 +68,7 @@ void checkPythonError(bool condition, const std::string& message) {
|
||||
namespace Cantera
|
||||
{
|
||||
|
||||
|
||||
bool PythonExtensionManager::s_imported = false;
|
||||
|
||||
PythonExtensionManager::PythonExtensionManager()
|
||||
@ -201,7 +190,7 @@ void PythonExtensionManager::registerPythonRateBuilder(
|
||||
delegator->setParameters(params, units);
|
||||
|
||||
// The delegator is responsible for eventually deleting the Python object
|
||||
delegator->holdExternalHandle(make_shared<PythonHandle>(extRate));
|
||||
delegator->holdExternalHandle(make_shared<PythonHandle>(extRate, false));
|
||||
return delegator.release();
|
||||
};
|
||||
ReactionRateFactory::factory()->reg(rateName, builder);
|
||||
|
Loading…
Reference in New Issue
Block a user