diff --git a/interfaces/cython/cantera/__init__.py b/interfaces/cython/cantera/__init__.py index 656ebae40..4c7ecf935 100644 --- a/interfaces/cython/cantera/__init__.py +++ b/interfaces/cython/cantera/__init__.py @@ -1,3 +1 @@ -from .solution import * -from .constants import * -from .mixture import * +from ._cantera import * diff --git a/interfaces/cython/cantera/substance.pxd b/interfaces/cython/cantera/_cantera.pxd similarity index 59% rename from interfaces/cython/cantera/substance.pxd rename to interfaces/cython/cantera/_cantera.pxd index e92bbe904..321dca388 100644 --- a/interfaces/cython/cantera/substance.pxd +++ b/interfaces/cython/cantera/_cantera.pxd @@ -1,5 +1,14 @@ from libcpp.vector cimport vector -from utils cimport * +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 extern from "cantera/thermo/ThermoPhase.h" namespace "Cantera": cdef cppclass CxxThermoPhase "Cantera::ThermoPhase": @@ -11,34 +20,50 @@ cdef extern from "cantera/thermo/ThermoPhase.h" namespace "Cantera": 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/transport/DustyGasTransport.h" namespace "Cantera": + cdef cppclass CxxDustyGasTransport "Cantera::DustyGasTransport": + void setPorosity(double) except + + + +cdef extern from "cantera/equil/MultiPhase.h" namespace "Cantera": + cdef cppclass CxxMultiPhase "Cantera::MultiPhase": + CxxMultiPhase() + void addPhase(CxxThermoPhase*, double) except + + void init() except + + double nSpecies() + void setTemperature(double) + double temperature() + void setPressure(double) + double pressure() 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 string stringify(x) cdef class _SolutionBase: cdef CxxThermoPhase* thermo cdef CxxKinetics* kinetics cdef CxxTransport* transport + +cdef class Mixture: + cdef CxxMultiPhase* mix + cdef list _phases diff --git a/interfaces/cython/cantera/_cantera.pyx b/interfaces/cython/cantera/_cantera.pyx new file mode 100644 index 000000000..645c3ca6c --- /dev/null +++ b/interfaces/cython/cantera/_cantera.pyx @@ -0,0 +1,17 @@ +import numpy as np +cimport numpy as np + +from cython.operator cimport dereference as deref + +from _cantera cimport * + +include "utils.pyx" +include "constants.pyx" + +include "base.pyx" +include "thermo.pyx" +include "kinetics.pyx" +include "transport.pyx" +include "composite.pyx" + +include "mixture.pyx" diff --git a/interfaces/cython/cantera/base.pyx b/interfaces/cython/cantera/base.pyx new file mode 100644 index 000000000..395c9596a --- /dev/null +++ b/interfaces/cython/cantera/base.pyx @@ -0,0 +1,38 @@ +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 diff --git a/interfaces/cython/cantera/composite.pyx b/interfaces/cython/cantera/composite.pyx new file mode 100644 index 000000000..3217c0728 --- /dev/null +++ b/interfaces/cython/cantera/composite.pyx @@ -0,0 +1,4 @@ +class Solution(ThermoPhase, Kinetics, Transport): + def __init__(self, *args, **kwars): + pass + diff --git a/interfaces/cython/cantera/kinetics.pyx b/interfaces/cython/cantera/kinetics.pyx new file mode 100644 index 000000000..cfd63d4ce --- /dev/null +++ b/interfaces/cython/cantera/kinetics.pyx @@ -0,0 +1,4 @@ +cdef class Kinetics(_SolutionBase): + property nReactions: + def __get__(self): + return self.kinetics.nReactions() diff --git a/interfaces/cython/cantera/mixture.pxd b/interfaces/cython/cantera/mixture.pxd deleted file mode 100644 index ace3dfa1a..000000000 --- a/interfaces/cython/cantera/mixture.pxd +++ /dev/null @@ -1,16 +0,0 @@ -from solution cimport * - -cdef extern from "cantera/equil/MultiPhase.h" namespace "Cantera": - cdef cppclass CxxMultiPhase "Cantera::MultiPhase": - CxxMultiPhase() - void addPhase(CxxThermoPhase*, double) except + - void init() except + - double nSpecies() - void setTemperature(double) - double temperature() - void setPressure(double) - double pressure() - -cdef class Mixture: - cdef CxxMultiPhase* mix - cdef list _phases diff --git a/interfaces/cython/cantera/mixture.pyx b/interfaces/cython/cantera/mixture.pyx index 6cab45f08..351300d15 100644 --- a/interfaces/cython/cantera/mixture.pyx +++ b/interfaces/cython/cantera/mixture.pyx @@ -1,5 +1,3 @@ -from mixture cimport * - cdef class Mixture: def __cinit__(self, phases): self.mix = new CxxMultiPhase() diff --git a/interfaces/cython/cantera/substance.pyx b/interfaces/cython/cantera/substance.pyx deleted file mode 100644 index eb5a5ef99..000000000 --- a/interfaces/cython/cantera/substance.pyx +++ /dev/null @@ -1,88 +0,0 @@ -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() - - property temperature: - def __get__(self): - return self.thermo.temperature() - - 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 diff --git a/interfaces/cython/cantera/thermo.pyx b/interfaces/cython/cantera/thermo.pyx new file mode 100644 index 000000000..d9f86e525 --- /dev/null +++ b/interfaces/cython/cantera/thermo.pyx @@ -0,0 +1,24 @@ +cdef class ThermoPhase(_SolutionBase): + property nSpecies: + def __get__(self): + return self.thermo.nSpecies() + + property pressure: + def __get__(self): + return self.thermo.pressure() + + property temperature: + def __get__(self): + return self.thermo.temperature() + + 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 diff --git a/interfaces/cython/cantera/transport.pyx b/interfaces/cython/cantera/transport.pyx new file mode 100644 index 000000000..23b80d552 --- /dev/null +++ b/interfaces/cython/cantera/transport.pyx @@ -0,0 +1,4 @@ +cdef class Transport(_SolutionBase): + property viscosity: + def __get__(self): + return self.transport.viscosity() diff --git a/interfaces/cython/cantera/utils.pxd b/interfaces/cython/cantera/utils.pxd deleted file mode 100644 index 841660ee4..000000000 --- a/interfaces/cython/cantera/utils.pxd +++ /dev/null @@ -1,14 +0,0 @@ -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) diff --git a/interfaces/cython/cantera/utils.pyx b/interfaces/cython/cantera/utils.pyx index a7a91c60e..167361c27 100644 --- a/interfaces/cython/cantera/utils.pyx +++ b/interfaces/cython/cantera/utils.pyx @@ -1,5 +1,3 @@ -from utils cimport * - cdef string stringify(x): """ Converts Python strings to std::string. """ # This method works with both Python 2.x and 3.x. diff --git a/interfaces/cython/setup.py.in b/interfaces/cython/setup.py.in index 954b844f5..d8b3f7e28 100644 --- a/interfaces/cython/setup.py.in +++ b/interfaces/cython/setup.py.in @@ -9,21 +9,14 @@ if os.name == 'nt': else: dataFiles.append('libcantera_shared.so') -exts = [] - -def addExtension(name): - exts.append(Extension("cantera.%s" % name, - ["cantera/%s.pyx" % name], - include_dirs=@py_include_dirs@, - language="c++", - libraries=@py_cantera_libs@, - library_dirs=@py_libdirs@, - extra_link_args=@py_extra_link_args@)) - -addExtension('solution') -addExtension('mixture') -addExtension('utils') -addExtension('constants') +exts = [Extension("cantera._cantera", + ["cantera/_cantera.pyx"], + include_dirs=@py_include_dirs@, + language="c++", + libraries=@py_cantera_libs@, + library_dirs=@py_libdirs@, + extra_compile_args=@py_extra_compiler_args@, + extra_link_args=@py_extra_link_args@)] setup(name="Cantera", version="@cantera_version@", diff --git a/src/python/SConscript b/src/python/SConscript index 621dcd32a..749952c14 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -117,13 +117,15 @@ libDirs = ('../../build/lib', localenv['sundials_libdir'], localenv['boost_lib_dir']) localenv['py_include_dirs'] = repr([x for x in incDirs if x]) -localenv['py_cantera_libs'] = repr(localenv['cantera_shared_libs']) +localenv['py_cantera_libs'] = repr(localenv['cantera_libs']) localenv['py_libdirs'] = repr([x for x in libDirs if x]) if localenv['CC'] == 'cl': localenv['py_extra_link_args'] = repr([]) + localenv['py_extra_compiler_args'] = repr(['/EHsc']) else: localenv['py_extra_link_args'] = repr(['-Wl,-rpath=$$ORIGIN']) + localenv['py_extra_compiler_args'] = repr([]) make_setup = localenv.SubstFile('#interfaces/cython/setup.py', '#interfaces/cython/setup.py.in')