Cantera/Extending C API: Difference between revisions
From charlesreid1
| (8 intermediate revisions by the same user not shown) | |||
| Line 2: | Line 2: | ||
To illustrate this procedure, I'll be adding a method to Cantera's ReactorBase class to remove all of the walls in a reactor. This article covers the following steps: | To illustrate this procedure, I'll be adding a method to Cantera's ReactorBase class to remove all of the walls in a reactor. This article covers the following steps: | ||
* Adding a C++ function to the ReactorBase object | * Adding a C++ function to the ReactorBase object (via <code>/path/to/cantera/src/zeroD/ReactorBase.cpp</code> and <code>/path/to/cantera/include/cantera/zeroD/ReactorBase.h</code>) | ||
* Extending Cantera's C API to include the new function | * Extending Cantera's C API to include the new function (via <code>/path/to/cantera/src/clib/ctreactor.{cpp,h}</code>) | ||
* Extending Cantera's Python-C interface to utilize the new function | * Extending Cantera's Python-C interface to utilize the new function (via <code>/path/to/cantera/src/python/{ctreactor_methods.cpp,methods.h}</code>) | ||
* Calling the method from Python | * Calling the new method from Cantera's Python classes (via <code>/path/to/cantera/interfaces/python/Cantera/Reactor.py</code>) | ||
=Add New C++ Method= | =Add New C++ Method= | ||
==C++ Code First== | |||
I'll add the following two methods to ReactorBase.cpp, to allow me to either remove a specific wall, or remove all walls: | I'll add the following two methods to ReactorBase.cpp, to allow me to either remove a specific wall, or remove all walls: | ||
| Line 15: | Line 19: | ||
--- ReactorBase.cpp (revision 2) | --- ReactorBase.cpp (revision 2) | ||
+++ ReactorBase.cpp (working copy) | +++ ReactorBase.cpp (working copy) | ||
@@ -72,6 +72, | @@ -72,6 +72,36 @@ | ||
m_nwalls++; | m_nwalls++; | ||
} | } | ||
| Line 30: | Line 34: | ||
+ } | + } | ||
+ } | + } | ||
+ m_nwalls--; | |||
+} | +} | ||
+ | + | ||
+void ReactorBase::removeWalls() | +void ReactorBase::removeWalls() | ||
+{ | +{ | ||
+ | + m_lr.clear(); | ||
+ | + m_wall.clear(); | ||
+ | + m_nwalls = 0; | ||
+} | +} | ||
+ | + | ||
| Line 48: | Line 49: | ||
</pre> | </pre> | ||
==Header File Next== | |||
Modify the ReactorBase header file as follows: | |||
<pre> | <pre> | ||
| Line 66: | Line 69: | ||
</pre> | </pre> | ||
Once you've added these changes, | ==Recompile== | ||
Once you've added these changes, recompile Cantera. If you're using my scons configure/build script from the [[Cantera2]] page, you'll just follow the instructions - delete cantera.conf, and re-run the scons configure/build script. | |||
=Extend Cantera's C API to Include New Method= | =Extend Cantera's C API to Include New Method= | ||
==C Code First== | |||
Cantera uses a C-language API (application programming interface) to provide a way for non-C++ programs (Fortran, Python, Matlab, etc.) to interface with Cantera. This interface is contained in <code>/path/to/cantera/src/clib</code>. | Cantera uses a C-language API (application programming interface) to provide a way for non-C++ programs (Fortran, Python, Matlab, etc.) to interface with Cantera. This interface is contained in <code>/path/to/cantera/src/clib</code>. | ||
| Line 98: | Line 107: | ||
int reactornet_new() | int reactornet_new() | ||
</pre> | </pre> | ||
==Then The Header File== | |||
Next, add the corresponding entry to the header file: | Next, add the corresponding entry to the header file: | ||
| Line 115: | Line 126: | ||
Now the Cantera C API has a way to call the ReactorBase::removeWalls() function. The last step necessary to call this method from Python is to create the glue between Python and the C API. | Now the Cantera C API has a way to call the ReactorBase::removeWalls() function. The last step necessary to call this method from Python is to create the glue between Python and the C API. | ||
=Extend Cantera's C-Python Interface to Include New Method= | =Extend Cantera's C-Python Interface to Include New Method= | ||
==Modify C Glue== | |||
The C-Python interface glue is all contained in <code>/path/to/cantera/src/python</code>. The code utilizing the C API for reactors is in <code>ctreactor_methods.cpp</code>. A new Python method, called from C, is defined as follows: | The C-Python interface glue is all contained in <code>/path/to/cantera/src/python</code>. The code utilizing the C API for reactors is in <code>ctreactor_methods.cpp</code>. A new Python method, called from C, is defined as follows: | ||
| Line 147: | Line 162: | ||
</pre> | </pre> | ||
This defines a Python method for calling the reactor removeWalls() function. As before, we'll need to create a corresponding entry in the header file: | This defines a Python method for calling the reactor removeWalls() function. | ||
==Modify Header Glue== | |||
As before, we'll need to create a corresponding entry in the header file: | |||
<pre> | <pre> | ||
| Line 166: | Line 185: | ||
* Python method py_reactor_removeWalls() calls C (Cantera API) method reactor_removeWalls() | * Python method py_reactor_removeWalls() calls C (Cantera API) method reactor_removeWalls() | ||
* C (Cantera API) method reactor_removeWalls() calls C++ method ReactorBase::removeWalls() | * C (Cantera API) method reactor_removeWalls() calls C++ method ReactorBase::removeWalls() | ||
=Call New Method from Python Classes= | =Call New Method from Python Classes= | ||
| Line 174: | Line 195: | ||
<pre> | <pre> | ||
=================================================================== | |||
--- interfaces/python/Cantera/Reactor.py (revision 2) | |||
+++ interfaces/python/Cantera/Reactor.py (working copy) | |||
@@ -336,6 +336,11 @@ | |||
else: | |||
return self._paramid[n] | |||
+ def removeWalls(self): | |||
+ _cantera.reactor_removeWalls(self.reactor_id()) | |||
+ self._walls = [] | |||
+ | |||
+ | |||
_reactorcount = 0 | |||
_reservoircount = 0 | |||
</pre> | </pre> | ||
We can test the new functionality with a simple test script: | We can test the new functionality with a simple test script in Python: | ||
< | <source lang="python"> | ||
# First, initialize a reactor with surface kinetics | |||
z = importPhase(' | z = importPhase('GasSurfaceMech.xml','gas') | ||
surf = importInterface(' | surf = importInterface('GasSurfaceMech.xml','catSurf',[z]) | ||
env=Reservoir(Air()) | env=Reservoir(Air()) | ||
r=Reactor(z) | r=Reactor(z) | ||
# Add a single wall and remove it | |||
w1 = Wall(left=env,right=r,A=1.0,kinetics=[None,surf]) | |||
r.removeWalls() | |||
# Add multiple walls and remove all of them | |||
w2 = Wall(left=env,right=r,A=2.0,kinetics=[None,surf]) | |||
w3 = Wall(left=env,right=r,A=3.0,kinetics=[None,surf]) | |||
w4 = Wall(left=env,right=r,A=4.0,kinetics=[None,surf]) | |||
r.removeWalls() | r.removeWalls() | ||
</ | |||
# This should be 0 | |||
print len(r._walls) | |||
</source> | |||
=Flags= | |||
{{CanteraFlag}} | |||
Latest revision as of 08:57, 17 April 2017
This article discusses extending Cantera's C API. This allows you to create a new class or function in Cantera, and create a handle for that object or function from Cantera's Python API. (Note: this guide covers the API for Cantera 2.0.)
To illustrate this procedure, I'll be adding a method to Cantera's ReactorBase class to remove all of the walls in a reactor. This article covers the following steps:
- Adding a C++ function to the ReactorBase object (via
/path/to/cantera/src/zeroD/ReactorBase.cppand/path/to/cantera/include/cantera/zeroD/ReactorBase.h) - Extending Cantera's C API to include the new function (via
/path/to/cantera/src/clib/ctreactor.{cpp,h}) - Extending Cantera's Python-C interface to utilize the new function (via
/path/to/cantera/src/python/{ctreactor_methods.cpp,methods.h}) - Calling the new method from Cantera's Python classes (via
/path/to/cantera/interfaces/python/Cantera/Reactor.py)
Add New C++ Method
C++ Code First
I'll add the following two methods to ReactorBase.cpp, to allow me to either remove a specific wall, or remove all walls:
===================================================================
--- ReactorBase.cpp (revision 2)
+++ ReactorBase.cpp (working copy)
@@ -72,6 +72,36 @@
m_nwalls++;
}
+void ReactorBase::removeWall(Wall& w)
+{
+ vector_int::iterator iL = m_lr.begin();
+ for( std::vector<Wall*>::iterator iW = m_wall.begin();
+ iW != m_wall.end();
+ ++iW, ++iL ) {
+ if ( (*iW) == &w) {
+ m_wall.erase( iW );
+ m_lr.erase( iL );
+ }
+ }
+ m_nwalls--;
+}
+
+void ReactorBase::removeWalls()
+{
+ m_lr.clear();
+ m_wall.clear();
+ m_nwalls = 0;
+}
+
Wall& ReactorBase::wall(size_t n)
{
return *m_wall[n];
Header File Next
Modify the ReactorBase header file as follows:
===================================================================
--- include/cantera/zeroD/ReactorBase.h (revision 2)
+++ include/cantera/zeroD/ReactorBase.h (working copy)
@@ -91,6 +91,11 @@
}
void addWall(Wall& w, int lr);
+
+ void removeWall(Wall& w);
+
+ void removeWalls();
+
Wall& wall(size_t n);
Recompile
Once you've added these changes, recompile Cantera. If you're using my scons configure/build script from the Cantera2 page, you'll just follow the instructions - delete cantera.conf, and re-run the scons configure/build script.
Extend Cantera's C API to Include New Method
C Code First
Cantera uses a C-language API (application programming interface) to provide a way for non-C++ programs (Fortran, Python, Matlab, etc.) to interface with Cantera. This interface is contained in /path/to/cantera/src/clib.
In the main code file (ctreactor.cpp), there are sections for reactor networks, reactors, walls, etc. Find the section for reactor methods, and add the following method:
===================================================================
--- ctreactor.cpp (revision 2)
+++ ctreactor.cpp (working copy)
@@ -282,7 +282,18 @@
}
}
+ int reactor_removeWalls( int i )
+ {
+ try {
+ ReactorBase* r = &ReactorCabinet::item(i);
+ ((Reactor*)r)->removeWalls(); //((Reactor*)r)->addSensitivityReaction(rxn);
+ return 0;
+ } catch (...) {
+ return handleAllExceptions(-1, ERR);
+ }
+ }
+
// reactor networks
int reactornet_new()
Then The Header File
Next, add the corresponding entry to the header file:
===================================================================
--- ctreactor.h (revision 2)
+++ ctreactor.h (working copy)
@@ -28,6 +28,7 @@
CANTERA_CAPI double reactor_pressure(int i);
CANTERA_CAPI double reactor_massFraction(int i, int k);
CANTERA_CAPI size_t reactor_nSensParams(int i);
+ CANTERA_CAPI int reactor_removeWalls(int i);
CANTERA_CAPI int reactor_addSensitivityReaction(int i, int rxn);
CANTERA_CAPI int flowReactor_setMassFlowRate(int i, double mdot);
Now the Cantera C API has a way to call the ReactorBase::removeWalls() function. The last step necessary to call this method from Python is to create the glue between Python and the C API.
Extend Cantera's C-Python Interface to Include New Method
Modify C Glue
The C-Python interface glue is all contained in /path/to/cantera/src/python. The code utilizing the C API for reactors is in ctreactor_methods.cpp. A new Python method, called from C, is defined as follows:
===================================================================
--- ctreactor_methods.cpp (revision 2)
+++ ctreactor_methods.cpp (working copy)
@@ -127,6 +127,21 @@
}
+
+ static PyObject*
+py_reactor_removeWalls(PyObject* self, PyObject* args)
+{
+ int _val;
+ int i;
+ if (!PyArg_ParseTuple(args,"reactor_removeWalls", &i)) {
+ return NULL;
+ }
+ _val = reactor_removeWalls(i);
+ if (int(_val) == -1) {
+ return reportCanteraError();
+ }
+ return Py_BuildValue("i",_val);
+}
static PyObject*
py_flowReactor_setMassFlowRate(PyObject* self, PyObject* args)
{
This defines a Python method for calling the reactor removeWalls() function.
Modify Header Glue
As before, we'll need to create a corresponding entry in the header file:
===================================================================
--- methods.h (revision 2)
+++ methods.h (working copy)
@@ -240,6 +240,7 @@
{"reactor_massFraction", py_reactor_massFraction, METH_VARARGS},
{"reactor_nSensParams", py_reactor_nSensParams, METH_VARARGS},
{"reactor_addSensitivityReaction", py_reactor_addSensitivityReaction, METH_VARARGS},
+ {"reactor_removeWalls", py_reactor_removeWalls, METH_VARARGS},
{"flowReactor_setMassFlowRate", py_flowReactor_setMassFlowRate, METH_VARARGS},
{"reactornet_rtol", py_reactornet_rtol, METH_VARARGS},
{"reactornet_atol", py_reactornet_atol, METH_VARARGS},
The logical chain is now as follows:
- Python method py_reactor_removeWalls() calls C (Cantera API) method reactor_removeWalls()
- C (Cantera API) method reactor_removeWalls() calls C++ method ReactorBase::removeWalls()
Call New Method from Python Classes
Now that we've created a Python handle for the C API of the C++ code, we have to call the Python handle from the Python code.
We'll edit Cantera's Python class for Reactors and add a new removeWalls() method. Start by finding Cantera's Python classes, in /path/to/cantera/interfaces/python/Cantera, and add a new method to the Reactor class:
===================================================================
--- interfaces/python/Cantera/Reactor.py (revision 2)
+++ interfaces/python/Cantera/Reactor.py (working copy)
@@ -336,6 +336,11 @@
else:
return self._paramid[n]
+ def removeWalls(self):
+ _cantera.reactor_removeWalls(self.reactor_id())
+ self._walls = []
+
+
_reactorcount = 0
_reservoircount = 0
We can test the new functionality with a simple test script in Python:
# First, initialize a reactor with surface kinetics
z = importPhase('GasSurfaceMech.xml','gas')
surf = importInterface('GasSurfaceMech.xml','catSurf',[z])
env=Reservoir(Air())
r=Reactor(z)
# Add a single wall and remove it
w1 = Wall(left=env,right=r,A=1.0,kinetics=[None,surf])
r.removeWalls()
# Add multiple walls and remove all of them
w2 = Wall(left=env,right=r,A=2.0,kinetics=[None,surf])
w3 = Wall(left=env,right=r,A=3.0,kinetics=[None,surf])
w4 = Wall(left=env,right=r,A=4.0,kinetics=[None,surf])
r.removeWalls()
# This should be 0
print len(r._walls)
Flags
| Cantera all pages on the wiki related to the Cantera combustion microkinetics and thermodynamics (a.k.a. "thermochemistry") software.
Cantera · Cantera Outline · Category:Cantera
Outline of Cantera topics: Cantera Outline · Cantera Outline/Brief Understanding Cantera's Structure: Cantera Structure Cantera from Matlab: Using_Cantera#Matlab Cantera from Python: Using_Cantera#Python Cantera from C++: Using_Cantera#C++ Cantera + Fipy (PDE Solver): Fipy and Cantera/Diffusion 1D Cantera Gas Objects: Cantera/Gases Cantera 1D Domains, Stacks: Cantera_One-D_Domains · Cantera_Stacks Cantera Gas Mixing: Cantera_Gas_Mixing
Topics in Combustion: Diffusion: Cantera/Diffusion · Cantera/Diffusion Coefficients Sensitivity Analysis: Cantera/Sensitivity Analysis Analysis of the Jacobian Matrix in Cantera: Jacobian_in_Cantera Chemical Equilibrium: Chemical_Equilibrium Kinetic Mechanisms: Cantera/Kinetic_Mechanisms Reactor Equations: Cantera/Reactor_Equations Differential vs. Integral Reactors: Cantera/Integral_and_Differential_Reactors Effect of Dilution on Adiabatic Flame Temperature: Cantera/Adiabatic_Flame_Temperature_Dilution
Topics in Catalysis: Cantera for Catalysis: Cantera_for_Catalysis Steps for Modeling 0D Multiphase Reactor: Cantera_Multiphase_Zero-D Reaction Rate Source Terms: Cantera/Reaction_Rate_Source_Terms Surface coverage: Cantera/Surface_Coverage Surface reactions: Cantera/Surface_Reactions
Cantera Input Files: Chemkin file format: Chemkin CTI files: Cantera/CTI_Files · Cantera/CTI_Files/Phases · Cantera/CTI_Files/Species · Cantera/CTI_Files/Reactions
Hacking Cantera: Pantera (monkey patches and convenience functions for Cantera): Pantera Extending Cantera's C API: Cantera/Extending_C_API Extending Cantera with Python Classes: Cantera/Adding Python Class Debugging Cantera: Cantera/Debugging_Cantera Debugging Cantera from Python: Cantera/Debugging_Cantera_from_Python Gas Mixing Functions: Cantera_Gas_Mixing Residence Time Reactor (new Cantera class): Cantera/ResidenceTimeReactor
Resources: Cantera Resources: Cantera Resources Cantera Lecture Notes: Cantera_Lecture
Category:Cantera · Category:Combustion Category:C++ · Category:Python Flags · Template:CanteraFlag · e |
| Installing Cantera notes on the wiki related to installing the Cantera thermochemistry software library.
Cantera Installation: Mac OS X 10.5 (Leopard): Installing_Cantera#Leopard Mac OS X 10.6 (Snow Leopard): Installing_Cantera#Snow_Leopard · Cantera2 Config Mac OS X 10.7 (Lion): Installing_Cantera#Lion Mac OS X 10.8 (Mountain Lion): Installing_Cantera#Mountain_Lion Ubuntu 12.04 (Precise Pangolin): Installing_Cantera#Ubuntu Windows XP: Installing_Cantera#Windows_XP Windows 7: Installing_Cantera#Windows_7
Cantera Preconfig: In old versions of Cantera, a preconfig file was used to specify library locations and options. Mac OS X 10.5 (Leopard) preconfig: Cantera_Preconfig/Leopard_Preconfig Mac OS X 10.6 (Snow Leopard) preconfig: Cantera_Preconfig/Snow_Leopard_Preconfig Mac OS X 10.8 (Mountain Lion) preconfig: Cantera_Config/MountainLion_SconsConfig Ubuntu 12.04 (Precise Pangolin) preconfig: Cantera_Config/Ubuntu1204_SconsConfig Flags · Template:InstallingCanteraFlag · e |