Compare commits

...

No commits in common. 'master' and 'gh-pages' have entirely different histories.

  1. 54
      .gitignore
  2. 21
      LICENSE
  3. 95
      README.md
  4. BIN
      images/bkg.png
  5. BIN
      images/blacktocat.png
  6. BIN
      images/body-bg.jpg
  7. BIN
      images/download-button.png
  8. BIN
      images/github-button.png
  9. BIN
      images/header-bg.jpg
  10. BIN
      images/highlight-bg.jpg
  11. BIN
      images/sidebar-bg.jpg
  12. 139
      index.html
  13. 1
      javascripts/main.js
  14. 17
      javascripts/scale.fix.js
  15. 170
      pantera/README.md
  16. 23
      pantera/__init__.py
  17. 51
      pantera/cantera_monkey_patches.py
  18. 5
      pantera/configurations/AutoignitionConfigs.py
  19. 5
      pantera/configurations/EquilibriumConfigs.py
  20. 130
      pantera/configurations/PC.md
  21. 74
      pantera/configurations/PanteraConfigs.py
  22. 10
      pantera/configurations/PistonCylinderConfigs.py
  23. 69
      pantera/configurations/README.md
  24. 4
      pantera/configurations/__init__.py
  25. 15
      pantera/engineering/HeatDuty.py
  26. 5
      pantera/exceptions/PanteraExceptions.py
  27. 1
      pantera/exceptions/__init__.py
  28. 80
      pantera/gases/BottledGases.py
  29. 158
      pantera/gases/CanteraCompositionUtils.py
  30. 195
      pantera/gases/CanteraGasUtils.py
  31. 204
      pantera/gases/README.md
  32. 3
      pantera/gases/__init__.py
  33. 19
      pantera/mechanisms/README.md
  34. 1663
      pantera/mechanisms/SanDiego.cti
  35. 27
      pantera/mechanisms/equilibrium.cti
  36. 86
      pantera/reactors/AutoignitionReactors.py
  37. 11
      pantera/reactors/EquilibriumReactors.py
  38. 10
      pantera/reactors/PackedBedReactors.py
  39. 112
      pantera/reactors/PanteraReactorBases.py
  40. 56
      pantera/reactors/PistonCylinders.py
  41. 25
      pantera/reactors/PlugFlowReactors.py
  42. 68
      pantera/reactors/README.md
  43. 5
      pantera/reactors/TubularReactors.py
  44. 1
      pantera/reactors/__init__.py
  45. 1
      params.json
  46. 17
      setup.py
  47. 226
      stylesheets/print.css
  48. 69
      stylesheets/pygment_trac.css
  49. 255
      stylesheets/styles.css
  50. 479
      stylesheets/stylesheet.css
  51. 22
      tests/README.md
  52. 4932
      tests/SanDiego.xml
  53. 4932
      tests/SanDiego201402_complete.xml
  54. 6
      tests/functions.py
  55. 41
      tests/test_aidt.py
  56. 27
      tests/test_bottledgases.py
  57. 39
      tests/test_configurations.py
  58. 176
      tests/test_gases.py
  59. 94
      tests/test_pistoncylinders.py
  60. 60
      tests/test_reactors.py

54
.gitignore vendored

@ -1,54 +0,0 @@ @@ -1,54 +0,0 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# C extensions
*.so
# Distribution / packaging
.Python
env/
bin/
build/
develop-eggs/
dist/
eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.cache
nosetests.xml
coverage.xml
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# Rope
.ropeproject
# Django stuff:
*.log
*.pot
# Sphinx documentation
docs/_build/

21
LICENSE

@ -1,21 +0,0 @@ @@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2014 Charles Reid
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

95
README.md

@ -1,95 +0,0 @@ @@ -1,95 +0,0 @@
# Pantera: A Toolbox for Cantera in Python
Pantera is a toolbox for using and extending Cantera 2.1 [(link to latest Cantera tarball on Sourceforge)](http://sourceforge.net/projects/cantera/files/latest/download) with Python: [http://charlesreid1.github.io/pantera](http://charlesreid1.github.io/pantera)
Pantera is beta software. Pantera is _not_ a finished product!
## What is Cantera?
Cantera is an object-oriented toolkit for chemical kinetics.
It handles all sorts of thermochemistry stuff - everything from
physical properties to reaction rates to reactors and ordinary
differential equation integrators.
Link: [Cantera on Google Code](https://code.google.com/p/cantera/)
Link: [Cantera Information on the CMR Wiki](http://charlesmartinreid.com/wiki/CanteraOutline)
## What is Pantera?
Pantera (yes, like the metal band) is a set of programmer tools
for people using Cantera in Python.
Cantera is an extremely useful library. This Python module will
make it even more useful, by providing some functionality commonly
used in engineering calculations, and by giving you ideas about how
you can extend Cantera for your own uses.
# Installing Pantera
Pantera has a couple of dependencies. Once these are installed,
you can do the usual setup.py thing to install Pantera.
## Dependencies
In order to use Pantera, you will, at the very least, need to install Cantera.
There are other features of Pantera that require other libraries. Their dependencies
are optional.
Required:
* Cantera
* JSON
Optional:
* Matplotlib
* itertools
## Installing
You can install Pantera by using setup.py:
```
python setup.py install
```
then import pantera like any other library:
```python
import pantera as pt
```
# What's in the Pantera Library?
## Pantera Core
The core of the Pantera library is the source code in the ```pantera``` directory.
This is divided into various sub-modules.
You can explore the various submodules of Pantera
[at the Pantera core source code README.md file](pantera/README.md)
## Tests
The Pantera library uses nose as the unit testing framework.
The ```tests``` directory contains nose tests that cover various
parts of the Pantera library.
# Getting Started
You can import the pantera library into Python like this:
```python
import pantera as pt
```
Once that import statement is working,
you can explore the various submodules of Pantera
[at the Pantera core source code README.md file](pantera/README.md)
mmmkay...

BIN
images/bkg.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
images/blacktocat.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/body-bg.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
images/download-button.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
images/github-button.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
images/header-bg.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
images/highlight-bg.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
images/sidebar-bg.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

139
index.html

@ -0,0 +1,139 @@ @@ -0,0 +1,139 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<title>Pantera by charlesreid1</title>
<link rel="stylesheet" href="stylesheets/styles.css">
<link rel="stylesheet" href="stylesheets/pygment_trac.css">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<div class="wrapper">
<header>
<h1>Pantera</h1>
<p>A toolset for using and extending Cantera in Python.</p>
<p class="view"><a href="https://github.com/charlesreid1/pantera">View the Project on GitHub <small>charlesreid1/pantera</small></a></p>
<ul>
<li><a href="https://github.com/charlesreid1/pantera/zipball/master">Download <strong>ZIP File</strong></a></li>
<li><a href="https://github.com/charlesreid1/pantera/tarball/master">Download <strong>TAR Ball</strong></a></li>
<li><a href="https://github.com/charlesreid1/pantera">View On <strong>GitHub</strong></a></li>
</ul>
</header>
<section>
<h1>
<a name="pantera-a-toolbox-for-cantera-in-python" class="anchor" href="#pantera-a-toolbox-for-cantera-in-python"><span class="octicon octicon-link"></span></a>Pantera: A Toolbox for Cantera in Python</h1>
<p>Pantera is a toolbox for using and extending Cantera in Python: <a href="http://charlesreid1.github.io/pantera">http://charlesreid1.github.io/pantera</a></p>
<p>Pantera is in beta and is under active development. </p>
<p>Pantera is <em>not</em> a finished product!</p>
<h2>
<a name="what-is-cantera" class="anchor" href="#what-is-cantera"><span class="octicon octicon-link"></span></a>What is Cantera?</h2>
<p>Cantera is an object-oriented toolkit for chemical kinetics.</p>
<p>It handles all sorts of thermochemistry stuff - everything from
physical properties to reaction rates to reactors and ordinary
differential equation integrators.</p>
<p>Link: <a href="https://code.google.com/p/cantera/">Cantera on Google Code</a></p>
<p>Link: <a href="http://charlesreid1.com/wiki/CanteraOutline">Cantera Information on the CMR Wiki</a></p>
<h2>
<a name="what-is-pantera" class="anchor" href="#what-is-pantera"><span class="octicon octicon-link"></span></a>What is Pantera?</h2>
<p>Pantera (yes, like the metal band) is a set of programmer tools
for people using Cantera in Python.</p>
<p>Cantera is an extremely useful library. This Python module will
make it even more useful, by providing some functionality commonly
used in engineering calculations, and by giving you ideas about how
you can extend Cantera for your own uses.</p>
<h1>
<a name="installing-pantera" class="anchor" href="#installing-pantera"><span class="octicon octicon-link"></span></a>Installing Pantera</h1>
<p>Pantera has a couple of dependencies. Once these are installed,
you can do the usual setup.py thing to install Pantera.</p>
<h2>
<a name="dependencies" class="anchor" href="#dependencies"><span class="octicon octicon-link"></span></a>Dependencies</h2>
<p>In order to use Pantera, you will, at the very least, need to install Cantera.
There are other features of Pantera that require other libraries. Their dependencies
are optional.</p>
<p>Required:</p>
<ul>
<li>Cantera</li>
<li>JSON</li>
</ul><p>Optional:</p>
<ul>
<li>Matplotlib</li>
<li>itertools</li>
</ul><h2>
<a name="installing" class="anchor" href="#installing"><span class="octicon octicon-link"></span></a>Installing</h2>
<p>You can install Pantera by using setup.py:</p>
<pre><code>python setup.py install
</code></pre>
<p>then import pantera like any other library:</p>
<div class="highlight highlight-python"><pre><span class="kn">import</span> <span class="nn">pantera</span> <span class="kn">as</span> <span class="nn">pt</span>
</pre></div>
<h1>
<a name="whats-in-the-pantera-library" class="anchor" href="#whats-in-the-pantera-library"><span class="octicon octicon-link"></span></a>What's in the Pantera Library?</h1>
<h2>
<a name="pantera-core" class="anchor" href="#pantera-core"><span class="octicon octicon-link"></span></a>Pantera Core</h2>
<p>The core of the Pantera library is the source code in the <code>pantera</code> directory.
This is divided into various sub-modules.</p>
<p>You can explore the various submodules of Pantera
<a href="https://github.com/charlesreid1/pantera/blob/master/pantera/README.md">at the Pantera core source code README.md file</a></p>
<h2>
<a name="tests" class="anchor" href="#tests"><span class="octicon octicon-link"></span></a>Tests</h2>
<p>The Pantera library uses nose as the unit testing framework.
The <code>tests</code> directory contains nose tests that cover various
parts of the Pantera library.</p>
<h1>
<a name="getting-started" class="anchor" href="#getting-started"><span class="octicon octicon-link"></span></a>Getting Started</h1>
<p>You can import the pantera library into Python like this:</p>
<div class="highlight highlight-python"><pre><span class="kn">import</span> <span class="nn">pantera</span> <span class="kn">as</span> <span class="nn">pt</span>
</pre></div>
<p>Once that import statement is working,
you can explore the various submodules of Pantera
<a href="https://github.com/charlesreid1/pantera/blob/master/pantera/README.md">at the Pantera core source code README.md file</a></p>
</section>
<footer>
<p>This project is maintained by <a href="https://github.com/charlesreid1">charlesreid1</a></p>
<p><small>Hosted on GitHub Pages &mdash; Theme by <a href="https://github.com/orderedlist">orderedlist</a></small></p>
</footer>
</div>
<script src="javascripts/scale.fix.js"></script>
</body>
</html>

1
javascripts/main.js

@ -0,0 +1 @@ @@ -0,0 +1 @@
console.log('This would be the main JS file.');

17
javascripts/scale.fix.js

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
var metas = document.getElementsByTagName('meta');
var i;
if (navigator.userAgent.match(/iPhone/i)) {
for (i=0; i<metas.length; i++) {
if (metas[i].name == "viewport") {
metas[i].content = "width=device-width, minimum-scale=1.0, maximum-scale=1.0";
}
}
document.addEventListener("gesturestart", gestureStart, false);
}
function gestureStart() {
for (i=0; i<metas.length; i++) {
if (metas[i].name == "viewport") {
metas[i].content = "width=device-width, minimum-scale=0.25, maximum-scale=1.6";
}
}
}

170
pantera/README.md

@ -1,170 +0,0 @@ @@ -1,170 +0,0 @@
# The Pantera Library Layout
This readme describes the layout of the core source code of Pantera.
Pantera provides classes that interface with and extend Cantera classes.
Pantera also monkey-patches Cantera. Monkey patches are modifications to
existing objects that add new features or bring back useful but deprecated features.
Pantera Sub-Modules:
* Cantera Monkey-Patches - patches existing Cantera classes (adds essential functionality ONLY!)
* [Gases submodule](gases/README.md) - gas compositions, gas mixing, gas objects
* [Configurations submodule](configurations/README.md) - extends Cantera reactor networks to be more useful and flexible (plug flow reactors, packed bed reactors, ignition reactors, recycle reactors, etc.)
* [Reactors submodule](reactors/README.md) - extends Cantera reactors to be more useful (but most of the useful stuff is in the configurations)
* [Engineering submodule](engineering/README.md) - applied engineering problems solved with Cantera
## Cantera Monkey-Patches
There are a couple of monkey patches applied to Cantera. The two classes affected are:
* Cantera.Reactor
* Cantera.Solution
### Solution class Monkey-Patches
The Solution class is monkey-patched to more easily obtain mass and mole fractions
for particular species.
If you have a Solution (bascially a gas phase object) using the Cantera library, you can
obtain mass and mole fractions using the somewhat clunky notation:
```python
speciesName = ['CH4','O2']
Xs = my_solution[speciesName].X
Ys = my_solution[speciesName].Y
```
This monkey-patch allows for the much more intuitive:
```python
speciesName = ['CH4','O2']
Xs = my_solution.mole_fraction( speciesName )
Ys = my_solution.mass_fraction( speciesName )
```
Works for single species names or for lists of species names.
### Reactor class Monkey-Patches
The Reactor class monkey-patches are actually provided in the PanteraReactors.py file in the
```pantera.reactors``` submodule. It is described here anyway, since it is still a monkey-patch.
In Cantera 2.0, you could access the state of a Cantera reactor
like this:
```python
# Cantera 2.0
r = Reactor(my_solution)
print r.temperature()
print r.pressure()
print r.moleFractions()
```
However, Cantera 2.1 created problems by doing away with this.
Now, you can only access the temperature of the reactor.
What's worse, if you want to access the pressure and mole fractions
of a reactor, you need to use the contents, but Cantera 2.1 also
did away with ways of accessing the contents of the reactor. You
used to be able to do this:
```python
# Cantera 2.0
r = Reactor(my_solution)
c = r._contents
T = c.temperature()
P = c.pressure()
X = c.moleFractions()
```
Again, Cantera 2.1 created problems by doing away with this.
These monkey-patches fix this. Now you can do this:
```python
r = Reactor(my_solution)
print r.T
print r.P
print r.X
print r.Y
c = r._contents
print c.T
print c.P
print c.X
print c.Y
```
Woo hoo!
## Configurations submodule
Configurations are the Pantera equivalent of a Cantera ReactorNet.
They are designed to construct a reactor (or set of reactors)
and any associated inlets and outlets, and solve it.
They extend Cantera ReactorNets, but have a constructor like
Cantera Reactors. This is more intuitive for the user to specify.
[Visit the configurations README.md for details](configurations/README.md)
## Gases submodule
Pantera defines several utility functions
for things like specification of composition,
conversion of formats, mixing of gases, and
others.
```python
from pantera.gases import *
ready_to_ignite = MethaneAir(phi=0.5)
```
[Visit the gases README.md for details](gases/README.md)
## Reactors submodule
You can create Pantera reactor objects. These
extend Cantera's Reactor classes.
You can create them once you import Pantera:
```python
from pantera import *
pr = PanteraReactor()
```
[Visit the reactors README.md for details](reactors/README.md)
## Engineering submodule
Cantera is very handy for everyday engineering calculations, with an emphasis on
reaction engineering and reactor design. This submodule creates some
objects and methods that assist in these kinds of calculations.
```python
from pantera import *
h = Heater()
```
## A Note on Namespaces
The Pantera library keeps the namespace clean by importing Cantera like this:
```python
import cantera as ct
```
This prevents conflicting functions and objects.
If you have to use Cantera and Pantera together, import them like this:
```python
import cantera as ct
import pantera as pt
```

23
pantera/__init__.py

@ -1,23 +0,0 @@ @@ -1,23 +0,0 @@
import cantera as ct
from .gases import *
from .reactors import *
from .configurations import *
# this makes cantera available directly through pt namespace
# (dubious...)
from cantera import *
#################################
# Add the mechanisms directory to Cantera's search path
# so we don't have to copy XML files everywhere
import pkg_resources
ct.add_directory( pkg_resources.resource_filename('pantera','mechanisms') )
#################################
# Monkey patch Cantera
from cantera_monkey_patches import *

51
pantera/cantera_monkey_patches.py

@ -1,51 +0,0 @@ @@ -1,51 +0,0 @@
import cantera as ct
#from cantera import *
#################################
# Monkey patch Cantera constants
# one bar
one_bar = 1.0e5
OneBar = one_bar
# one atm
one_atm = 1.01325e5
OneAtm = one_atm
#################################
# Monkey patch Cantera Solution class
def mole_fraction(self,speciesName):
X = self[speciesName].X
if len(X) > 1:
return X
else:
return X[0]
def mass_fraction(self,speciesName):
Y = self[speciesName].Y
if len(Y) > 1:
return Y
else:
return Y[0]
ct.Solution.mole_fraction = mole_fraction
ct.Solution.mass_fraction = mass_fraction
ct.Solution.nSpecies = ct.Solution.n_species
ct.Solution.nReactions = ct.Solution.n_reactions
################################
# Monkey patch Cantera Reactor class
def get_contents(self):
return self.thermo
#ct.Reactor._contents = get_contents
#ct.Reactor.P = ct.Reactor.thermo.P
#ct.Reactor.X = ct.Reactor.thermo.X
#ct.Reactor.mole_fractions = ct.Reactor.X

5
pantera/configurations/AutoignitionConfigs.py

@ -1,5 +0,0 @@ @@ -1,5 +0,0 @@
from PanteraConfigs import *
class AutoignitionConfig(Configuration):
pass

5
pantera/configurations/EquilibriumConfigs.py

@ -1,5 +0,0 @@ @@ -1,5 +0,0 @@
from PanteraConfigs import *
class EquilibriumConfig(Configuration):
pass

130
pantera/configurations/PC.md

@ -1,130 +0,0 @@ @@ -1,130 +0,0 @@
# Piston Cylinder (PC) Reactors
The governing equation for piston cylinder systems and their
volume change as a function of thermodynamic state is:
```
\frac{dV}{dt} = K A ( P_{left} - P_{right} )
```
[More about piston cylinder systems](pantera/configurations/PC.md)
## Initialization
Because piston cylinders are a single-reactor system,
their initialization and solution is a mix of
reactor and reactor network information.
Our goal is not to interfere with this natural combination,
but to make it easier.
## Cantera Method
In Cantera, we have the necessary but awkward
two-step process of creating the reactor,
and then creating the reactor network,
and then installing the wall,
and then setting the wall parameters,
```python
import cantera as ct
g = get_gas() # imaginary function returning a Solution object with TPX set
ctreactor = ct.Reactor(g)
ctnet = ct.ReactorNet([ctreactor])
ctnet.solve(0.01)
```
is all made much easier in Pantera.
* First, you initialize it like a reactor.
* Then, it sets the piston/wall parameters for you,
and dissolves the difference between a reactor
and a reactor network.
* Finally, solve it like a ReactorNetwork.
Like so:
```python
import pantera as pt
g = get_gas() # imaginary function returning a Solution object with TPX set
pc = pt.PistonCylinderConfig(contents=g)
pc.solve(0.01)
```
Initialize the piston cylinder configuration the same
way you would a reactor:
```
### Isobaric PC (Weightless Piston)
An isobaric piston-cylinder has a constant pressure,
which requires the proportionality constant K to be
very large, e.g.:
```
K = 1.0e6
```
#### Adiabatic
To make an adiabatic isobaric piston-cylinder system,
remember that we are inheriting Cantera Reactor types,
so we can pass any parameters that Cantera Reactors take.
To make an adiabatic isobaric piston cylinder, we pass
the ```energy='on'``` option:
```python
import pantera as pt
g = pt.Solution('gri30.xml')
g.TPX = 898.15, pt.one_atm, "C2H6:1.0, O2:4.0"
e = pt.Solution('gri30.xml')
e.TPX = 898.15, pt.one_atm, "N2:0.79, O2:0.2"
pc = pt.IsobaricPC(contents=g,energy='on')
```
#### Isothermal
Same as above, except now we pass ```energy='off'```:
```python
import pantera as pt
g = pt.Solution('gri30.xml')
g.TPX = 898.15, pt.one_atm, "C2H6:1.0, O2:4.0"
e = pt.Solution('gri30.xml')
e.TPX = 898.15, pt.one_atm, "N2:0.79, O2:0.2"
pc = pt.IsobaricPC(contents=g,energy='off')
```
### Isochoric PC (Heavy Piston)
Isochoric piston-cylinders have a constant volume, so
the expansion coefficient is zero to prevent any
expansion:
```python
K = 0
```
### Adiabatic
Pass ```energy='on'``` to constructor
### Isothermal
Pass ```energy='off'``` to constructor

74
pantera/configurations/PanteraConfigs.py

@ -1,74 +0,0 @@ @@ -1,74 +0,0 @@
import cantera as ct
from ..reactors.PanteraReactorBases import *
class Configuration(ct.ReactorNet):
"""
Default behavior: reactor network wraps a single reactor
Initialize it like a reactor,
advance()/solve() it like a reactor network.
If you have a different scenario, your constructor and solve
will look different.
"""
def __init__(self,contents=None,params={},**kwargs):
"""
Initialize the piston cylinder system
"""
# first call reactor constructor
self.r = PanteraReactor(contents=contents,params=params,**kwargs)
# now call reactor network constructor
ct.ReactorNet.__init__(self,[self.r])
# now, we're done!
# it will behave exactly like a normal reactornet now
# hence, the constructor of a reactor,
# and the functionality of a reactor network
# Oh yeah - we may want to define some of the same
# properties that reactors have.
# P pressure property
def get_P(self):
return self.r.P
def set_P(self,newP):
self.r.P = newP
P = property(get_P,set_P)
# T pressure property
def get_T(self):
return self.r.T
def set_T(self,newT):
self.r.T = newT
T = property(get_T,set_T)
# Y mass frac property
def get_Y(self):
return self.r.Y
def set_Y(self,newY):
self.r.Y = newY
Y = property(get_Y,set_Y)
# X mole frac property
def get_X(self):
return self.r.X
def set_X(self,newX):
self.r.X = newX
X = property(get_X,set_X)
# params property
def get_params(self):
return self.r.params
def set_params(self):
raise Exception("Error: can't set input parameter dictionary")
params = property(get_params,set_params)
# _contents property
def get_contents(self):
return self.r._contents
def set_contents(self,content):
self.r.insert(contents)
_contents = property(get_contents,set_contents)

10
pantera/configurations/PistonCylinderConfigs.py

@ -1,10 +0,0 @@ @@ -1,10 +0,0 @@
from PanteraConfigs import *
class PistonCylinderConfig(Configuration):
"""
Piston cylinder configuration
Initialize it like a reactor,
advance()/solve() it like a reactor network.
"""
pass

69
pantera/configurations/README.md

@ -1,69 +0,0 @@ @@ -1,69 +0,0 @@
# Configurations Submodule
This directory contains classes that define Pantera configurations.
Configurations are the Pantera equivalent of a Cantera ReactorNet.
Configurations allow for the fact that the user will want to
initialize their system the way they initialize reactors -
by inserting a gas and passing options - but want to solve their
system the way they solve a reactor network - with a simple
call to a solve() method.
You can extend the Pantera Configuration class to handle multiple reactors,
multiple inlets, multiple outlets, or whatever your situation is.
You just redefine the constructor to take whatever arguments you want,
then properly intialize whatever reactors and flow devices you want.
When you call advance, or do anything else with your configuration/reactor network,
it will behave just like a regular reactor network.
## How to Use Configurations
We can treat them the same way we treat reactor networks. With Cantera:
```python
import cantera as ct
g = get_gas() # imaginary function returning a Solution object with TPX set
ctreactor = ct.Reactor(g)
ctnet = ct.ReactorNet([ctreactor])
ctnet.advance(0.01)
```
The Pantera Configuration class functions the exact same way, via inheritance:
```python
import pantera as pt
g = get_gas() # imaginary function returning a Solution object with TPX set
ptreactor = pt.PanteraReactor(g)
ptconfig = pt.Configuration([ptreactor])
ptconfig.advance(0.01)
```
Of course, configurations are designed to do
much more than Cantera reactor networks.
We'll cover some examples shortly.
## Piston Cylinder (PC) Configurations
Piston cylinder configurations consist of two gases,
one on either side of a flexible wall.
The gas on the left side is the contents of your
piston cylinder system. THe gas on the right side is the
environment.
The pressure difference dictates the volume change of the cylinder,
through an expansion coefficient K,
```
\frac{dV}{dt} = K A ( P_{left} - P_{right} )
```
[More about piston cylinder systems](PC.md)

4
pantera/configurations/__init__.py

@ -1,4 +0,0 @@ @@ -1,4 +0,0 @@
from PanteraConfigs import *
from PistonCylinderConfigs import *
from AutoignitionConfigs import *
from EquilibriumConfigs import *

15
pantera/engineering/HeatDuty.py

@ -1,15 +0,0 @@ @@ -1,15 +0,0 @@
"""
Class for computing heat duty
This class performs simple thermodynamic calculations
to allow for heat duty and temperature change calculations.
Perfect heaters:
* You can specify a heat duty, and see what the final temperature is
* You can specify a final temperatue, and see what the heat duty required is
Heat loss heaters:
* You can specify a heat tansfer coefficient, and do same as above
* You can specify a heat loss percentage, and do same as above
"""

5
pantera/exceptions/PanteraExceptions.py

@ -1,5 +0,0 @@ @@ -1,5 +0,0 @@
class PanteraException(Exception):
pass
class PanteraGasChangedException(PanteraException):
pass

1
pantera/exceptions/__init__.py

@ -1 +0,0 @@ @@ -1 +0,0 @@
from PanteraExceptions import *

80
pantera/gases/BottledGases.py

@ -1,80 +0,0 @@ @@ -1,80 +0,0 @@
import cantera as ct
from CanteraGasUtils import *
"""
==========================
Bottled Gases
Charles Reid
August 2013
==========================
This is a library of gases with various
mechanisms and compositions.
Inspired by Cantera's GRI30().
"""
DEFAULT_MECH = 'gri30.xml'
DEFAULT_GAS_ID = 'gri30'
class Air(object):
"""
Defines an air gas
using the GRI 3.0 mchanism.
"""
def __new__(self):
try:
return self.sol
except AttributeError:
self.sol = ct.Solution('gri30.xml')
self.sol.TPX = 298.15, ct.one_atm, "N2:0.79,O2:0.21"
return self.sol
class GRI30(object):
"""
Defines a gas using the
GRI 3.0 mechanism.
"""
def __new__(self):
try:
return self.sol
except AttributeError:
self.sol = ct.Solution('gri30.xml')
return self.sol
class SanDiego(object):
"""
Defines a gas using the
UC San Diego combustion mechanism
web.eng.ucsd.edu/mae/groups/combustion/mechanism.html
"""
def __new__(self):
try:
return self.sol
except AttributeError:
self.sol = ct.Solution('SanDiego.cti')
return self.sol
class MethaneAir(object):
"""
Defines a mixtue of methane and air
in a proportion specified with
equivalence ratio phi.
"""
def __new__(self,phi=1.0):
try:
# if phi has changed, let's make a new gas
if phi <> self.phi:
raise PanteraGasChangedException
return self.sol
except AttributeError, PanteraGasChangedException:
self.sol = ct.Solution('gri30.xml')
meth_air_stoich = 1.0/2.0
nox = 1
nmeth = phi * meth_air_stoich
nn2 = (0.79/0.21)*nox
composition = "CH4:%0.5f,O2:%0.5f,N2:%0.5f"%(nmeth,nox,nn2)
self.sol.TPX = 298.15, ct.one_atm, composition
return self.sol

158
pantera/gases/CanteraCompositionUtils.py

@ -1,158 +0,0 @@ @@ -1,158 +0,0 @@
import cantera as ct
import itertools
from numpy import *
"""
=============================
Cantera Composition Utility Functions
Charles Reid
August 2013
=============================
There are three methods for specifying
gas compositions:
* String, e.g. "CH4:1.0, O2:1.0"
* Vector, e.g. [0.0, 0.1, 0.75, 1.5, 2.2, 1.0e-5]
* Dict, e.g. d['CH4'] = 1.0; d['O2'] = 1.0
(Note that the dict method is not supported by
Cantera, it is simply a more convenient way
of dealing with compositions.)
We want to be able to do a couple of things:
1. Turn gases into strings/vectors/dicts
2. Turn vectors into dicts and dicts into vectors
3. Turn strings into dicts and dicts into strings
Functions defined in file:
Converting gases to composition vectors, dicts, and strings:
+ convert_gas_to_composition_vector
+ convert_gas_to_composition_dict
+ convert_gas_to_composition_string
+ convert_arrays_to_dict
Converting between composition vectors and dicts:
+ convert_composition_vector_to_dict
+ convert_composition_dict_to_vector
Converting between composition strings and dicts:
+ convert_composition_string_to_dict
+ convert_composition_dict_to_string
Gas mixing:
+ getGasMixture( gases, Xs )
"""
# ==========================================
# Turning gases into a composition representation:
# ==========================================
def convert_gas_to_composition_vector( gas ):
"""
Converts a Cantera gas with a specified composition into
a composition vector of mole fractions
"""
return gas.X
def convert_gas_to_composition_dict( gas ):
"""
Converts a Cantera gas with a specified composition into
a composition dict of mole fractions
"""
d = {}
for sp in gas.species_names:
if gas.mole_fraction(sp) > 0.0:
d[sp] = gas.mole_fraction(sp)
return d
def convert_gas_to_composition_string( gas ):
"""
Converts a Cantera gas with a specified composition into
a representative composition string of style "CH4:1.0, N2:4.0"
"""
d = convert_gas_to_composition_dict(gas)
s = convert_composition_dict_to_string(d)
return s
def convert_arrays_to_dict(speciesNames,moleFractions):
"""
Converts two vectors, one containing species names and
one containing mole fractions, into a species dictionary
"""
d = {}
assert len(speciesNames) == len(moleFractions)
for name, amt in zip(speciesNames,moleFractions):
if amt > 0.0:
d[name] = amt
return d
# ==========================================
# Converting between composition vectors and dicts:
# ==========================================
def convert_composition_vector_to_dict( g, Xv ):
"""Convert a composition vector Xv into a dict, for a given gas g"""
Xd = {}
for iv, v in enumerate(Xv):
if v > 0.0:
Xd[g.species_name(iv)] = v
return Xd
def convert_composition_dict_to_vector( g, Xd ):
"""Convert a composition dict Xd into a vector, for a given gas g"""
Xv = zeros( g.n_species, )
for k in Xd.keys():
Xv[g.species_index(k)] = Xd[k]
Xv = Xv/sum(Xv)
return Xv
# ==========================================
# Converting between composition strings and dicts:
# ==========================================
def convert_composition_string_to_dict( X ):
"""
Converts a composition string of style "CH4:0.02, N2:0.01, O2:0.45"
into a dict, a la composition['CH4'] = 0.02
"""
results = {}
for sp in X.split(","):
st = sp.strip()
try:
results[ st.split(":")[0].strip() ] = float( st.split(":")[1].strip() )
except IndexError:
# X is probably not a list
# (why would we run split on a list?)
# or is empty
err = "ERROR: CanteraGasUtils: your X is probably specified incorrectly. Expected type list, got type "+type(X)
raise Exception(err)
# normalize
results_sum = sum( [results[k] for k in results.keys()] )
for k in results.keys():
results[k] = results[k]/results_sum
return results
def convert_composition_dict_to_string( d ):
"""
Converts a composition dict of stype composition['CH4'] = 0.02,
into a string like "CH4: 0.02"
"""
X = ""
for item in d:
if d[item] > 0.0:
X += "%s:%0.16f"%(item,d[item])
X += ", "
X=X[:-2]
return X

195
pantera/gases/CanteraGasUtils.py

@ -1,195 +0,0 @@ @@ -1,195 +0,0 @@
import cantera as ct
from numpy import *
from CanteraCompositionUtils import *
"""
=============================
Cantera Gas Utility Functions
Charles Reid
August 2013
=============================
It is often convenient to be able to
take multiple gas objects of various
compositions and mix them all together
in specified proportions.
This function allows for specifying
mass, mole, or volume fractions.
Note that each gas must have a common
XML file, so that the final mixture
shares species.
"""
# =======================================
# Gas mixing:
# =======================================
def getGasMixture( gases, # list of gases
Xs, # list of moles/mole fractions of each gas
Ws = None, # list of weights/weight fractions of each gas[sensible/my notation]
Ys = None, # list of masses/mass fractions of each gas[Cantera notation]
Vs = None, # list of volumes/vol fractions of each gas
model_file=None,
gas_phase_name=None ):
"""
Convert a list of gases and mole fractions
(or mass fractions, or volume fractions,
or partial pressures, eventually)
into a single Gas mixture.
Do this by manually computing
mass-averaged mixture enthalpy,
mole-averaged pressure,
and composition mixing via composition dict
"""
if model_file == None or gas_phase_name == None:
err = "ERROR: CanteraGasUtils: You must specify a model file (via params['model_file']) and gas phase name (via params['gas_phase_name']) for the gas mixture."
raise Exception(err)
# pass in a normalized Xs
Xsarr = array(Xs)
Xsnorm = Xsarr/sum(Xsarr)
# technically a little better,
# but setting HPX is expensive
# (Newton iterations over T)
#try:
# H, P, X = mixture_HPX( gases, Xnorm )
#except CanteraError:
# T, P, X = mixture_TPX( gases, Xsnorm )
# this approximates constant Cp
# (i.e, only works for limited T differences
# among geses being mixed):
T, P, X = mixture_TPX( gases, Xsnorm )
gas = ct.Solution(model_file,gas_phase_name)
gas.TPX = T,P,X
return gas
def mixture_TPX( gases, Xs):
"""
Given a list of gases and their mole fractions,
this returns the TPX info needed to create
a Cantera Gas object that is
a mixture of these gases.
"""
# --------------
# X
mixture_d = {}
for gas,wx_i in zip(gases,Xs):
for sp in gas.species_names:
mf = gas.mole_fraction(sp)
if sp in mixture_d:
mixture_d[sp] += wx_i * mf
elif mf != 0.0:
mixture_d[sp] = wx_i * mf
else:
pass
mixture_s = convert_composition_dict_to_string(mixture_d)
# --------------
# H
# Compute Tmix with molar heat capacities
#
# Define:
# h_mix = C_pmix T_mix = ( sum_i n_i C_pi Ti )/( n_T )
#
# from which we get relationship:
# T_mix = \sum_i [ (x_i C_pi )/( C_pmix ) ] T_i
# first compute c_pmix
cp_mix = 0
for gas, wx_i in zip(gases,Xs):
cp_mix += wx_i * gas.cp_mole
# next compute T_mix
T_mix = 0
for gas, wx_i in zip(gases,Xs):
coeff = ( wx_i * gas.cp_mole )/( cp_mix )
T_mix += coeff * gas.T
# --------------
# P
press = 0.0
for gas,wx_i in zip(gases,Xs):
press += wx_i * gas.P
# -------------------
# Return TPX
return T_mix, press, mixture_s
def mixture_HPX( gases, Xs ):
"""
Given a mixture of gases and their mole fractions,
this method returns the enthalpy, pressure, and
composition string needed to initialize
the mixture gas in Cantera.
NOTE: The method of setting enthalpy
usually fails, b/c Cantera uses a Newton
iterator to find the temperature that
yields the specified enthalpy, and it
isn't very robust.
Instead, approximate constant Cp's
and find T_mix manually, as with the
mixture_TPX() method above.
"""
# --------------
# X
mixture_d = {}
for gas,wx_i in zip(gases,Xs):
for sp in gas.species_names:
if sp in mixture_d:
mixture_d[sp] += wx_i * gas.mole_fraction(sp)
elif gas.moleFraction(sp) != 0.0:
mixture_d[sp] = wx_i * gas.mole_fraction(sp)
else:
pass
mixture_s = convert_composition_dict_to_string(mixture_d)
# --------------
# H
# Compute Tmix with molar heat capacities
#
# Define:
# h_mix = sum_i n_i h_i
#
# where h is molar enthalpy
# compute H_mix
H_mix = 0
for gas, wx_i in zip(gases,Xs):
Hmix += wx_i * gas.enthalpy_mole
# --------------
# P
press = 0.0
for gas,wx_i in zip(gases,Xs):
press += wx_i * gas.P
# -------------------
# Return HPX
return H_mix, press, mixture_s

204
pantera/gases/README.md

@ -1,204 +0,0 @@ @@ -1,204 +0,0 @@
# Gases
This directory contains objects and functions that
make dealing with gases and gas compositions easier.
## Bottled Gases
This is a virtual cabinet of various mixtures.
These create a shorthand way of doing things,
like creating a methane-air mixture and specifying
its equivalence ratio:
```python
from pantera.gases import *
ready_to_ignite = MethaneAir(phi=0.5)
```
## Cantera Composition Utilities
Cantera provides the user with two ways of specifying
composition, neither of which are particularly
convenient for programming purposes:
1. Specify composition by string, e.g., "CH4:1.0, O2:8.0"
2. Specify composition by vector, e.g., [0.0, 0.7, 9.0, 15.3, 0.0, 1.0e-5]
The first way is cumbersome for converting back and forth between
molar or volume ratios, and the second way is cumbersome for the
user to specify by hand (which vector index corresponds to which
species index is dictated by their order in the XML file, and is
usually random).
To resolve this, I've added a third method for specifying
composition that resolves that, and it is the compsition dict:
```python
d={}
d['CH4'] = 1.0
d['O2'] = 8.0*d['CH4']
d['N2'] = (0.79/0.21)*d['O2']
```
Now we have our mixture.
Composition dicts allow you to specify, with strings, things that
are natural to express with strings, and to specify things with formulas
that are natural to specify with formulas.
This file provids functions for converting between each of these types,
as well as converting back and forth between these composition
specification methods and Cantera gas phase objects.
### Converting Gases to Composition Formats
Converting gases to composition vectors, dicts, and strings:
```python
import pantera as pt
gas = pt.SanDiego()
gas.TPX = 898.15, 9*pt.one_atm, "C2H6:1.0, O2:4.0"
print pt.convert_gas_to_composition_vector(gas)
# ans = [ 0. 0. 0. 0. 0.8 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
# 0. 0. 0. 0. 0. 0. 0. 0.2 0. 0. 0. 0. 0. 0. 0.
# 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
# 0. 0. 0. 0. 0. ]
print pt.convert_gas_to_composition_dict()
# ans = {'C2H6': 0.20000000000000001, 'O2': 0.80000000000000004}
print pt.convert_gas_to_composition_string()
# ans = "C2H6:0.2000000000000000, O2:0.8000000000000000"
```
### Composition Dict Specification
```python
import pantera as pt
gas = pt.SanDiego()
gas.TPX = 898.15, 9*pt.one_atm, "C2H6:1.0, O2:4.0"
namesvector = gas.species_names
xvector = array([ 0., 0., 0., 0., 0.8, 0., 0., 0. , 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0. , 0., 0., 0.2, 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0. , 0., 0., 0. , 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0. ])
print pt.convert_arrays_to_dict(namesvector,xvector)
# ans = {'C2H6': 0.20000000000000001, 'O2': 0.80000000000000004}
```
### Composition Vector Specification
Converting between composition vectors and dicts:
```python
import pantera as pt
g = pt.SanDiego()
xdict = {'C2H6': 0.20, 'O2': 0.80}
print pt.convert_composition_dict_to_vector(g,xdict)
# ans = [ 0. 0. 0. 0. 0.8 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
# 0. 0. 0. 0. 0. 0. 0. 0.2 0. 0. 0. 0. 0. 0. 0.
# 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
# 0. 0. 0. 0. 0. ]
xvector = array([ 0., 0., 0., 0., 0.8, 0., 0., 0. , 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0. , 0., 0., 0.2, 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0. , 0., 0., 0. , 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0. ])
print pt.convert_composition_vector_to_dict(g,xvector)
# ans = {'C2H6': 0.20000000000000001, 'O2': 0.80000000000000004}
```
### Composition String Specification
Converting between composition strings and dicts:
```python
import pantera as pt
g = pt.SanDiego()
xstring = "C2H6:0.2000000000000000, O2:0.8000000000000000"
print pt.convert_composition_string_to_dict(xstring)
# ans = {'C2H6': 0.20000000000000001, 'O2': 0.80000000000000004}
xdict = {'C2H6': 0.20, 'O2': 0.80}
print pt.convert_composition_dict_to_string(xdict)
# ans = "C2H6:0.2000000000000000, O2:0.8000000000000000"
```
## Cantera Gas Utilities
This implements the ability to create a set of
Cantera phase objects, each with various
thermochemical states, and mix them all
together. It then returns the mixture
as a single Cantera gas object.
You can specify your mixing proportions
by mole, mass, or volume fraction.
```python
import pantera as pt
gs = [Solution('SanDiego.cti'),
Solution('SanDiego.cti'),
Solution('SanDiego.cti')]
Ts = [873.15, 973.15, 1073.15]
Ps = [pt.one_atm, 2*pt.one_atm, 3*pt.one_atm]
Xs = ["CO2:1.0", "N2:0.79, O2:0.21", "C2H6:1.0, CH4:10.0"]
for g,T,P,X in zip(gs,Ts,Ps,Xs):
g.TPX = T,P,X
mix = pt.getGasMixture(gs,[1.0,1.0,2.0],model_file='SanDiego.cti',gas_phase_name='gas')
print mix.X
# ans = array([ 0.1975 , 0. , 0. , 0. , 0.0525 ,
# 0. , 0. , 0. , 0. , 0. ,
# 0. , 0. , 0.25 , 0. , 0. ,
# 0.45454545, 0. , 0. , 0. , 0. ,
# 0. , 0. , 0.04545455, 0. , 0. ,
# 0. , 0. , 0. , 0. , 0. ,
# 0. , 0. , 0. , 0. , 0. ,
# 0. , 0. , 0. , 0. , 0. ,
# 0. , 0. , 0. , 0. , 0. ,
# 0. , 0. , 0. , 0. , 0. ])
```
### Caveat
Beware!!! the otherwise-pythonic
```python
gs = [Solution('gri30.xml'),]*3
```
does not work, because it creates ONE solution object, then intializes the list
with three copies of the SAME object.
When you modify one gas, you modify all of them.
Ooops!
(Ideally, you would be able to grab the XML file
and gas phase name from each gas object, and ensure
they all match. But I haven't looked into this yet.)

3
pantera/gases/__init__.py

@ -1,3 +0,0 @@ @@ -1,3 +0,0 @@
from BottledGases import *
from CanteraCompositionUtils import *
from CanteraGasUtils import *

19
pantera/mechanisms/README.md

@ -1,19 +0,0 @@ @@ -1,19 +0,0 @@
# Mechanisms
Directory containing mechanism files,
in xml or (preferrably) cti format.
# SanDiego.cti
UC San Diego combustion mechanism from [http://web.eng.ucsd.edu/mae/groups/combustion/mechanism.html](http://web.eng.ucsd.edu/mae/groups/combustion/mechanism.html)
(version: Complete 2014-02-17).
You can download the Chemkin version of the mechanism,
then use the ck2cti mechanism to convert the Chemkin
mechanism to a CTI mechanism.
# Equilibrium.cti
Equilibrium chemistry combustion mechanism
(included with Cantera).

1663
pantera/mechanisms/SanDiego.cti

File diff suppressed because it is too large Load Diff

27
pantera/mechanisms/equilibrium.cti

@ -1,27 +0,0 @@ @@ -1,27 +0,0 @@
ideal_gas(
name="complete",
elements=" C H O",
species="gri30: O2 CH4 H2O CO2",
initial_state=state(temperature=298.0,
pressure = 100000.0))
ideal_gas(
name="incomplete",
elements=" C H O",
species="gri30: O2 CH4 H2O CO2 CO H2 OH",
initial_state=state(temperature=298.0,
pressure = 100000.0))
ideal_gas(
name="overconstrained-1",
elements=" C H O",
species="gri30: O2 CH4",
initial_state=state(temperature=298.0,
pressure = 100000.0))
ideal_gas(
name="overconstrained-2",
elements=" C H O N Ar",
species="gri30: O2 CH4 AR",
initial_state=state(temperature=298.0,
pressure = 100000.0))

86
pantera/reactors/AutoignitionReactors.py

@ -1,86 +0,0 @@ @@ -1,86 +0,0 @@
from PistonCylinders import *
class AutoignitionReactor(IsobaricPC):
"""
An autoignition reactor is a constant-pressure
reactor containing a flammable mixture.
The reactor is advanced in time until the mixture
ignites.
The autoignition delay time is defined as
the time to reach maximum rate of
temperature change:
[$
t_{aidt} = t | (dT/dt) = (dT/dt)_{max}
$]
The autoignition reactor needs to wrap the solve() method
so that the simulation ends when the autoignition time
has been found.
"""
def __init__(self,contents=None,params={},**kwargs):
"""
Autoignition reactors are perfectly adiabatic,
and constant pressure.
parameters:
* contents - reactor contents initialized with this Cantera Solution
* params - input parameter dictionary
"""
# Call parent constructor first
IsobaricPC.__init__(self,contents=contents,params=params,env_gas=None)
self.problem_setup()
if contents==None:
g = GRI30()
# how to see if X in
if 'X' in self.__dict__:
g.TPX = self.T, self.P, self.X
elif 'Y' in self.__dict__:
g.TPY = self.T, self.P, self.Y
self.insert(g)
def problem_setup(self):
"""
The input parameters may specify
TPX/TPY
If you wanna do anything more fancy,
make a Solution yourself, and pass it
as the reactor contents.
"""
self.problem_setup_composition()
self.problem_setup_pressure()
self.problem_setup_temperature()
def problem_setup_composition(self):
"""
Check for X or Y specified
"""
if 'X' in self.params:
self.X = self.params['X']
elif 'Y' in self.params:
self.Y = self.params['Y']
# convert to/store as X
pass
def problem_setup_pressure(self):
pass
def problem_setup_temperature(self):
pass
def autoignition_time(self):
# wrap calls to solve
# compute dT/dt and d2T/dt2 at each point in time
# once d2T/dt2 becomes negative, dT/dt stops increasing,
# and we have our autoigition time
pass

11
pantera/reactors/EquilibriumReactors.py

@ -1,11 +0,0 @@ @@ -1,11 +0,0 @@
from PanteraReactorBases import *
"""
overload solve method
to run equilibrate() on contents
"""
class EquilibriumReactor(PanteraReactor):
def solve(self):
self._contents.equilibrate('TP')

10
pantera/reactors/PackedBedReactors.py

@ -1,10 +0,0 @@ @@ -1,10 +0,0 @@
"""
A packed bed reactor is a plug flow reactor with a packed bed of particles.
These are probably catalyst particles.
extend plug flow reactors
create surface/interface
store object internally
create some methods
"""

112
pantera/reactors/PanteraReactorBases.py

@ -1,112 +0,0 @@ @@ -1,112 +0,0 @@
import cantera as ct
from ..gases.BottledGases import *
class CanteraReactor(ct.Reactor):
"""
Monkey patch the Cantera reactor class
so that you can get the TPX of the contents,
or the contents themselves.
r = Reactor()
print r.T
print r.P
print r.X
print r._contents.viscosity()
"""
# P pressure property
def get_P(self):
return self.thermo.P
def set_P(self,newP):
self.thermo.P = newP
P = property(get_P,set_P)
# Y mass frac property
def get_Y(self):
return self.thermo.Y
def set_Y(self,newY):
self.thermo.Y = newY
Y = property(get_Y,set_Y)
# X mole frac property
def get_X(self):
return self.thermo.X
def set_X(self,newX):
self.thermo.X = newX
X = property(get_X,set_X)
# _contents property
def get_contents(self):
return self.thermo
def set_contents(self):
raise Exception("Error: Cantera reactor: you can't set the contents of a reactor directly.")
_contents = property(get_contents,set_contents)
class PanteraReactor(CanteraReactor):
"""
This is a very barebones extension of the
Cantera Reactor type.
It takes a dictionary of parameters
in the constructor, functionality that can
be used to build sophisticated reactors
that parse high-level input file
parameter specifications.
"""
def __init__(self,contents=None,params={},**kwargs):
"""
Saves input parameters for later.
Constructs a Reactor by calling parent Reactor constructor.
* contents - a Cantera Phase object;
the usual first argument to a Cantera
Reactor constructor
* params - a dictionary of parameters,
whatever the programmer wishes.
The usefulness of this will become
clear in later examples.
"""
# First, save the parameters
self.params = params
# Next, process the input parameters to
# check for required parameters, set default
# parameter values, etc.
self.problemSetup()
# If the user doesn't specify contents,
# we'll fill it with air
if contents == None:
contents = Air()
# Now call the parent constructor
ct.Reactor.__init__(self,contents,**kwargs)
def problemSetup(self):
"""
The problemSetup method is intended to process
the input parameter dictionary, self.params.
It checks that required input parameters are specified,
and sets any unspecified parameters to default values.
This is one of the first methods a Pantera Reactor will call.
The base class does not do anything interesting, so it doesn't
need to process any input parameters.
"""
pass
def make_rxnpath(self,element,file_name,**options):
"""
Output a reaction pathway for the current state of the gas in the reactor.
Call this method while the reactor is running or after it has already run.
Parameters:
* element - which element to trace (usually 'C')
* file_name - filename of output graphviz dot file
* options - options to pass to graphviz dot
"""
file_name += ".dot"
rxnpath = ct.ReactionPathDiagram(self._contents, str(element))
rxnpath.write_dot(file_name)

56
pantera/reactors/PistonCylinders.py

@ -1,56 +0,0 @@ @@ -1,56 +0,0 @@
from PanteraReactorBases import *
class PistonCylinder(PanteraReactor):
"""
Defines a generic piston-cylinder system.
"""
def __init__(self,contents=None,environment=None,params={},**kwargs):
"""
Piston cylinder systems consist of a reactor with:
* a wall (the piston)
* an environment
"""
# We'll call the parent constructor first
PanteraReactor.__init__(self,contents,params,**kwargs)
# Create the environment
# (if none specified, use air at same TP as reactor contents)
if environment == None:
environment = Air()
environment.TPX = self.T,self.thermo.P,"N2:0.79,O2:0.21"
self.env = ct.Reservoir(environment)
# Install the piston
self.w = ct.Wall(self, self.env)
# For convenience:
PC = PistonCylinder
class IsobaricPC(PC):
"""
Isobaric piston-cyinder
(weightless piston)
"""
def __init__(self,*args,**kwargs):
PC.__init__(self,*args,**kwargs)
# expansion parameter dV/dt = KA(P_1 - P_2)
self.w.expansion_rate_coeff = 1.0e6
self.w.area = 1.0
class IsochoricPC(PC):
"""
Isochoric piston-cyinder
(very heavy piston)
"""
def __init__(self,**kwargs):
PC.__init__(self,**kwargs)
# expansion parameter dV/dt = KA(P_1 - P_2)
self.w.expansion_rate_coeff = 0.0
self.w.area = 1.0

25
pantera/reactors/PlugFlowReactors.py

@ -1,25 +0,0 @@ @@ -1,25 +0,0 @@
"""
plug flow reactors
length-based
constant flowrate
continuity equation
series of N cstrs
each cstr has a volume equal to total volume / N reactors
solve:
for each reactor:
create inlet, outlet, cstr
equilibrate reactor
create reservoir with results contents for inlet
cstr train
"""
class PlugFlowReactor(PanteraReactor):
def __init__(self,*args,**kwargs):
PanteraReactor.__init__(self,*args,**kwargs)
# make N reactors

68
pantera/reactors/README.md

@ -1,68 +0,0 @@ @@ -1,68 +0,0 @@
# Reactors Submodule
This directory contains classes that define Pantera reactors.
```python
import pantera as pt
pr = pt.PanteraReactor()
```
There isn't a whole lot here, because most of the useful functionality
is not provided by the reactor, but the reactor network.
In Pantera, reactor networks are also called "configurations." (As in,
a specific, pre-defined configuration of reactors, inlets, outlets, etc.)
## Reactors vs. Configurations
Cantera defines Reactors and Reactor Networks separately. Reactors are
basically just source term generators for a set of ordinary differential equations.
By adding reactors (and inlets and outlets) to a reactor network, you are
changing the variables and equations.
The Reactor Network object, then, is an ordinary differential equation
integrator. It owns a set of equations, variables, and right-hand sides,
and when you call the ```advance()``` or ```solve()``` method on it,
it integrates those in time.
## Inheritance
Pantera reactors take advantage of Cantera's object-oriented code
to re-use and extend existing Cantera code. Pantera Reactor objects inherit
all of the characteristics of Cantera Reactor objects, so that allows us
to use our Pantera Reactor anywhere we can use a Cantera Reactor.
## Pantera Reactor Bases
Contains base classes that define common functionality
for all Pantera reactors (specifically, taking a dictionary
of reactor input parameters, and defining a problem setup
method that processes these input parameters.
#### Isothermal and Adiabatic Reactors
To make an adiabatic or isothermal reactor,
remember that a Pantera Reactor can do anything a
Cantera Reactor can do. So with Cantera, we would
make an isothermal reactor like this:
```python
import cantera as ct
g = ct.Solution('gri30.xml')
g.TPX = 898.15, ct.one_atm, "C2H6:1.0, O2:4.0"
cr = ct.Reactor(g,energy='off')
```
```python
import pantera as pt
g = pt.Solution('gri30.xml')
g.TPX = 898.15, pt.one_atm, "C2H6:1.0, O2:4.0"
pr = pt.PanteraReactor(g,energy='off')
```
Voila! [OOP](http://en.wikipedia.org/wiki/Object_oriented_programming)!

5
pantera/reactors/TubularReactors.py

@ -1,5 +0,0 @@ @@ -1,5 +0,0 @@
"""
Tubular reactors are isothermal PFRs
Extend PFR class
"""

1
pantera/reactors/__init__.py

@ -1 +0,0 @@ @@ -1 +0,0 @@
from PanteraReactorBases import *

1
params.json

@ -0,0 +1 @@ @@ -0,0 +1 @@
{"name":"Pantera","tagline":"A toolset for using and extending Cantera in Python.","body":"# Pantera: A Toolbox for Cantera in Python\r\n\r\nPantera is a toolbox for using and extending Cantera in Python: [http://charlesreid1.github.io/pantera](http://charlesreid1.github.io/pantera)\r\n\r\nPantera is in beta and is under active development. \r\n\r\nPantera is _not_ a finished product!\r\n\r\n## What is Cantera?\r\n\r\nCantera is an object-oriented toolkit for chemical kinetics.\r\n\r\nIt handles all sorts of thermochemistry stuff - everything from \r\nphysical properties to reaction rates to reactors and ordinary \r\ndifferential equation integrators.\r\n\r\nLink: [Cantera on Google Code](https://code.google.com/p/cantera/)\r\n\r\nLink: [Cantera Information on the CMR Wiki](http://charlesmartinreid.com/wiki/CanteraOutline)\r\n\r\n## What is Pantera?\r\n\r\nPantera (yes, like the metal band) is a set of programmer tools \r\nfor people using Cantera in Python.\r\n\r\nCantera is an extremely useful library. This Python module will \r\nmake it even more useful, by providing some functionality commonly\r\nused in engineering calculations, and by giving you ideas about how\r\nyou can extend Cantera for your own uses.\r\n\r\n\r\n\r\n# Installing Pantera\r\n\r\nPantera has a couple of dependencies. Once these are installed,\r\nyou can do the usual setup.py thing to install Pantera.\r\n\r\n## Dependencies\r\n\r\nIn order to use Pantera, you will, at the very least, need to install Cantera. \r\nThere are other features of Pantera that require other libraries. Their dependencies\r\nare optional.\r\n\r\nRequired:\r\n* Cantera\r\n* JSON\r\n\r\nOptional:\r\n* Matplotlib\r\n* itertools\r\n\r\n## Installing\r\n\r\nYou can install Pantera by using setup.py:\r\n\r\n```\r\npython setup.py install\r\n```\r\n\r\nthen import pantera like any other library:\r\n\r\n```python\r\nimport pantera as pt\r\n```\r\n\r\n# What's in the Pantera Library?\r\n\r\n## Pantera Core\r\n\r\nThe core of the Pantera library is the source code in the ```pantera``` directory.\r\nThis is divided into various sub-modules.\r\n\r\nYou can explore the various submodules of Pantera\r\n[at the Pantera core source code README.md file](pantera/README.md)\r\n\r\n## Tests\r\n\r\nThe Pantera library uses nose as the unit testing framework. \r\nThe ```tests``` directory contains nose tests that cover various\r\nparts of the Pantera library.\r\n\r\n\r\n\r\n# Getting Started\r\n\r\nYou can import the pantera library into Python like this:\r\n\r\n```python\r\nimport pantera as pt\r\n```\r\n\r\nOnce that import statement is working,\r\nyou can explore the various submodules of Pantera\r\n[at the Pantera core source code README.md file](pantera/README.md)\r\n\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."}

17
setup.py

@ -1,17 +0,0 @@ @@ -1,17 +0,0 @@
from setuptools import setup
setup(name='pantera',
version='0.1',
description='Pantera is a toolset for using and extending Cantera in Python.',
url='http://github.com/charlesreid1/pantera',
author='Charles Reid',
author_email='root@charlesmartinreid.com',
license='MIT',
packages=['pantera','pantera.gases','pantera.reactors','pantera.configurations','pantera.exceptions'],
package_data={'pantera':['mechanisms/*.xml','mechanisms/*.cti']},
test_suite='nose.collector',
install_requires=[
"numpy >= 1.0",
"simplejson >= 2.3",
],
zip_safe=False)

226
stylesheets/print.css

@ -0,0 +1,226 @@ @@ -0,0 +1,226 @@
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
body {
font-size: 13px;
line-height: 1.5;
font-family: 'Helvetica Neue', Helvetica, Arial, serif;
color: #000;
}
a {
color: #d5000d;
font-weight: bold;
}
header {
padding-top: 35px;
padding-bottom: 10px;
}
header h1 {
font-weight: bold;
letter-spacing: -1px;
font-size: 48px;
color: #303030;
line-height: 1.2;
}
header h2 {
letter-spacing: -1px;
font-size: 24px;
color: #aaa;
font-weight: normal;
line-height: 1.3;
}
#downloads {
display: none;
}
#main_content {
padding-top: 20px;
}
code, pre {
font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal;
color: #222;
margin-bottom: 30px;
font-size: 12px;
}
code {
padding: 0 3px;
}
pre {
border: solid 1px #ddd;
padding: 20px;
overflow: auto;
}
pre code {
padding: 0;
}
ul, ol, dl {
margin-bottom: 20px;
}
/* COMMON STYLES */
table {
width: 100%;
border: 1px solid #ebebeb;
}
th {
font-weight: 500;
}
td {
border: 1px solid #ebebeb;
text-align: center;
font-weight: 300;
}
form {
background: #f2f2f2;
padding: 20px;
}
/* GENERAL ELEMENT TYPE STYLES */
h1 {
font-size: 2.8em;
}
h2 {
font-size: 22px;
font-weight: bold;
color: #303030;
margin-bottom: 8px;
}
h3 {
color: #d5000d;
font-size: 18px;
font-weight: bold;
margin-bottom: 8px;
}
h4 {
font-size: 16px;
color: #303030;
font-weight: bold;
}
h5 {
font-size: 1em;
color: #303030;
}
h6 {
font-size: .8em;
color: #303030;
}
p {
font-weight: 300;
margin-bottom: 20px;
}
a {
text-decoration: none;
}
p a {
font-weight: 400;
}
blockquote {
font-size: 1.6em;
border-left: 10px solid #e9e9e9;
margin-bottom: 20px;
padding: 0 0 0 30px;
}
ul li {
list-style: disc inside;
padding-left: 20px;
}
ol li {
list-style: decimal inside;
padding-left: 3px;
}
dl dd {
font-style: italic;
font-weight: 100;
}
footer {
margin-top: 40px;
padding-top: 20px;
padding-bottom: 30px;
font-size: 13px;
color: #aaa;
}
footer a {
color: #666;
}
/* MISC */
.clearfix:after {
clear: both;
content: '.';
display: block;
visibility: hidden;
height: 0;
}
.clearfix {display: inline-block;}
* html .clearfix {height: 1%;}
.clearfix {display: block;}

69
stylesheets/pygment_trac.css

@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
.highlight { background: #ffffff; }
.highlight .c { color: #999988; font-style: italic } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { font-weight: bold } /* Keyword */
.highlight .o { font-weight: bold } /* Operator */
.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #999999 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold; } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { font-weight: bold } /* Keyword.Constant */
.highlight .kd { font-weight: bold } /* Keyword.Declaration */
.highlight .kn { font-weight: bold } /* Keyword.Namespace */
.highlight .kp { font-weight: bold } /* Keyword.Pseudo */
.highlight .kr { font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #009999 } /* Literal.Number */
.highlight .s { color: #d14 } /* Literal.String */
.highlight .na { color: #008080 } /* Name.Attribute */
.highlight .nb { color: #0086B3 } /* Name.Builtin */
.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
.highlight .no { color: #008080 } /* Name.Constant */
.highlight .ni { color: #800080 } /* Name.Entity */
.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
.highlight .nn { color: #555555 } /* Name.Namespace */
.highlight .nt { color: #000080 } /* Name.Tag */
.highlight .nv { color: #008080 } /* Name.Variable */
.highlight .ow { font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #009999 } /* Literal.Number.Float */
.highlight .mh { color: #009999 } /* Literal.Number.Hex */
.highlight .mi { color: #009999 } /* Literal.Number.Integer */
.highlight .mo { color: #009999 } /* Literal.Number.Oct */
.highlight .sb { color: #d14 } /* Literal.String.Backtick */
.highlight .sc { color: #d14 } /* Literal.String.Char */
.highlight .sd { color: #d14 } /* Literal.String.Doc */
.highlight .s2 { color: #d14 } /* Literal.String.Double */
.highlight .se { color: #d14 } /* Literal.String.Escape */
.highlight .sh { color: #d14 } /* Literal.String.Heredoc */
.highlight .si { color: #d14 } /* Literal.String.Interpol */
.highlight .sx { color: #d14 } /* Literal.String.Other */
.highlight .sr { color: #009926 } /* Literal.String.Regex */
.highlight .s1 { color: #d14 } /* Literal.String.Single */
.highlight .ss { color: #990073 } /* Literal.String.Symbol */
.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #008080 } /* Name.Variable.Class */
.highlight .vg { color: #008080 } /* Name.Variable.Global */
.highlight .vi { color: #008080 } /* Name.Variable.Instance */
.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
.type-csharp .highlight .k { color: #0000FF }
.type-csharp .highlight .kt { color: #0000FF }
.type-csharp .highlight .nf { color: #000000; font-weight: normal }
.type-csharp .highlight .nc { color: #2B91AF }
.type-csharp .highlight .nn { color: #000000 }
.type-csharp .highlight .s { color: #A31515 }
.type-csharp .highlight .sc { color: #A31515 }

255
stylesheets/styles.css

@ -0,0 +1,255 @@ @@ -0,0 +1,255 @@
@import url(https://fonts.googleapis.com/css?family=Lato:300italic,700italic,300,700);
body {
padding:50px;
font:14px/1.5 Lato, "Helvetica Neue", Helvetica, Arial, sans-serif;
color:#777;
font-weight:300;
}
h1, h2, h3, h4, h5, h6 {
color:#222;
margin:0 0 20px;
}
p, ul, ol, table, pre, dl {
margin:0 0 20px;
}
h1, h2, h3 {
line-height:1.1;
}
h1 {
font-size:28px;
}
h2 {
color:#393939;
}
h3, h4, h5, h6 {
color:#494949;
}
a {
color:#39c;
font-weight:400;
text-decoration:none;
}
a small {
font-size:11px;
color:#777;
margin-top:-0.6em;
display:block;
}
.wrapper {
width:860px;
margin:0 auto;
}
blockquote {
border-left:1px solid #e5e5e5;
margin:0;
padding:0 0 0 20px;
font-style:italic;
}
code, pre {
font-family:Monaco, Bitstream Vera Sans Mono, Lucida Console, Terminal;
color:#333;
font-size:12px;
}
pre {
padding:8px 15px;
background: #f8f8f8;
border-radius:5px;
border:1px solid #e5e5e5;
overflow-x: auto;
}
table {
width:100%;
border-collapse:collapse;
}
th, td {
text-align:left;
padding:5px 10px;
border-bottom:1px solid #e5e5e5;
}
dt {
color:#444;
font-weight:700;
}
th {
color:#444;
}
img {
max-width:100%;
}
header {
width:270px;
float:left;
position:fixed;
}
header ul {
list-style:none;
height:40px;
padding:0;
background: #eee;
background: -moz-linear-gradient(top, #f8f8f8 0%, #dddddd 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f8f8f8), color-stop(100%,#dddddd));
background: -webkit-linear-gradient(top, #f8f8f8 0%,#dddddd 100%);
background: -o-linear-gradient(top, #f8f8f8 0%,#dddddd 100%);
background: -ms-linear-gradient(top, #f8f8f8 0%,#dddddd 100%);
background: linear-gradient(top, #f8f8f8 0%,#dddddd 100%);
border-radius:5px;
border:1px solid #d2d2d2;
box-shadow:inset #fff 0 1px 0, inset rgba(0,0,0,0.03) 0 -1px 0;
width:270px;
}
header li {
width:89px;
float:left;
border-right:1px solid #d2d2d2;
height:40px;
}
header ul a {
line-height:1;
font-size:11px;
color:#999;
display:block;
text-align:center;
padding-top:6px;
height:40px;
}
strong {
color:#222;
font-weight:700;
}
header ul li + li {
width:88px;
border-left:1px solid #fff;
}
header ul li + li + li {
border-right:none;
width:89px;
}
header ul a strong {
font-size:14px;
display:block;
color:#222;
}
section {
width:500px;
float:right;
padding-bottom:50px;
}
small {
font-size:11px;
}
hr {
border:0;
background:#e5e5e5;
height:1px;
margin:0 0 20px;
}
footer {
width:270px;
float:left;
position:fixed;
bottom:50px;
}
@media print, screen and (max-width: 960px) {
div.wrapper {
width:auto;
margin:0;
}
header, section, footer {
float:none;
position:static;
width:auto;
}
header {
padding-right:320px;
}
section {
border:1px solid #e5e5e5;
border-width:1px 0;
padding:20px 0;
margin:0 0 20px;
}
header a small {
display:inline;
}
header ul {
position:absolute;
right:50px;
top:52px;
}
}
@media print, screen and (max-width: 720px) {
body {
word-wrap:break-word;
}
header {
padding:0;
}
header ul, header p.view {
position:static;
}
pre, code {
word-wrap:normal;
}
}
@media print, screen and (max-width: 480px) {
body {
padding:15px;
}
header ul {
display:none;
}
}
@media print {
body {
padding:0.4in;
font-size:12pt;
color:#444;
}
}

479
stylesheets/stylesheet.css

@ -0,0 +1,479 @@ @@ -0,0 +1,479 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
/* LAYOUT STYLES */
body {
font-size: 15px;
line-height: 1.5;
background: #fafafa url(../images/body-bg.jpg) 0 0 repeat;
font-family: 'Helvetica Neue', Helvetica, Arial, serif;
font-weight: 400;
color: #666;
}
a {
color: #2879d0;
}
a:hover {
color: #2268b2;
}
header {
padding-top: 40px;
padding-bottom: 40px;
font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif;
background: #2e7bcf url(../images/header-bg.jpg) 0 0 repeat-x;
border-bottom: solid 1px #275da1;
}
header h1 {
letter-spacing: -1px;
font-size: 72px;
color: #fff;
line-height: 1;
margin-bottom: 0.2em;
width: 540px;
}
header h2 {
font-size: 26px;
color: #9ddcff;
font-weight: normal;
line-height: 1.3;
width: 540px;
letter-spacing: 0;
}
.inner {
position: relative;
width: 940px;
margin: 0 auto;
}
#content-wrapper {
border-top: solid 1px #fff;
padding-top: 30px;
}
#main-content {
width: 690px;
float: left;
}
#main-content img {
max-width: 100%;
}
aside#sidebar {
width: 200px;
padding-left: 20px;
min-height: 504px;
float: right;
background: transparent url(../images/sidebar-bg.jpg) 0 0 no-repeat;
font-size: 12px;
line-height: 1.3;
}
aside#sidebar p.repo-owner,
aside#sidebar p.repo-owner a {
font-weight: bold;
}
#downloads {
margin-bottom: 40px;
}
a.button {
width: 134px;
height: 58px;
line-height: 1.2;
font-size: 23px;
color: #fff;
padding-left: 68px;
padding-top: 22px;
font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif;
}
a.button small {
display: block;
font-size: 11px;
}
header a.button {
position: absolute;
right: 0;
top: 0;
background: transparent url(../images/github-button.png) 0 0 no-repeat;
}
aside a.button {
width: 138px;
padding-left: 64px;
display: block;
background: transparent url(../images/download-button.png) 0 0 no-repeat;
margin-bottom: 20px;
font-size: 21px;
}
code, pre {
font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace;
color: #222;
margin-bottom: 30px;
font-size: 13px;
}
code {
background-color: #f2f8fc;
border: solid 1px #dbe7f3;
padding: 0 3px;
}
pre {
padding: 20px;
background: #fff;
text-shadow: none;
overflow: auto;
border: solid 1px #f2f2f2;
}
pre code {
color: #2879d0;
background-color: #fff;
border: none;
padding: 0;
}
ul, ol, dl {
margin-bottom: 20px;
}
/* COMMON STYLES */
hr {
height: 1px;
line-height: 1px;
margin-top: 1em;
padding-bottom: 1em;
border: none;
background: transparent url('../images/hr.png') 0 0 no-repeat;
}
table {
width: 100%;
border: 1px solid #ebebeb;
}
th {
font-weight: 500;
}
td {
border: 1px solid #ebebeb;
text-align: center;
font-weight: 300;
}
form {
background: #f2f2f2;
padding: 20px;
}
/* GENERAL ELEMENT TYPE STYLES */
#main-content h1 {
font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif;
font-size: 2.8em;
letter-spacing: -1px;
color: #474747;
}
#main-content h1:before {
content: "/";
color: #9ddcff;
padding-right: 0.3em;
margin-left: -0.9em;
}
#main-content h2 {
font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif;
font-size: 22px;
font-weight: bold;
margin-bottom: 8px;
color: #474747;
}
#main-content h2:before {
content: "//";
color: #9ddcff;
padding-right: 0.3em;
margin-left: -1.5em;
}
#main-content h3 {
font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif;
font-size: 18px;
font-weight: bold;
margin-top: 24px;
margin-bottom: 8px;
color: #474747;
}
#main-content h3:before {
content: "///";
color: #9ddcff;
padding-right: 0.3em;
margin-left: -2em;
}
#main-content h4 {
font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif;
font-size: 15px;
font-weight: bold;
color: #474747;
}
h4:before {
content: "////";
color: #9ddcff;
padding-right: 0.3em;
margin-left: -2.8em;
}
#main-content h5 {
font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif;
font-size: 14px;
color: #474747;
}
h5:before {
content: "/////";
color: #9ddcff;
padding-right: 0.3em;
margin-left: -3.2em;
}
#main-content h6 {
font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif;
font-size: .8em;
color: #474747;
}
h6:before {
content: "//////";
color: #9ddcff;
padding-right: 0.3em;
margin-left: -3.7em;
}
p {
margin-bottom: 20px;
}
a {
text-decoration: none;
}
p a {
font-weight: 400;
}
blockquote {
font-size: 1.6em;
border-left: 10px solid #e9e9e9;
margin-bottom: 20px;
padding: 0 0 0 30px;
}
ul {
list-style: disc inside;
padding-left: 20px;
}
ol {
list-style: decimal inside;
padding-left: 3px;
}
dl dd {
font-style: italic;
font-weight: 100;
}
footer {
background: transparent url('../images/hr.png') 0 0 no-repeat;
margin-top: 40px;
padding-top: 20px;
padding-bottom: 30px;
font-size: 13px;
color: #aaa;
}
footer a {
color: #666;
}
footer a:hover {
color: #444;
}
/* MISC */
.clearfix:after {
clear: both;
content: '.';
display: block;
visibility: hidden;
height: 0;
}
.clearfix {display: inline-block;}
* html .clearfix {height: 1%;}
.clearfix {display: block;}
/* #Media Queries
================================================== */
/* Smaller than standard 960 (devices and browsers) */
@media only screen and (max-width: 959px) {}
/* Tablet Portrait size to standard 960 (devices and browsers) */
@media only screen and (min-width: 768px) and (max-width: 959px) {
.inner {
width: 740px;
}
header h1, header h2 {
width: 340px;
}
header h1 {
font-size: 60px;
}
header h2 {
font-size: 30px;
}
#main-content {
width: 490px;
}
#main-content h1:before,
#main-content h2:before,
#main-content h3:before,
#main-content h4:before,
#main-content h5:before,
#main-content h6:before {
content: none;
padding-right: 0;
margin-left: 0;
}
}
/* All Mobile Sizes (devices and browser) */
@media only screen and (max-width: 767px) {
.inner {
width: 93%;
}
header {
padding: 20px 0;
}
header .inner {
position: relative;
}
header h1, header h2 {
width: 100%;
}
header h1 {
font-size: 48px;
}
header h2 {
font-size: 24px;
}
header a.button {
background-image: none;
width: auto;
height: auto;
display: inline-block;
margin-top: 15px;
padding: 5px 10px;
position: relative;
text-align: center;
font-size: 13px;
line-height: 1;
background-color: #9ddcff;
color: #2879d0;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
header a.button small {
font-size: 13px;
display: inline;
}
#main-content,
aside#sidebar {
float: none;
width: 100% ! important;
}
aside#sidebar {
background-image: none;
margin-top: 20px;
border-top: solid 1px #ddd;
padding: 20px 0;
min-height: 0;
}
aside#sidebar a.button {
display: none;
}
#main-content h1:before,
#main-content h2:before,
#main-content h3:before,
#main-content h4:before,
#main-content h5:before,
#main-content h6:before {
content: none;
padding-right: 0;
margin-left: 0;
}
}
/* Mobile Landscape Size to Tablet Portrait (devices and browsers) */
@media only screen and (min-width: 480px) and (max-width: 767px) {}
/* Mobile Portrait Size to Mobile Landscape Size (devices and browsers) */
@media only screen and (max-width: 479px) {}

22
tests/README.md

@ -1,22 +0,0 @@ @@ -1,22 +0,0 @@
# Tests
Directory containing nose regression tests.
## Running Tests
To run the tests, use Nose:
```
nosetests
```
## Running Tests on Ubutunu
Note that to run these tests in Ubuntu, you may need to run
```
nosetests --exe
```
because, annoyingly, nose skips executable files.

4932
tests/SanDiego.xml

File diff suppressed because it is too large Load Diff

4932
tests/SanDiego201402_complete.xml

File diff suppressed because it is too large Load Diff

6
tests/functions.py

@ -1,6 +0,0 @@ @@ -1,6 +0,0 @@
import pantera as pt
def get_gas(T,P,X):
g = pt.Solution('gri30.xml')
g.TPX = T, P, X
return g

41
tests/test_aidt.py

@ -1,41 +0,0 @@ @@ -1,41 +0,0 @@
import pantera as pt
import numpy as np
from numpy import allclose
from functions import *
def get_autoignition_dict():
d = {}
return d
def test_AutoignitionReactor_specify_contents():
"""
Testing initialization of autoignition reactor config with user-specified gas contents
"""
g = pt.GRI30()
T = 998.15
P = pt.one_atm
X = "CH4:1.5, O2:3.0, H:0.00001"
g.TPX = T,P,X
a = pt.AutoignitionConfig(contents=g)
def test_AutoignitionReactor_specify_contents_inputparams():
"""
Testing initialization of autoignition reactor config with user-specified gas contents and input params
"""
g = pt.GRI30()
T = 998.15
P = pt.one_atm
X = "CH4:1.5, O2:3.0"
g.TPX = T,P,X
input_params = get_autoignition_dict()
a = pt.AutoignitionConfig(contents=g,params=input_params)

27
tests/test_bottledgases.py

@ -1,27 +0,0 @@ @@ -1,27 +0,0 @@
from pantera import *
def test_SanDiego():
"""
Testing solutions that use the San Diego mechanism
"""
sd = SanDiego()
# verify something about
# san diego
# (nspecies? something?)
def test_MethaneAir():
"""
Testing methane-air solutions
"""
ma1 = MethaneAir()
# verify mole fractions match
# using numpy compare arrays
phi = 1.0
ma2 = MethaneAir(phi=phi)
phi = 3.0
ma3 = MethaneAir(phi=phi)

39
tests/test_configurations.py

@ -1,39 +0,0 @@ @@ -1,39 +0,0 @@
import pantera as pt
import cantera as ct
import numpy as np
from numpy import allclose
from functions import *
def get_gas():
g = pt.Solution('SanDiego.cti')
g.TPX = 1098.15, 5*ct.one_atm, "C2H6:1.0, O2:4.0"
return g
def test_cantera_reactornet():
"""
Testing basic Cantera ReactorNet functionality
"""
g = get_gas()
ctreactor = ct.Reactor(g)
ctnet = ct.ReactorNet([ctreactor])
ctnet.advance(0.01)
def test_configuration():
"""
Testing basic Pantera Configuration functionality
"""
g = get_gas()
ptreactor = pt.PanteraReactor(g)
ptconfig = pt.Configuration(g)
ptconfig.advance(0.01)
def test_piston_cylinder_config():
"""
Testing basic piston cylinder configuration functionality
"""
g = get_gas()
pc = pt.PistonCylinderConfig(g)
pc.advance(0.01)

176
tests/test_gases.py

@ -1,176 +0,0 @@ @@ -1,176 +0,0 @@
from pantera import *
def mix1():
T = 873.15
P = OneAtm
X = "CO2:2.0, CO:2.0"
sol = Solution('gri30.xml')
sol.TPX = T,P,X
return sol
def mix2():
T = 973.15
P = 3*OneAtm
X = "CH4:8.0, C2H6:1.0"
sol = Solution('gri30.xml')
sol.TPX = T,P,X
return sol
def mix3():
T = 1073.15
P = 5*OneAtm
X = "N2:10.0, AR:1.0"
sol = Solution('gri30.xml')
sol.TPX = T,P,X
return sol
def get_gases_to_mix():
g1=mix1()
g2=mix2()
g3=mix3()
return [g1,g2,g3]
def test_mixing():
"""Testing getGasMixture function"""
gs = get_gases_to_mix()
result = getGasMixture(gs,[1.0,1.0,2.0], model_file='gri30.xml', gas_phase_name='gri30')
def test_gas2vector():
"""
Testing conversion of gas to vector representation of composition.
"""
g = mix1()
lead_vector = convert_gas_to_composition_vector(g)
gold_vector = zeros(g.n_species)
gold_vector[g.species_index('CO2')] = 2.0
gold_vector[g.species_index('CO')] = 2.0
# normalize
gold_vector = gold_vector/sum(gold_vector)
assert allclose(gold_vector,lead_vector,1.0e-5)
def test_gas2string():
"""
Testing conversion of gas to string representation of composition.
"""
g = mix1()
lead_string = convert_gas_to_composition_string(g)
gold_string = "CO2:0.5000000000000000, CO:0.5000000000000000"
assert lead_string==gold_string
def test_gas2dict():
"""
Testing conversion of gas to dict representation of composition.
"""
g = mix1()
lead_dict = convert_gas_to_composition_dict(g)
gold_dict = {}
gold_dict['CO2'] = 2.0
gold_dict['CO'] = 2.0
# normalize
gold_sum = sum( [gold_dict[k] for k in gold_dict.keys()] )
for k in gold_dict.keys():
gold_dict[k] = gold_dict[k]/gold_sum
assert lead_dict==gold_dict
def test_arrays2dict():
"""
Testing conversion of species names/fractions arrays to dict representation of composition.
"""
names = ['CH4','C2H6','H2']
moleFractions = [0.2,0.4,0.4]
lead_dict = convert_arrays_to_dict(names,moleFractions)
gold_dict = {}
for name, frac in zip(names, moleFractions):
gold_dict[name] = frac
assert lead_dict==gold_dict
def test_vector2dict():
"""
Testing conversion of species vector to species dict.
"""
g = mix2()
starting_vector = zeros(g.n_species,)
starting_vector[g.species_index('CH4')] = 8.0
starting_vector[g.species_index('C2H6')] = 1.0
starting_vector = starting_vector/sum(starting_vector)
lead_dict = convert_composition_vector_to_dict(g,starting_vector)
gold_dict = {}
gold_dict['CH4'] = 8.0
gold_dict['C2H6'] = 1.0
# normalize
gold_sum = sum( [gold_dict[k] for k in gold_dict.keys()] )
for k in gold_dict.keys():
gold_dict[k] = gold_dict[k]/gold_sum
assert lead_dict==gold_dict
def test_dict2vector():
"""
Testing conversion of species dict to species vector.
"""
g = mix2()
starting_dict = {}
starting_dict['CH4'] = 8.0
starting_dict['C2H6'] = 1.0
lead_vector = convert_composition_dict_to_vector(g,starting_dict)
gold_vector = zeros(g.n_species)
gold_vector[ g.species_index('CH4') ] = 8.0
gold_vector[ g.species_index('C2H6') ] = 1.0
gold_vector = gold_vector/sum(gold_vector)
assert allclose(lead_vector,gold_vector,1.0e-5)
def test_string2dict():
"""
Testing conversion of species string to species dict.
"""
g = mix2()
starting_string = "CO2:2.0, CO:2.0"
lead_dict = convert_composition_string_to_dict(starting_string)
gold_dict = {}
gold_dict['CO2'] = 2.0
gold_dict['CO'] = 2.0
# normalize
gold_sum = sum( [gold_dict[k] for k in gold_dict.keys()] )
for k in gold_dict.keys():
gold_dict[k] = gold_dict[k]/gold_sum
print lead_dict
print gold_dict
assert lead_dict==gold_dict
def test_dict2string():
"""
Testing conversion of species dict to species string.
"""
g = mix2()

94
tests/test_pistoncylinders.py

@ -1,94 +0,0 @@ @@ -1,94 +0,0 @@
import pantera as pt
import numpy as np
from numpy import allclose
from functions import *
def test_PistonCylinder_empty():
"""
Testing initialization of PistonCylinder with no inputs
"""
pc = pt.PistonCylinderConfig()
def test_PistonCylinder_specify_contents():
"""
Testing initialization of piston cylinder configuration with user-specified contents
"""
T = 998.15
P = pt.one_atm
X = "CH4:1.5, O2:3.0"
g = get_gas(T,P,X)
pc = pt.PistonCylinderConfig(contents=g)
assert np.allclose(pc.T,T)
assert np.allclose(pc.P,P)
def test_PistonCylinder_shorthand_specify_contents():
"""
Testing shorthand initialization of piston cylinder configuration with Cantera-style contents specification
"""
T = 998.15
P = pt.one_atm
X = "CH4:1.5, O2:3.0"
g = get_gas(T,P,X)
pc = pt.PistonCylinderConfig(g)
assert np.allclose(pc.T,T)
assert np.allclose(pc.P,P)
pci = pt.PistonCylinderConfig(g,energy='off')
assert np.allclose(pci.T,T)
assert np.allclose(pci.P,P)
def test_PistonCylinder_specify_contents_environment():
"""
Testing initialization of PistonCylinder with user-specified contents and environment
"""
T = 998.15
P = pt.one_atm
X = "CH4:1.5, O2:3.0"
g = get_gas(T,P,X)
Te = 998.15
Pe = pt.one_atm
Xe = "N2:0.79, O2:0.21"
e = get_gas(Te,Pe,Xe)
# create reactor
pc = pt.PistonCylinderConfig(contents=g,environment=e)
assert np.allclose(pc.T,T)
assert np.allclose(pc.P,P)
def test_PistonCylinder_specify_contents_inputparams():
"""
Testing initialization of PistonCylinder with user-specified contents and input param dict
"""
T = 998.15
P = pt.one_atm
X = "CH4:1.5, O2:3.0"
g = get_gas(T,P,X)
input_params = {'dummyvar1':10.0,'dummyvar2':100.0}
# create reactor
pc = pt.PistonCylinderConfig(contents=g,params=input_params)
assert np.allclose(pc.T,T)
assert np.allclose(pc.P,P)
c = pc._contents
assert c!=None
assert pc.params['dummyvar1']==10.0
assert pc.params['dummyvar2']==100.0

60
tests/test_reactors.py

@ -1,60 +0,0 @@ @@ -1,60 +0,0 @@
import pantera as pt
import numpy as np
from numpy import allclose
from functions import *
def test_PanteraReactor_empty():
"""
Testing initialization of PanteraReactor
with no inputs
"""
# make sure no params works
pr = pt.PanteraReactor()
def test_PanteraReactor_contents_inputparams():
"""
Testing initialization of PanteraReactor
with user-specified contents and input param dict
"""
# prep contents/input params
T = 998.15
P = pt.one_atm
X = "CH4:1.5, O2:3.0"
g = get_gas(T,P,X)
input_params = {'dummyvar1':10.0,'dummyvar2':100.0}
# create reactor
pr = pt.PanteraReactor(contents=g,params=input_params)
# test that Canter reactor methods
# are extended/inherited properly
assert np.allclose(pr.T,T)
assert np.allclose(pr.P,P)
# test that we can access reactor contents,
# a property defined by the Pantera library
c = pr._contents
assert c != None
# test that we can access our input parameter values
assert pr.params['dummyvar1']==10.0
assert pr.params['dummyvar2']==100.0
Loading…
Cancel
Save