Compare commits
No commits in common. 'master' and 'gh-pages' have entirely different histories.
@ -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/ |
|
||||||
|
|
@ -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. |
|
@ -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... |
|
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 3.1 KiB |
@ -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 — Theme by <a href="https://github.com/orderedlist">orderedlist</a></small></p> |
||||||
|
</footer> |
||||||
|
</div> |
||||||
|
<script src="javascripts/scale.fix.js"></script> |
||||||
|
|
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1 @@ |
|||||||
|
console.log('This would be the main JS file.'); |
@ -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"; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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 |
|
||||||
``` |
|
@ -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 * |
|
||||||
|
|
@ -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 |
|
||||||
|
|
@ -1,5 +0,0 @@ |
|||||||
from PanteraConfigs import * |
|
||||||
|
|
||||||
class AutoignitionConfig(Configuration): |
|
||||||
pass |
|
||||||
|
|
@ -1,5 +0,0 @@ |
|||||||
from PanteraConfigs import * |
|
||||||
|
|
||||||
class EquilibriumConfig(Configuration): |
|
||||||
pass |
|
||||||
|
|
@ -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 |
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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) |
|
||||||
|
|
||||||
|
|
@ -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 |
|
@ -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) |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,4 +0,0 @@ |
|||||||
from PanteraConfigs import * |
|
||||||
from PistonCylinderConfigs import * |
|
||||||
from AutoignitionConfigs import * |
|
||||||
from EquilibriumConfigs import * |
|
@ -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 |
|
||||||
""" |
|
||||||
|
|
@ -1,5 +0,0 @@ |
|||||||
class PanteraException(Exception): |
|
||||||
pass |
|
||||||
|
|
||||||
class PanteraGasChangedException(PanteraException): |
|
||||||
pass |
|
@ -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 |
|
||||||
|
|
@ -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 |
|
||||||
|
|
||||||
|
|
@ -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 |
|
||||||
|
|
@ -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.) |
|
||||||
|
|
@ -1,3 +0,0 @@ |
|||||||
from BottledGases import * |
|
||||||
from CanteraCompositionUtils import * |
|
||||||
from CanteraGasUtils import * |
|
@ -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). |
|
||||||
|
|
@ -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)) |
|
@ -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 |
|
||||||
|
|
||||||
|
|
@ -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') |
|
||||||
|
|
@ -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 |
|
||||||
""" |
|
||||||
|
|
@ -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) |
|
||||||
|
|
@ -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 |
|
||||||
|
|
@ -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 |
|
||||||
|
|
@ -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)! |
|
||||||
|
|
@ -1,5 +0,0 @@ |
|||||||
""" |
|
||||||
Tubular reactors are isothermal PFRs |
|
||||||
Extend PFR class |
|
||||||
""" |
|
||||||
|
|
@ -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."} |
@ -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) |
|
@ -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;} |
@ -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 } |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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) {} |
@ -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. |
|
||||||
|
|
@ -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 |
|
@ -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) |
|
||||||
|
|
@ -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) |
|
||||||
|
|
@ -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) |
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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() |
|
||||||
|
|
@ -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 |
|
||||||
|
|
||||||
|
|
@ -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 |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|