Proof-of-concept for a Python interface written using Cython
This module is compatible with both Python 2 and Python 3. Unlike the existing Python module, this module directly utilizes the Cantera C++ interface, bypassing the "clib" compatibility layer, as well as all of the direct use of the Python C API. Currently, this contains just enough to instantiate a ThermoPhase object from an XML input file.
This commit is contained in:
parent
ea16489a82
commit
8afc669b67
9 changed files with 202 additions and 0 deletions
|
|
@ -790,6 +790,11 @@ std::string getChildValue(const Cantera::XML_Node& parent,
|
|||
void get_CTML_Tree(Cantera::XML_Node* node, const std::string file,
|
||||
const int debug = 0);
|
||||
|
||||
//! Read an ctml file from a file and fill up an XML tree.
|
||||
//! @param file Name of the file
|
||||
//! @return Root of the tree
|
||||
Cantera::XML_Node getCtmlTree(const std::string file);
|
||||
|
||||
//! Convert a cti file into a ctml file
|
||||
/*!
|
||||
*
|
||||
|
|
|
|||
3
interfaces/cython/.gitignore
vendored
Normal file
3
interfaces/cython/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
cantera/*.cpp
|
||||
cantera/*.c
|
||||
setup.py
|
||||
1
interfaces/cython/cantera/__init__.py
Normal file
1
interfaces/cython/cantera/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
from .solution import *
|
||||
43
interfaces/cython/cantera/substance.pxd
Normal file
43
interfaces/cython/cantera/substance.pxd
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
from libcpp.vector cimport vector
|
||||
from utils cimport *
|
||||
|
||||
cdef extern from "cantera/thermo/ThermoPhase.h" namespace "Cantera":
|
||||
cdef cppclass CxxThermoPhase "Cantera::ThermoPhase":
|
||||
CxxThermoPhase()
|
||||
double pressure() except +
|
||||
void setMoleFractions(double*) except +
|
||||
void getMassFractions(double*) except +
|
||||
int nSpecies()
|
||||
XML_Node& xml()
|
||||
|
||||
|
||||
cdef extern from "cantera/kinetics/Kinetics.h" namespace "Cantera":
|
||||
cdef cppclass CxxKinetics "Cantera::Kinetics":
|
||||
CxxKinetics()
|
||||
int nReactions()
|
||||
|
||||
|
||||
cdef extern from "cantera/transport/TransportBase.h" namespace "Cantera":
|
||||
cdef cppclass CxxTransport "Cantera::Transport":
|
||||
CxxTransport(CxxThermoPhase*)
|
||||
double viscosity() except +
|
||||
|
||||
|
||||
cdef extern from "cantera/thermo/ThermoFactory.h" namespace "Cantera":
|
||||
cdef CxxThermoPhase* newPhase(string, string) except +
|
||||
cdef CxxThermoPhase* newPhase(XML_Node&) except +
|
||||
|
||||
|
||||
cdef extern from "cantera/kinetics/KineticsFactory.h" namespace "Cantera":
|
||||
cdef CxxKinetics* newKineticsMgr(XML_Node&, vector[CxxThermoPhase*]) except +
|
||||
|
||||
|
||||
cdef extern from "cantera/transport/TransportFactory.h" namespace "Cantera":
|
||||
cdef CxxTransport* newDefaultTransportMgr(CxxThermoPhase*) except +
|
||||
cdef CxxTransport* newTransportMgr(string, CxxThermoPhase*) except +
|
||||
|
||||
|
||||
cdef class _SolutionBase:
|
||||
cdef CxxThermoPhase* thermo
|
||||
cdef CxxKinetics* kinetics
|
||||
cdef CxxTransport* transport
|
||||
84
interfaces/cython/cantera/substance.pyx
Normal file
84
interfaces/cython/cantera/substance.pyx
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
import numpy as np
|
||||
cimport numpy as np
|
||||
|
||||
from cython.operator cimport dereference as deref
|
||||
|
||||
from utils cimport *
|
||||
|
||||
cdef class _SolutionBase:
|
||||
def __cinit__(self, infile, phaseid=''):
|
||||
rootNode = getCtmlTree(stringify(infile))
|
||||
|
||||
# Get XML data
|
||||
cdef XML_Node* phaseNode
|
||||
if phaseid:
|
||||
phaseNode = rootNode.findID(stringify(phaseid))
|
||||
else:
|
||||
phaseNode = rootNode.findByName(stringify('phase'))
|
||||
if phaseNode is NULL:
|
||||
raise ValueError("Couldn't read phase node from XML file")
|
||||
|
||||
# Thermo
|
||||
if isinstance(self, ThermoPhase):
|
||||
self.thermo = newPhase(deref(phaseNode))
|
||||
else:
|
||||
self.thermo = NULL
|
||||
|
||||
# Kinetics
|
||||
cdef vector[CxxThermoPhase*] v
|
||||
|
||||
if isinstance(self, Kinetics):
|
||||
v.push_back(self.thermo)
|
||||
self.kinetics = newKineticsMgr(deref(phaseNode), v)
|
||||
else:
|
||||
self.kinetics = NULL
|
||||
|
||||
# Transport
|
||||
if isinstance(self, Transport):
|
||||
self.transport = newDefaultTransportMgr(self.thermo)
|
||||
else:
|
||||
self.transport = NULL
|
||||
|
||||
def __dealloc__(self):
|
||||
del self.thermo
|
||||
del self.kinetics
|
||||
del self.transport
|
||||
|
||||
|
||||
cdef class ThermoPhase(_SolutionBase):
|
||||
property nSpecies:
|
||||
def __get__(self):
|
||||
return self.thermo.nSpecies()
|
||||
|
||||
property pressure:
|
||||
def __get__(self):
|
||||
return self.thermo.pressure()
|
||||
|
||||
def setMoleFractions(self, X):
|
||||
if len(X) != self.nSpecies:
|
||||
raise ValueError("Mole fraction array has incorrect length")
|
||||
cdef np.ndarray[np.double_t, ndim=1] X_c = np.ascontiguousarray(X, dtype=np.double)
|
||||
self.thermo.setMoleFractions(&X_c[0])
|
||||
|
||||
property massFractions:
|
||||
def __get__(self):
|
||||
cdef np.ndarray[np.double_t, ndim=1] X_c = np.empty(self.nSpecies)
|
||||
self.thermo.getMassFractions(&X_c[0])
|
||||
return X_c
|
||||
|
||||
|
||||
cdef class Kinetics(_SolutionBase):
|
||||
property nReactions:
|
||||
def __get__(self):
|
||||
return self.kinetics.nReactions()
|
||||
|
||||
|
||||
cdef class Transport(_SolutionBase):
|
||||
property viscosity:
|
||||
def __get__(self):
|
||||
return self.transport.viscosity()
|
||||
|
||||
|
||||
class Solution(ThermoPhase, Kinetics, Transport):
|
||||
def __init__(self, *args, **kwars):
|
||||
pass
|
||||
14
interfaces/cython/cantera/utils.pxd
Normal file
14
interfaces/cython/cantera/utils.pxd
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
from libcpp.string cimport string
|
||||
|
||||
cdef extern from "cantera/base/xml.h" namespace "Cantera":
|
||||
cdef cppclass XML_Node:
|
||||
XML_Node* findByName(string)
|
||||
XML_Node* findID(string)
|
||||
int nChildren()
|
||||
|
||||
|
||||
cdef extern from "cantera/base/ctml.h" namespace "ctml":
|
||||
XML_Node getCtmlTree(string) except +
|
||||
|
||||
|
||||
cdef string stringify(x)
|
||||
7
interfaces/cython/cantera/utils.pyx
Normal file
7
interfaces/cython/cantera/utils.pyx
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
from utils cimport *
|
||||
|
||||
cdef string stringify(x):
|
||||
""" Converts Python strings to std::string. """
|
||||
# This method works with both Python 2.x and 3.x.
|
||||
tmp = bytes(x.encode())
|
||||
return string(tmp)
|
||||
37
interfaces/cython/setup.py.in
Normal file
37
interfaces/cython/setup.py.in
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import os
|
||||
from distutils.core import setup, Extension
|
||||
from distutils.sysconfig import get_config_var
|
||||
from Cython.Distutils import build_ext
|
||||
|
||||
dataFiles = ['_cantera%s' % get_config_var('SO')]
|
||||
if os.name == 'nt':
|
||||
dataFiles.append('cantera_shared.dll')
|
||||
else:
|
||||
dataFiles.append('libcantera_shared.so')
|
||||
|
||||
canteraExtensions = []
|
||||
|
||||
def addExtension(name):
|
||||
canteraExtensions.append(Extension("cantera.%s" % name,
|
||||
["cantera/%s.pyx" % name],
|
||||
include_dirs=[".", "../../include"],
|
||||
language="c++",
|
||||
libraries=['cantera_shared','sundials_cvodes','sundials_idas','sundials_nvecserial','lapack','blas'],
|
||||
library_dirs=['../../build/lib'],
|
||||
extra_link_args=['-Wl,-rpath=$ORIGIN']))
|
||||
|
||||
addExtension('solution')
|
||||
addExtension('utils')
|
||||
|
||||
setup(name="Cantera",
|
||||
version="2.1a1",
|
||||
description="The Cantera Python Interface",
|
||||
long_description="""
|
||||
""",
|
||||
author="Raymond Speth",
|
||||
author_email="speth@mit.edu",
|
||||
url="http://code.google.com/p/cantera",
|
||||
packages = ["cantera"],
|
||||
cmdclass = {'build_ext': build_ext},
|
||||
ext_modules = canteraExtensions,
|
||||
package_data = {'cantera': dataFiles})
|
||||
|
|
@ -279,4 +279,12 @@ void get_CTML_Tree(Cantera::XML_Node* rootPtr, const std::string file, const int
|
|||
rootPtr->build(fin);
|
||||
fin.close();
|
||||
}
|
||||
|
||||
Cantera::XML_Node getCtmlTree(const std::string file)
|
||||
{
|
||||
Cantera::XML_Node root;
|
||||
get_CTML_Tree(&root, file);
|
||||
return root;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue