Reformatted the Python docstrings to work better with Sphinx

This means that the docstrings are now parsed as reStructuredText.
This commit is contained in:
Ray Speth 2012-03-13 17:34:47 +00:00
parent 09d9ded2e7
commit b4ceb7da2e
26 changed files with 1059 additions and 866 deletions

View file

@ -14,6 +14,8 @@ if localenv['sphinx_docs']:
localenv['SPHINXBUILD'] = Dir('#build/sphinx')
localenv['SPHINXSRC'] = Dir('sphinx')
build(localenv.Command('${SPHINXBUILD}/html/index.html',
'sphinx/conf.py',
'sphinx-build -b html -d ${SPHINXBUILD}/doctrees ${SPHINXSRC} ${SPHINXBUILD}/html'))
sphinxdocs = build(localenv.Command('${SPHINXBUILD}/html/index.html',
'sphinx/conf.py',
'sphinx-build -b html -d ${SPHINXBUILD}/doctrees ${SPHINXSRC} ${SPHINXBUILD}/html'))
localenv.AlwaysBuild(sphinxdocs)

View file

@ -17,6 +17,7 @@ import sys, os
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('../../interfaces/python'))
sys.path.append(os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
@ -25,11 +26,20 @@ sys.path.insert(0, os.path.abspath('../../interfaces/python'))
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.pngmath',
'sphinx.ext.autosummary']
extensions = ['sphinx.ext.autodoc',
'sphinx.ext.todo',
'sphinx.ext.autosummary',
'mathjax']
# @todo: Sphinx version 1.1 adds support for MathJax, so we can remove the
# custom extension for that once that version becomes more standard
autodoc_default_flags = ['members','show-inheritance','undoc-members']
autoclass_content = 'both'
mathjax_path = 'http://mathjax.connectmv.com/MathJax.js'
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

View file

@ -1,4 +1,12 @@
Func Module
===========
Quick links:
* :class:`.Polynomial`
* :class:`.Gaussian`
* :class:`.Fourier`
* :class:`.Arrhenius`
.. automodule:: Cantera.Func
:member-order: bysource
:no-show-inheritance:

68
doc/sphinx/mathjax.py Normal file
View file

@ -0,0 +1,68 @@
# -*- coding: utf-8 -*-
"""
sphinx.ext.mathjax
~~~~~~~~~~~~~~~~~~
Allow `MathJax <http://mathjax.org/>`_ to be used to display math
in Sphinx's HTML writer - requires the MathJax JavaScript library
on your webserver/computer.
Kevin Dunn, kgdunn@gmail.com, 3-clause BSD license.
For background, installation details and support:
https://bitbucket.org/kevindunn/sphinx-extension-mathjax
"""
from docutils import nodes
from sphinx.application import ExtensionError
from sphinx.ext.mathbase import setup_math as mathbase_setup
def html_visit_math(self, node):
self.body.append(self.starttag(node, 'span', '', CLASS='math'))
self.body.append(self.builder.config.mathjax_inline[0] + \
self.encode(node['latex']) +\
self.builder.config.mathjax_inline[1] + '</span>')
raise nodes.SkipNode
def html_visit_displaymath(self, node):
self.body.append(self.starttag(node, 'div', CLASS='math'))
if node['nowrap']:
self.body.append(self.builder.config.mathjax_display[0] + \
node['latex'] +\
self.builder.config.mathjax_display[1])
self.body.append('</div>')
raise nodes.SkipNode
parts = [prt for prt in node['latex'].split('\n\n') if prt.strip() != '']
for i, part in enumerate(parts):
part = self.encode(part)
if i == 0:
# necessary to e.g. set the id property correctly
if node['number']:
self.body.append('<span class="eqno">(%s)</span>' %
node['number'])
if '&' in part or '\\\\' in part:
self.body.append(self.builder.config.mathjax_display[0] + \
'\\begin{split}' + part + '\\end{split}' + \
self.builder.config.mathjax_display[1])
else:
self.body.append(self.builder.config.mathjax_display[0] + part + \
self.builder.config.mathjax_display[1])
self.body.append('</div>\n')
raise nodes.SkipNode
def builder_inited(app):
if not app.config.mathjax_path:
raise ExtensionError('mathjax_path config value must be set for the '
'mathjax extension to work')
app.add_javascript(app.config.mathjax_path)
def setup(app):
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
app.add_config_value('mathjax_path', '', False)
app.add_config_value('mathjax_inline', [r'\(', r'\)'], 'html')
app.add_config_value('mathjax_display', [r'\[', r'\]'], 'html')
app.connect('builder-inited', builder_inited)

View file

@ -1,4 +1,4 @@
Transport Properties
====================
.. autoclass:: Cantera.Transport.Transport
.. automodule:: Cantera.Transport

View file

@ -12,28 +12,27 @@ class Edge(EdgePhase, Kinetics):
Instances of class Edge represent reacting 1D edges between
between 2D surfaces. Class Edge defines no methods of its
own. All of its methods derive from either EdgePhase or Kinetics.
own. All of its methods derive from either :class:`.EdgePhase` or
:class:`.Kinetics`.
Function importInterface should usually be used to build an
Function :func:`.importInterface` should usually be used to build an
Edge object from a CTI file definition, rather than calling
the Interface constructor directly.
See: EdgePhase, Kinetics, importInterface
the :class:`.Edge` constructor directly.
"""
def __init__(self, src="", root=None, surfaces=[]):
"""
src - CTML or CTI input file name. If more than one phase is
defined in the file, src should be specified as 'filename\#id'
If the file is not CTML, it will be run through the CTI -> CTML
preprocessor first.
root - If a CTML tree has already been read in that contains
the definition of this interface, the root of this tree can be
specified instead of specifying 'src'.
phases - A list of all objects representing the neighboring
surface phases which participate in the reaction mechanism.
:param src:
CTML or CTI input file name. If more than one phase is
defined in the file, src should be specified as ``filename#id``
If the file is not CTML, it will be run through the CTI -> CTML
preprocessor first.
:param root:
If a CTML tree has already been read in that contains
the definition of this interface, the root of this tree can be
specified instead of specifying *src*.
:param phases:
A list of all objects representing the neighboring
surface phases which participate in the reaction mechanism.
"""
self.ckin = 0
self._owner = 0

View file

@ -1,11 +1,8 @@
"""
The classes in this module are designed to allow constructing
user-defined functions of one variable in Python that can be used with the
Cantera C++ kernel. These classes are mostly shadow classes for
corresponding classes in the C++ kernel.
"""
from Cantera.num import array, asarray, ravel, shape, transpose
@ -14,31 +11,33 @@ import types
class Func1:
"""Functors of one variable.
"""
Functors of one variable.
A Functor is an object that behaves like a function. Class 'Func1'
A Functor is an object that behaves like a function. :class:`Func1`
is the base class from which several functor classes derive. These
classes are designed to allow specifying functions of time from Python
that can be used by the C++ kernel.
Functors can be added, multiplied, and divided to yield new functors.
>>> f1 = Polynomial([1.0, 0.0, 3.0]) # 3*t*t + 1
>>> f1(2.0)
___13
13
>>> f2 = Polynomial([-1.0, 2.0]) # 2*t - 1
>>> f2(2.0)
___5
5
>>> f3 = f1/f2 # (3*t*t + 1)/(2*t - 1)
>>> f3(2.0)
___4.3333333
4.3333333
"""
def __init__(self, typ, n, coeffs=[]):
"""
The constructor is
meant to be called from constructors of subclasses of Func1.
See: Polynomial, Gaussian, Arrhenius, Fourier, Const,
PeriodicFunction """
The constructor is meant to be called from constructors of subclasses
of Func1: :class:`Polynomial`, :class:`Gaussian`, :class:`Arrhenius`,
:class:`Fourier`, :class:`Const`, :class:`PeriodicFunction`.
"""
self.n = n
self._own = 1
self._func_id = 0
@ -166,13 +165,14 @@ class Pow(Func1):
Func1.__init__(self,106,1,n)
class Polynomial(Func1):
"""A polynomial.
r"""
A polynomial.
Instances of class 'Polynomial' evaluate
\f[
f(t) = \sum_{n = 0}^N a_n t^n.
\f]
The coefficients are supplied as a list, beginning with
\f$a_N\f$ and ending with \f$a_0\f$.
.. math:: f(t) = \sum_{n = 0}^N a_n t^n .
The coefficients are supplied as a list, beginning with :math:`a_N` and
ending with :math:`a_0`.
>>> p1 = Polynomial([1.0, -2.0, 3.0]) # 3t^2 - 2t + 1
>>> p2 = Polynomial([6.0, 8.0]) # 8t + 6
@ -187,26 +187,26 @@ class Polynomial(Func1):
class Gaussian(Func1):
"""A Gaussian pulse. Instances of class 'Gaussian' evaluate
\f[
f(t) = A \exp[-(t - t_0) / \tau]
\f]
r"""A Gaussian pulse. Instances of class 'Gaussian' evaluate
.. math:: f(t) = A \exp[-(t - t_0) / \tau]
where
\f[
\tau = \frac{\mbox{FWHM}}{2.0\sqrt{\ln(2.0)}}
\f]
.. math:: \tau = \frac{\mbox{FWHM}}{2.0\sqrt{\ln(2.0)}}
'FWHM' denotes the full width at half maximum.
As an example, here is how to create
a Gaussian pulse with peak amplitude 10.0, centered at time 2.0,
with full-width at half max = 0.2:
As an example, here is how to create a Gaussian pulse with peak amplitude
10.0, centered at time 2.0, with full-width at half max = 0.2:
>>> f = Gaussian(A = 10.0, t0 = 2.0, FWHM = 0.2)
>>> f(2.0)
___10
10
>>> f(1.9)
___5
5
>>> f(2.1)
___5
5
"""
def __init__(self, A, t0, FWHM):
coeffs = array([A, t0, FWHM], 'd')
@ -214,35 +214,41 @@ class Gaussian(Func1):
class Fourier(Func1):
"""Fourier series. Instances of class 'Fourier' evaluate the Fourier series
\f[
f(t) = \frac{a_0}{2} + \sum_{n=1}^N [a_n \cos(n\omega t) + b_n \sin(n \omega t)]
\f]
r"""
Fourier series. Instances of class 'Fourier' evaluate the Fourier series
.. math::
f(t) = \frac{a_0}{2} +
\sum_{n=1}^N [a_n \cos(n\omega t) + b_n \sin(n \omega t)]
where
\f[
a_n = \frac{\omega}{\pi}
\int_{-\pi/\omega}^{\pi/\omega} f(t) \cos(n \omega t) dt
\f]
and
\f[
b_n = \frac{\omega}{\pi}
\int_{-\pi/\omega}^{\pi/\omega} f(t) \sin(n \omega t) dt.
\f]
The function \f$ f(t) \f$ is periodic, with period \f$ T = 2\pi/\omega \f$.
.. math::
a_n = \frac{\omega}{\pi}
\int_{-\pi/\omega}^{\pi/\omega} f(t) \cos(n \omega t) dt
b_n = \frac{\omega}{\pi}
\int_{-\pi/\omega}^{\pi/\omega} f(t) \sin(n \omega t) dt.
The function :math:`f(t)` is periodic, with period :math:`T = 2\pi/\omega`.
As an example, a function with Fourier components up to the second harmonic
is constructed as follows:
>>> coeffs = [(a0, b0), (a1, b1), (a2, b2)]
>>> f = Fourier(omega, coeffs)
Note that 'b0' must be specified, but is not
used. The value of 'b0' is arbitrary.
Note that ``b0`` must be specified, but is not used. The value of ``b0``
is arbitrary.
"""
def __init__(self, omega, coefficients):
"""
omega - fundamental frequency [radians/sec].
coefficients - List of (a,b) pairs, beginning with \f$n = 0\f$.
:param omega:
fundamental frequency [radians/sec].
:param coefficients:
List of (a,b) pairs, beginning with n = 0.
"""
cc = asarray(coefficients,'d')
n, m = cc.shape
@ -252,30 +258,19 @@ class Fourier(Func1):
Func1.__init__(self, 1, n-1, ravel(transpose(cc)))
##Sum of modified Arrhenius terms. Instances of class 'Arrhenius' evaluate
# \f[
# f(T) = \sum_{n=1}^N A_n T^{b_n}\exp(-E_n/T)
# \f]
#
# Example:
#
# >>> f = Arrhenius([(a0, b0, e0), (a1, b1, e1)])
#
class Arrhenius(Func1):
"""Sum of modified Arrhenius terms. Instances of class 'Arrhenius' evaluate
\f[
f(T) = \sum_{n=1}^N A_n T^{b_n}\exp(-E_n/T)
\f]
r"""Sum of modified Arrhenius terms. Instances of class 'Arrhenius' evaluate
.. math:: f(T) = \sum_{n=1}^N A_n T^{b_n}\exp(-E_n/T)
Example:
>>> f = Arrhenius([(a0, b0, e0), (a1, b1, e1)])
"""
def __init__(self, coefficients):
"""
coefficients - sequence of \f$(A, b, E)\f$ triplets.
:param coefficients:
sequence of (*A*, *b*, *E*) triplets.
"""
cc = asarray(coefficients,'d')
n, m = cc.shape
@ -284,15 +279,16 @@ class Arrhenius(Func1):
Func1.__init__(self, 3, n, ravel(cc))
class Const(Func1):
"""Constant function.
Objects created by function Const
act as functions that have a constant value.
These are used internally whenever a statement like
Objects created by function Const act as functions that have a constant
value. These are used internally whenever a statement like
>>> f = Gausian(2.0, 1.0, 0.1) + 4.0
is encountered. The addition operator of class Func1 is defined
so that this is equivalent to
is encountered. The addition operator of class Func1 is defined so that
this is equivalent to
>>> f = SumFunction(Gaussian(2.0, 1.0, 0.1), Const(4.0))
Function Const returns instances of class Polynomial that have
@ -307,9 +303,10 @@ class PeriodicFunction(Func1):
"""Converts a function into a periodic function with period T."""
def __init__(self, func, T):
"""
func - initial non-periodic function
T - period [s]
:param func:
initial non-periodic function
:param T:
period [s]
"""
Func1.__init__(self, 50, func.func_id(), array([T],'d'))
func._own = 0
@ -323,7 +320,6 @@ class ComboFunc1(Func1):
This class is the base class for functors that combine two
other functors in a binary operation.
"""
def __init__(self, typ, f1, f2):
self._own = 1
self._func_id = 0
@ -345,18 +341,21 @@ class SumFunction(ComboFunc1):
It is not necessary to explicitly create an instance of SumFunction, since
the addition operator of the base class is overloaded to return a SumFunction
instance.
>>> f1 = Polynomial([2.0, 1.0])
>>> f2 = Polynomial([3.0, -5.0])
>>> f3 = f1 + f2 # functor to evaluate (2t + 1) + (3t - 5)
In this example, object 'f3' is a functor of class'SumFunction' that calls f1 and f2
and returns their sum.
In this example, object 'f3' is a functor of class'SumFunction' that calls
f1 and f2 and returns their sum.
"""
def __init__(self, f1, f2):
"""
f1 - first functor.
f2 - second functor.
:param f1:
first functor.
:param f2:
second functor.
"""
ComboFunc1.__init__(self, 20, f1, f2)
@ -367,23 +366,25 @@ class DiffFunction(ComboFunc1):
functors. It is not necessary to explicitly create an instance of
DiffFunction, since the subtraction operator of the base class is
overloaded to return a DiffFunction instance.
>>> f1 = Polynomial([2.0, 1.0])
>>> f2 = Polynomial([3.0, -5.0])
>>> f3 = f1 - f2 # functor to evaluate (2t + 1) - (3t - 5)
In this example, object 'f3' is a functor of class'DiffFunction' that
calls f1 and f2 and returns their difference.
"""
def __init__(self, f1, f2):
"""
f1 - first functor.
f2 - second functor.
:param f1:
first functor.
:param f2:
second functor.
"""
ComboFunc1.__init__(self, 25, f1, f2)
class ProdFunction(ComboFunc1):
"""Product of two functions. Instances of class ProdFunction
evaluate the product of two supplied functors. It is not
necessary to explicitly create an instance of 'ProdFunction',
@ -395,11 +396,14 @@ class ProdFunction(ComboFunc1):
>>> f3 = f1 * f2 # functor to evaluate (2t + 1)*(3t - 5)
In this example, object 'f3' is a functor of class'ProdFunction'
that calls f1 and f2 and returns their product. """
that calls f1 and f2 and returns their product.
"""
def __init__(self, f1, f2):
""" f1 - first functor.
f2 - second functor.
"""
:param f1:
first functor.
:param f2:
second functor.
"""
ComboFunc1.__init__(self, 30, f1, f2)
@ -410,40 +414,45 @@ class RatioFunction(ComboFunc1):
It is not necessary to explicitly create an instance of 'RatioFunction', since
the division operator of the base class is overloaded to return a RatioFunction
instance.
>>> f1 = Polynomial([2.0, 1.0])
>>> f2 = Polynomial([3.0, -5.0])
>>> f3 = f1 / f2 # functor to evaluate (2t + 1)/(3t - 5)
In this example, object 'f3' is a functor of class'RatioFunction' that calls f1 and f2
and returns their ratio.
In this example, object 'f3' is a functor of class'RatioFunction' that
calls f1 and f2 and returns their ratio.
"""
def __init__(self, f1, f2):
"""
f1 - first functor.
f2 - second functor.
:param f1:
first functor.
:param f2:
second functor.
"""
ComboFunc1.__init__(self, 40, f1, f2)
## Function of a function.
# Instances of class CompositeFunction evaluate f(g(t)) for two supplied
# functors f and g. It is not necessary to explicitly create an instance
# of 'CompositeFunction', since the () operator of the base class is
# overloaded to return a CompositeFunction when called with a functor
# argument.
# @example
# >>> f1 = Polynomial([2.0, 1.0])
# >>> f2 = Polynomial([3.0, -5.0])
# >>> f3 = f1(f2) # functor to evaluate 2(3t - 5) + 1
# In this example, object 'f3' is a functor of class'CompositeFunction'
# that calls f1 and f2 and returns f1(f2(t)).
class CompositeFunction(ComboFunc1):
"""
Function of a function.
Instances of class CompositeFunction evaluate f(g(t)) for two supplied
functors f and g. It is not necessary to explicitly create an instance
of 'CompositeFunction', since the () operator of the base class is
overloaded to return a CompositeFunction when called with a functor
argument.
>>> f1 = Polynomial([2.0, 1.0])
>>> f2 = Polynomial([3.0, -5.0])
>>> f3 = f1(f2) # functor to evaluate 2(3t - 5) + 1
In this example, object 'f3' is a functor of class'CompositeFunction'
that calls f1 and f2 and returns f1(f2(t)).
"""
def __init__(self, f1, f2):
"""
f1 - first functor.
f2 - second functor.
:param f1:
first functor.
:param f2:
second functor.
"""
ComboFunc1.__init__(self, 60, f1, f2)
@ -455,8 +464,9 @@ class DerivativeFunction(Func1):
self._own = 1
self._func_id = _cantera.func_derivative(f.func_id())
##
# The derivative of f
#
def derivative(f):
"""
Take the derivative of a functor *f*
"""
return DerivativeFunction(f)

View file

@ -12,28 +12,27 @@ class Interface(SurfacePhase, Kinetics):
Instances of class Interface represent reacting 2D interfaces
between bulk 3D phases. Class Interface defines no methods of its
own. All of its methods derive from either SurfacePhase or Kinetics.
own. All of its methods derive from either :class:`.SurfacePhase` or
:class:`.Kinetics`.
Function importInterface should usually be used to build an
Function :func:`.importInterface` should usually be used to build an
Interface object from a CTI file definition, rather than calling
the Interface constructor directly.
See: SurfacePhase, Kinetics, importInterface
"""
def __init__(self, src="", root=None, phases=[], debug = 0):
"""
src - CTML or CTI input file name. If more than one phase is
defined in the file, src should be specified as 'filename\#id'
If the file is not CTML, it will be run through the CTI -> CTML
preprocessor first.
root - If a CTML tree has already been read in that contains
the definition of this interface, the root of this tree can be
specified instead of specifying 'src'.
phases - A list of all objects representing the neighboring phases
which participate in the reaction mechanism.
:param src:
CTML or CTI input file name. If more than one phase is
defined in the file, src should be specified as ``filename#id``
If the file is not CTML, it will be run through the CTI -> CTML
preprocessor first.
:param root:
If a CTML tree has already been read in that contains the
definition of this interface, the root of this tree can be
specified instead of specifying *src*.
:param phases:
A list of all objects representing the neighboring phases which
participate in the reaction mechanism.
"""
self.ckin = 0
self._owner = 0

View file

@ -13,19 +13,18 @@ class Kinetics:
Kinetics managers. Instances of class Kinetics are responsible for
evaluating reaction rates of progress, species production rates,
and other quantities pertaining to a reaction mechanism.
parameters -
kintype - integer specifying the type of kinetics manager to create.
"""
def __init__(self, kintype=-1, thrm=0, xml_phase=None, id=None, phases=[]):
"""Build a kinetics manager from an XML specification.
root -- root of a CTML tree
id -- id of the 'kinetics' node within the tree that contains
the specification of the parameters.
"""
Build a kinetics manager from an XML specification.
:param kintype:
Integer specifying the type of kinetics manager to create.
:param root:
Root of a CTML tree
:param id:
id of the 'kinetics' node within the tree that contains the
specification of the parameters.
"""
np = len(phases)
self._sp = []
@ -82,8 +81,11 @@ class Kinetics:
def kineticsSpeciesIndex(self, name, phase):
"""The index of a species.
name -- species name
phase -- phase name
:param name:
species name
:param phase:
phase name
Kinetics managers for heterogeneous reaction mechanisms
maintain a list of all species in all phases. The order of the
@ -118,13 +120,13 @@ class Kinetics:
def isReversible(self,i):
"""
True (1) if reaction number 'i' is reversible,
True (1) if reaction number *i* is reversible,
and false (0) otherwise.
"""
return _cantera.kin_isreversible(self.ckin,i)
def reactionType(self,i):
"""Type of reaction 'i'"""
"""Type of reaction *i*"""
return _cantera.kin_rxntype(self.ckin,i)
def reactionEqn(self,i):
@ -139,7 +141,7 @@ class Kinetics:
return self.reactionString(i)
def reactionString(self, i):
"""Reaction string for reaction number 'i'"""
"""Reaction string for reaction number *i*"""
s = ''
nsp = _cantera.kin_nspecies(self.ckin)
for k in range(nsp):
@ -169,7 +171,7 @@ class Kinetics:
return s
def reactantStoichCoeff(self,k,i):
"""The stoichiometric coefficient of species k as a reactant in reaction i."""
"""The stoichiometric coefficient of species *k* as a reactant in reaction *i*."""
return _cantera.kin_rstoichcoeff(self.ckin,k,i)
def reactantStoichCoeffs(self):
@ -185,13 +187,13 @@ class Kinetics:
return nu
def productStoichCoeff(self,k,i):
"""The stoichiometric coefficient of species k as a product in reaction i."""
"""The stoichiometric coefficient of species *k* as a product in reaction *i*."""
return _cantera.kin_pstoichcoeff(self.ckin,k,i)
def productStoichCoeffs(self):
"""The array of product stoichiometric coefficients. Element
[k,i] of this array is the product stoichiometric
coefficient of species k in reaction i."""
coefficient of species *k* in reaction *i*."""
nsp = _cantera.kin_nspecies(self.ckin)
nr = _cantera.kin_nreactions(self.ckin)
nu = zeros((nsp,nr),'d')

View file

@ -6,17 +6,21 @@ class BurnerDiffFlame(Stack):
def __init__(self, gas = None, burner = None, outlet = None, grid = None):
"""
gas -- object to use to evaluate all gas properties and reaction
rates. Required
burner -- Inlet object representing the burner. Optional;
if not supplied, one will be created with name 'burner'
outlet -- Outlet object representing the outlet. Optional;
if not supplied, one will be created with name 'outlet'
grid -- array of initial grid points
:param gas:
object to use to evaluate all gas properties and reaction
rates. Required
:param burner:
Inlet object representing the burner. Optional; if not supplied,
one will be created with name 'burner'
:param outlet:
Outlet object representing the outlet. Optional; if not supplied,
one will be created with name 'outlet'
:param grid:
array of initial grid points
A domain of type AxisymmetricFlow named 'flame' will be created to
represent the flame. The three domains comprising the stack
are stored as self.burner, self.flame, and self.outlet.
A domain of type :class:`.AxisymmetricFlow` named 'flame' will be
created to represent the flame. The three domains comprising the stack
are stored as ``self.burner``, ``self.flame``, and ``self.outlet``.
"""
if burner:
@ -70,14 +74,14 @@ class BurnerDiffFlame(Stack):
def solve(self, loglevel = 1, refine_grid = 1):
"""Solve the flame. See Stack.solve"""
"""Solve the flame. :meth:`.Stack.solve`"""
if not self._initialized: self.init()
Stack.solve(self, loglevel = loglevel, refine_grid = refine_grid)
def setRefineCriteria(self, ratio = 10.0, slope = 0.8,
curve = 0.8, prune = 0.0):
"""See Stack.setRefineCriteria"""
"""See :meth:`.Stack.setRefineCriteria`"""
Stack.setRefineCriteria(self, domain = self.flame,
ratio = ratio, slope = slope, curve = curve,
prune = prune)
@ -89,9 +93,13 @@ class BurnerDiffFlame(Stack):
def set(self, tol = None, energy = '', tol_time = None):
"""Set parameters.
tol -- (rtol, atol) for steady-state
tol_time -- (rtol, atol) for time stepping
energy -- 'on' or 'off' to enable or disable the energy equation
:param tol:
(rtol, atol) for steady-state
:param tol_time:
(rtol, atol) for time stepping
:param energy:
``'on'`` or ``'off'`` to enable or disable the energy equation
"""
if tol:
self.flame.setTolerances(default = tol)
@ -120,7 +128,7 @@ class BurnerDiffFlame(Stack):
def setGasState(self, j):
"""Set the state of the object representing the gas to the
current solution at grid point j."""
current solution at grid point *j*."""
nsp = self.gas.nSpecies()
y = zeros(nsp, 'd')
for n in range(nsp):

View file

@ -6,17 +6,21 @@ class BurnerFlame(Stack):
def __init__(self, gas = None, burner = None, outlet = None, grid = None):
"""
gas -- object to use to evaluate all gas properties and reaction
rates. Required
burner -- Inlet object representing the burner. Optional;
if not supplied, one will be created with name 'burner'
outlet -- Outlet object representing the outlet. Optional;
if not supplied, one will be created with name 'outlet'
grid -- array of initial grid points
:param gas:
object to use to evaluate all gas properties and reaction
rates. Required
:param burner:
Inlet object representing the burner. Optional;
if not supplied, one will be created with name ``burner``
:param outlet:
Outlet object representing the outlet. Optional;
if not supplied, one will be created with name ``outlet``
:param grid:
array of initial grid points
A domain of type AxisymmetricFlow named 'flame' will be created to
represent the flame. The three domains comprising the stack
are stored as self.burner, self.flame, and self.outlet.
A domain of type :class:`.AxisymmetricFlow` named ``flame`` will be
created to represent the flame. The three domains comprising the stack
are stored as ``self.burner``, ``self.flame``, and ``self.outlet``.
"""
if burner:
@ -70,14 +74,14 @@ class BurnerFlame(Stack):
def solve(self, loglevel = 1, refine_grid = 1):
"""Solve the flame. See Stack.solve"""
"""Solve the flame. See :meth:`.Stack.solve`"""
if not self._initialized: self.init()
Stack.solve(self, loglevel = loglevel, refine_grid = refine_grid)
def setRefineCriteria(self, ratio = 10.0, slope = 0.8,
curve = 0.8, prune = 0.0):
"""See Stack.setRefineCriteria"""
"""See :meth:`.Stack.setRefineCriteria`"""
Stack.setRefineCriteria(self, domain = self.flame,
ratio = ratio, slope = slope, curve = curve,
prune = prune)
@ -89,9 +93,13 @@ class BurnerFlame(Stack):
def set(self, tol = None, energy = '', tol_time = None):
"""Set parameters.
tol -- (rtol, atol) for steady-state
tol_time -- (rtol, atol) for time stepping
energy -- 'on' or 'off' to enable or disable the energy equation
:param tol:
(rtol, atol) for steady-state
:param tol_time:
(rtol, atol) for time stepping
:param energy:
``'on'`` or ``'off'`` to enable or disable the energy equation
"""
if tol:
self.flame.setTolerances(default = tol)
@ -120,7 +128,7 @@ class BurnerFlame(Stack):
def setGasState(self, j):
"""Set the state of the object representing the gas to the
current solution at grid point j."""
current solution at grid point *j*."""
nsp = self.gas.nSpecies()
y = zeros(nsp, 'd')
for n in range(nsp):

View file

@ -33,11 +33,12 @@ class CounterFlame(Stack):
"""A non-premixed counterflow flame."""
def __init__(self, gas = None, grid = None):
"""The domains are [
self.fuel_inlet -- class Inlet,
self.flame -- class AxisymmetricFlow,
self.oxidizer_inlet -- class Inlet
]
"""
The domains are::
[self.fuel_inlet, # class Inlet,
self.flame, # class AxisymmetricFlow,
self.oxidizer_inlet] # class Inlet
"""
self.fuel_inlet = Inlet('fuel inlet')
@ -58,7 +59,7 @@ class CounterFlame(Stack):
"""Set the initial guess for the solution. The fuel species
must be specified, and the oxidizer may be
>>> f.init(fuel = 'CH4')
>>> f.init(fuel='CH4')
The initial guess is generated by assuming infinitely-fast
chemistry."""
@ -153,10 +154,13 @@ class CounterFlame(Stack):
def solve(self, loglevel = 1, refine_grid = 1):
"""Solve the flame.
loglevel -- integer flag controlling the amount of
diagnostic output. Zero suppresses all output, and
5 produces very verbose output. Default: 1
refine_grid -- if non-zero, enable grid refinement."""
:param loglevel:
integer flag controlling the amount of diagnostic output. Zero
suppresses all output, and 5 produces very verbose output. Default: 1
:param refine_grid:
if non-zero, enable grid refinement.
"""
if not self._initialized: self.init()
Stack.solve(self, loglevel = loglevel, refine_grid = refine_grid)
@ -164,21 +168,25 @@ class CounterFlame(Stack):
def setRefineCriteria(self, ratio = 10.0, slope = 0.8, curve = 0.8,
prune = 0.0):
"""Set the criteria used to refine the flame.
ratio -- additional points will be added if the ratio of the spacing
on either side of a grid point exceeds this value
slope -- maximum difference in value between two adjacent points,
scaled by the maximum difference in the profile
(0.0 < slope < 1.0). Adds points in regions of high slope.
curve -- maximum difference in slope between two adjacent intervals,
scaled by the maximum difference in the profile
(0.0 < curve < 1.0). Adds points in regions of high
curvature.
prune -- if the slope or curve criteria are satisfied to the level of
'prune', the grid point is assumed not to be needed and is
removed. Set prune significantly smaller than
'slope' and 'curve'. Set to zero to disable pruning
the grid.
"""
Set the criteria used to refine the flame.
:param ratio:
additional points will be added if the ratio of the spacing
on either side of a grid point exceeds this value
:param slope:
maximum difference in value between two adjacent points,
scaled by the maximum difference in the profile
(0.0 < slope < 1.0). Adds points in regions of high slope.
:param curve:
maximum difference in slope between two adjacent intervals, scaled
by the maximum difference in the profile (0.0 < curve < 1.0). Adds
points in regions of high curvature.
:param prune:
if the slope or curve criteria are satisfied to the level of
'prune', the grid point is assumed not to be needed and is removed.
Set prune significantly smaller than 'slope' and 'curve'. Set to
zero to disable pruning the grid.
>>> f.setRefineCriteria(ratio = 5.0, slope = 0.2, curve = 0.3,
... prune = 0.03)
@ -194,9 +202,13 @@ class CounterFlame(Stack):
def set(self, tol = None, energy = '', tol_time = None):
"""Set parameters.
tol -- (rtol, atol) for steady-state
tol_time -- (rtol, atol) for time stepping
energy -- 'on' or 'off' to enable or disable the energy equation
:param tol:
(rtol, atol) for steady-state
:param tol_time:
(rtol, atol) for time stepping
:param energy:
'on' or 'off' to enable or disable the energy equation
"""
if tol:
self.flame.setTolerances(default = tol)

View file

@ -8,13 +8,15 @@ class FreeFlame(Stack):
def __init__(self, gas = None, grid = None, tfix = 500.0):
"""
gas -- object to use to evaluate all gas properties and reaction
rates. Required
grid -- array of initial grid points
:param gas:
object to use to evaluate all gas properties and reaction
rates. Required
:param grid:
array of initial grid points
A domain of type FreeFlame named 'flame' will be created to
represent the flame. The three domains comprising the stack
are stored as self.inlet, self.flame, and self.outlet.
are stored as ``self.inlet``, ``self.flame``, and ``self.outlet``.
"""
self.inlet = Inlet('burner')
@ -68,14 +70,14 @@ class FreeFlame(Stack):
def solve(self, loglevel = 1, refine_grid = 1):
"""Solve the flame. See Stack.solve"""
"""Solve the flame. See :meth:`.Stack.solve`"""
if not self._initialized: self.init()
Stack.solve(self, loglevel = loglevel, refine_grid = refine_grid)
def setRefineCriteria(self, ratio = 10.0, slope = 0.8,
curve = 0.8, prune = 0.0):
"""See Stack.setRefineCriteria"""
"""See :meth:`.Stack.setRefineCriteria`"""
Stack.setRefineCriteria(self, domain = self.flame,
ratio = ratio, slope = slope, curve = curve,
prune = prune)
@ -90,9 +92,12 @@ class FreeFlame(Stack):
def set(self, tol = None, energy = '', tol_time = None):
"""Set parameters.
tol -- (rtol, atol) for steady-state
tol_time -- (rtol, atol) for time stepping
energy -- 'on' or 'off' to enable or disable the energy equation
:param tol:
(rtol, atol) for steady-state
:param tol_time:
(rtol, atol) for time stepping
:param energy:
'on' or 'off' to enable or disable the energy equation
"""
if tol:
self.flame.setTolerances(default = tol)

View file

@ -6,17 +6,20 @@ class StagnationFlow(Stack):
def __init__(self, gas = None, surfchem = None, grid = None):
"""
gas -- object to use to evaluate all gas properties and reaction
rates. Required.
surfchem -- object used to evaluate surface reaction rates. If
omitted, surface will be treated as inert.
grid -- array of initial grid points
:param gas:
object to use to evaluate all gas properties and reaction
rates. Required.
:param surfchem:
object used to evaluate surface reaction rates. If omitted,
surface will be treated as inert.
:param grid:
array of initial grid points
A domain of type AxisymmetricFlow named 'flow' will be created to
represent the flow, and one of type Surface named 'surface' will
be created to represent the surface.
The three domains comprising the stack
are stored as self.inlet, self.flow, and self.surface.
A domain of type :class:`.AxisymmetricFlow` named ``flow`` will be
created to represent the flow, and one of type :class:`.Surface` named
``surface`` will be created to represent the surface. The three domains
comprising the stack are stored as ``self.inlet``, ``self.flow``,
and ``self.surface``.
"""
self.inlet = Inlet('inlet')
self.gas = gas
@ -74,10 +77,14 @@ class StagnationFlow(Stack):
def solve(self, loglevel = 1, refine_grid = 1):
"""Solve the flame.
loglevel -- integer flag controlling the amount of
diagnostic output. Zero suppresses all output, and
5 produces very verbose output. Default: 1
refine_grid -- if non-zero, enable grid refinement."""
:param loglevel:
integer flag controlling the amount of diagnostic output.
Zero suppresses all output, and 5 produces very verbose output.
Default: 1
:param refine_grid:
if non-zero, enable grid refinement.
"""
if not self._initialized: self.init()
Stack.solve(self, loglevel = loglevel, refine_grid = refine_grid)
@ -85,21 +92,25 @@ class StagnationFlow(Stack):
def setRefineCriteria(self, ratio = 10.0, slope = 0.8,
curve = 0.8, prune = 0.0):
"""Set the criteria used to refine the flame.
ratio -- additional points will be added if the ratio of the spacing
on either side of a grid point exceeds this value
slope -- maximum difference in value between two adjacent points,
scaled by the maximum difference in the profile
(0.0 < slope < 1.0). Adds points in regions of high slope.
curve -- maximum difference in slope between two adjacent intervals,
scaled by the maximum difference in the profile
(0.0 < curve < 1.0). Adds points in regions of high
curvature.
prune -- if the slope or curve criteria are satisfied to the level of
'prune', the grid point is assumed not to be needed and is
removed. Set prune significantly smaller than
'slope' and 'curve'. Set to zero to disable pruning
the grid.
"""
Set the criteria used to refine the flame.
:param ratio:
additional points will be added if the ratio of the spacing
on either side of a grid point exceeds this value
:param slope:
maximum difference in value between two adjacent points, scaled by
the maximum difference in the profile (0.0 < slope < 1.0). Adds
points in regions of high slope.
:param curve:
maximum difference in slope between two adjacent intervals, scaled
by the maximum difference in the profile (0.0 < curve < 1.0). Adds
points in regions of high curvature.
:param prune:
if the slope or curve criteria are satisfied to the level of
'prune', the grid point is assumed not to be needed and is removed.
Set prune significantly smaller than 'slope' and 'curve'. Set to
zero to disable pruning the grid.
>>> f.setRefineCriteria(ratio = 5.0, slope = 0.2, curve = 0.3,
... prune = 0.03)
@ -115,9 +126,13 @@ class StagnationFlow(Stack):
def set(self, tol = None, energy = '', tol_time = None):
"""Set parameters.
tol -- (rtol, atol) for steady-state
tol_time -- (rtol, atol) for time stepping
energy -- 'on' or 'off' to enable or disable the energy equation
:param tol:
(rtol, atol) for steady-state
:param tol_time:
(rtol, atol) for time stepping
:param energy:
'on' or 'off' to enable or disable the energy equation
"""
if tol:
self.flow.setTolerances(default = tol)
@ -140,7 +155,7 @@ class StagnationFlow(Stack):
def solution(self, component = '', point = -1):
"""The solution for one specified component. If a point number
is given, return the value of component 'component' at this
is given, return the value of component *component* at this
point. Otherwise, return the entire profile for this
component."""
if point >= 0: return self.value(self.flow, component, point)
@ -157,7 +172,7 @@ class StagnationFlow(Stack):
def setGasState(self, j):
"""Set the state of the object representing the gas to the
current solution at grid point j."""
current solution at grid point *j*."""
nsp = self.gas.nSpecies()
y = zeros(nsp, 'd')
for n in range(nsp):

View file

@ -54,13 +54,13 @@ class Domain1D:
The argument list should consist of keyword/value pairs, with
component names as keywords and (lower_bound, upper_bound)
tuples as the values. The keyword 'default' may be used to
tuples as the values. The keyword *default* may be used to
specify default bounds for all unspecified components. The
keyword 'Y' can be used to stand for all species mass
keyword *Y* can be used to stand for all species mass
fractions in flow domains.
>>> d.setBounds(default = (0, 1),
... Y = (-1.0e-5, 2.0))
>>> d.setBounds(default=(0, 1),
... Y=(-1.0e-5, 2.0))
"""
d = {}
@ -85,6 +85,7 @@ class Domain1D:
def bounds(self, component):
"""Return the (lower, upper) bounds for a solution component.
>>> d.bounds('T')
(200.0, 5000.0)
"""
@ -98,8 +99,7 @@ class Domain1D:
"""Return the (relative, absolute) error tolerances for
a solution component.
(r, a) = d.tolerances('u')
>>> (r, a) = d.tolerances('u')
"""
ic = self.componentIndex(component)
r = _cantera.domain_rtol(self._hndl, ic)
@ -107,20 +107,20 @@ class Domain1D:
return (r, a)
def setTolerances(self, **tol):
"""Set the error tolerances. If 'time' is present and
"""Set the error tolerances. If *time* is present and
non-zero, then the values entered will apply to the transient
problem. Otherwise, they will apply to the steady-state
problem.
The argument list should consist of keyword/value pairs, with
component names as keywords and (rtol, atol) tuples as the
values. The keyword 'default' may be used to specify default
bounds for all unspecified components. The keyword 'Y' can be
values. The keyword *default* may be used to specify default
bounds for all unspecified components. The keyword *Y* can be
used to stand for all species mass fractions in flow domains.
d.setTolerances(Y = (1.0e-5, 1.0e-9),
default = (1.0e-7, 1.0e-12),
time = 1)
>>> d.setTolerances(Y=(1.0e-5, 1.0e-9),
... default=(1.0e-7, 1.0e-12),
... time=1)
"""
d = {}
@ -151,7 +151,7 @@ class Domain1D:
def setupGrid(self, grid):
"""Specify the grid.
d.setupGrid([0.0, 0.1, 0.2])
>>> d.setupGrid([0.0, 0.1, 0.2])
"""
return _cantera.domain_setupGrid(self._hndl, asarray(grid))
@ -164,12 +164,12 @@ class Domain1D:
return _cantera.domain_setDesc(self._hndl, desc)
def grid(self, n = -1):
""" If n >= 0, return the value of the nth grid point
""" If *n* >= 0, return the value of the nth grid point
from the left in this domain. If n is not supplied, return
the entire grid.
z4 = d.grid(4)
z_array = d.grid()
>>> z4 = d.grid(4)
>>> z_array = d.grid()
"""
if n >= 0:
@ -187,7 +187,7 @@ class Domain1D:
grid, name, desc
d.set(name = 'flame', grid = z)
>>> d.set(name='flame', grid=z)
"""
self._set(options)
@ -267,7 +267,6 @@ class Bdry1D(Domain1D):
mdot or massflux
temperature or T
mole_fractions or X
"""
for opt in options.keys():
v = options[opt]
@ -354,11 +353,17 @@ class AxisymmetricFlow(Domain1D):
In an axisymmetric flow domain, the equations solved are the
similarity equations for the flow in a finite-height gap of
infinite radial extent. The solution variables are
u -- axial velocity
V -- radial velocity divided by radius
T -- temperature
lambda -- (1/r)(dP/dr)
Y_k -- species mass fractions
*u*
axial velocity
*V*
radial velocity divided by radius
*T*
temperature
*lambda*
(1/r)(dP/dr)
*Y_k*
species mass fractions
It may be shown that if the boundary conditions on these variables
are independent of radius, then a similarity solution to the exact
@ -409,12 +414,13 @@ class AxisymmetricFlow(Domain1D):
"""Set the fixed temperature profile. This profile is used
whenever the energy equation is disabled.
pos - arrray of relative positions from 0 to 1
temp - array of temperature values
:param pos:
arrray of relative positions from 0 to 1
:param temp:
array of temperature values
>>> d.setFixedTempProfile(array([0.0, 0.5, 1.0]),
... array([500.0, 1500.0, 2000.0])
"""
return _cantera.stflow_setFixedTempProfile(self._hndl, pos, temp)
@ -432,7 +438,7 @@ class AxisymmetricFlow(Domain1D):
with no arguments or with a non-zero argument, the energy
equations will be solved. If invoked with a zero argument,
it will not be, and instead the temperature profiles will be
held to the one specified by the call to setFixedTempProfile.
held to the one specified by the call to :meth:`.setFixedTempProfile`.
Default: energy equation enabled."""
return _cantera.stflow_solveEnergyEqn(self._hndl, _onoff[flag])
@ -441,8 +447,7 @@ class AxisymmetricFlow(Domain1D):
In addition to the parameters that may be set by Domain1D.set,
this method can be used to set the pressure and energy flag
>>> d.set(pressure = OneAtm, energy = 'on')
>>> d.set(pressure=OneAtm, energy='on')
"""
for o in opt.keys():
v = opt[o]
@ -456,7 +461,6 @@ class AxisymmetricFlow(Domain1D):
class Stack:
""" Class Stack is a container for one-dimensional domains. It
also holds the multi-domain solution vector, and controls the
process of finding the solution.
@ -480,32 +484,36 @@ class Stack:
def setValue(self, dom, comp, localPoint, value):
"""Set the value of one component in one domain at one point
to 'value'.
dom -- domain object
comp -- component number
localPoint -- grid point number within domain 'dom', starting with
zero on the left
value -- numerical value
:param dom:
domain object
:param comp:
component number
:param localPoint:
grid point number within domain *dom* starting with zero on the left
:param value:
numerical value
>>> s.set(d, 3, 5, 6.7)
"""
idom = dom.domain_hndl()
_cantera.sim1D_setValue(self._hndl, idom,
comp, localPoint, value)
def setProfile(self, dom, comp, pos, v):
"""Set an initial estimate for a profile of one component in
one domain.
dom -- domain object
comp -- component name
pos -- sequence of relative positions, from 0 on the
left to 1 on the right
v -- sequence of values at the relative positions specified in 'pos'
:param dom:
domain object
:param comp:
component name
:param pos:
sequence of relative positions, from 0 on the left to 1 on the right
:param v:
sequence of values at the relative positions specified in 'pos'
>>> s.setProfile(d, 'T', [0.0, 0.2, 1.0], [400.0, 800.0, 1500.0])
"""
idom = dom.index()
@ -515,12 +523,15 @@ class Stack:
def setFlatProfile(self, dom, comp, v):
"""Set a flat profile for one component in one domain.
dom -- domain object
comp -- component name
v -- value
:param dom:
domain object
:param comp:
component name
:param v:
value
>>> s.setFlatProfile(d, 'u', -3.0)
"""
idom = dom.index()
icomp = dom.componentIndex(comp)
@ -533,18 +544,18 @@ class Stack:
>>> s.showSolution()
>>> s.showSolution('soln.txt')
"""
_cantera.sim1D_showSolution(self._hndl, fname)
def setTimeStep(self, stepsize, nsteps):
"""Set the sequence of time steps to try when Newton fails.
stepsize -- initial time step size [s]
nsteps - sequence of integer step numbers
:param stepsize:
initial time step size [s]
:param nsteps:
sequence of integer step numbers
>>> s.setTimeStep(1.0e-5, [1, 2, 5, 10])
"""
# 3/20/09
# The use of asarray seems to set the nsteps array to be of
@ -559,10 +570,12 @@ class Stack:
def solve(self, loglevel=1, refine_grid=1):
"""Solve the problem.
loglevel -- integer flag controlling the amount of
diagnostic output. Zero suppresses all output, and
5 produces very verbose output. Default: 1
refine_grid -- if non-zero, enable grid refinement."""
:param loglevel:
integer flag controlling the amount of diagnostic output. Zero
suppresses all output, and 5 produces very verbose output. Default: 1
:param refine_grid:
if non-zero, enable grid refinement."""
return _cantera.sim1D_solve(self._hndl, loglevel, refine_grid)
@ -574,33 +587,38 @@ class Stack:
def setRefineCriteria(self, domain = None, ratio = 10.0, slope = 0.8,
curve = 0.8, prune = 0.05):
"""Set the criteria used to refine one domain.
domain -- domain object
ratio -- additional points will be added if the ratio of the spacing
on either side of a grid point exceeds this value
slope -- maximum difference in value between two adjacent points,
scaled by the maximum difference in the profile
(0.0 < slope < 1.0). Adds points in regions of high slope.
curve -- maximum difference in slope between two adjacent intervals,
scaled by the maximum difference in the profile
(0.0 < curve < 1.0). Adds points in regions of high
curvature.
prune -- if the slope or curve criteria are satisfied to the level of
'prune', the grid point is assumed not to be needed and is
removed. Set prune significantly smaller than
'slope' and 'curve'. Set to zero to disable pruning
the grid.
>>> s.setRefineCriteria(d, ratio = 5.0, slope = 0.2, curve = 0.3,
... prune = 0.03)
:param domain:
domain object
:param ratio:
additional points will be added if the ratio of the spacing
on either side of a grid point exceeds this value
:param slope:
maximum difference in value between two adjacent points, scaled by
the maximum difference in the profile (0.0 < slope < 1.0). Adds
points in regions of high slope.
:param curve:
maximum difference in slope between two adjacent intervals, scaled
by the maximum difference in the profile (0.0 < curve < 1.0). Adds
points in regions of high curvature.
:param prune:
if the slope or curve criteria are satisfied to the level of
'prune', the grid point is assumed not to be needed and is removed.
Set prune significantly smaller than 'slope' and 'curve'. Set to
zero to disable pruning the grid.
>>> s.setRefineCriteria(d, ratio=5.0, slope=0.2, curve=0.3,
... prune=0.03)
"""
idom = domain.index()
return _cantera.sim1D_setRefineCriteria(self._hndl,
idom, ratio, slope, curve, prune)
def save(self, file = 'soln.xml', id = 'solution', desc = 'none'):
"""Save the solution in XML format.
>>> s.save(file = 'save.xml', id = 'energy_off',
... desc = 'solution with energy eqn. disabled')
>>> s.save(file='save.xml', id='energy_off',
... desc='solution with energy eqn. disabled')
"""
return _cantera.sim1D_save(self._hndl, file, id, desc)
@ -608,8 +626,10 @@ class Stack:
def restore(self, file = 'soln.xml', id = 'solution'):
"""Set the solution vector to a previously-saved solution.
file -- solution file
id -- solution name within the file
:param file:
solution file
:param id:
solution name within the file
>>> s.restore(file = 'save.xml', id = 'energy_off')
"""
@ -630,13 +650,15 @@ class Stack:
def value(self, domain, component, localPoint):
"""Solution value at one point.
domain -- domain object
component -- component name
localPoint -- grid point number in the domain, starting with
zero at the left
:param domain:
domain object
:param component:
component name
:param localPoint:
grid point number in the domain, starting with zero at the left
>>> t = s.value(flow, 'T', 6)
"""
icomp = domain.componentIndex(component)
idom = domain.index()
@ -644,6 +666,7 @@ class Stack:
def profile(self, domain, component):
"""Spatial profile of one component in one domain.
>>> print s.profile(flow, 'T')
"""
np = domain.nPoints()
@ -655,13 +678,15 @@ class Stack:
def workValue(self, dom, icomp, localPoint):
"""Internal work array value at one point. After calling eval,
this array contains the values of the residual function.
domain -- domain object
component -- component name
localPoint -- grid point number in the domain, starting with
zero at the left
:param domain:
domain object
:param component:
component name
:param localPoint:
grid point number in the domain, starting with zero at the left
>>> t = s.value(flow, 'T', 6)
"""
idom = dom.index()
return _cantera.sim1D_workValue(self._hndl, idom, icomp, localPoint)
@ -674,8 +699,11 @@ class Stack:
def setMaxJacAge(self, ss_age, ts_age):
"""Set the maximum number of times the Jacobian will be used
before it must be re-evaluated.
ss_age -- age criterion during steady-state mode
ts_age -- age criterion during time-stepping mode
:param ss_age:
age criterion during steady-state mode
:param ts_age:
age criterion during time-stepping mode
"""
return _cantera.sim1D_setMaxJacAge(self._hndl, ss_age, ts_age)
@ -683,7 +711,7 @@ class Stack:
"""Set the factor by which the time step will be increased
after a successful step, or decreased after an unsuccessful one.
s.timeStepFactor(3.0)
>>> s.timeStepFactor(3.0)
"""
return _cantera.sim1D_timeStepFactor(self._hndl, tfactor)

View file

@ -72,10 +72,11 @@ class Phase:
return _cantera.phase_nspecies(self._phase_id)
def nAtoms(self, species = None, element = None):
"""Number of atoms of element 'element' in species 'species'.
"""Number of atoms of element *element* in species *species*.
The element and species may be specified by name or by number.
>>> ph.nAtoms('CH4','H')
___ 4
4
"""
try:
@ -122,9 +123,9 @@ class Phase:
def moleFractions(self, species = None):
"""Species mole fraction array.
If optional argument 'species'
is supplied, then only the values for the selected species are
returned.
If optional argument *species* is supplied, then only the values
for the selected species are returned.
>>> x1 = ph.moleFractions() # all species
>>> x2 = ph.moleFractions(['OH', 'CH3'. 'O2'])
"""
@ -132,8 +133,8 @@ class Phase:
return self.selectSpecies(x, species)
def moleFraction(self, species):
"""Mole fraction of a species, referenced by name or
index number.
"""Mole fraction of a species, referenced by name or index number.
>>> ph.moleFraction(4)
>>> ph.moleFraction('CH4')
"""
@ -143,9 +144,9 @@ class Phase:
def massFractions(self, species = None):
"""Species mass fraction array.
If optional argument 'species'
is supplied, then only the values for the selected species are
returned.
If optional argument *species* is supplied, then only the values for
the selected species are returned.
>>> y1 = ph.massFractions() # all species
>>> y2 = ph.massFractions(['OH', 'CH3'. 'O2'])
"""
@ -156,6 +157,7 @@ class Phase:
def massFraction(self, species):
"""Mass fraction of one species, referenced by name or
index number.
>>> ph.massFraction(4)
>>> ph.massFraction('CH4')
"""
@ -164,7 +166,7 @@ class Phase:
def elementName(self,m):
"""Name of the element with index number m."""
"""Name of the element with index number *m*."""
return _cantera.phase_getstring(self._phase_id,1,m)
def elementNames(self):
@ -173,7 +175,7 @@ class Phase:
return map(self.elementName,range(nel))
def elementIndex(self, element):
"""The index of element 'element', which may be specified as
"""The index of element *element*, which may be specified as
a string or an integer index. In the latter case, the index is
checked for validity and returned. If no such element is
present, an exception is thrown."""
@ -189,9 +191,8 @@ class Phase:
return m
def speciesName(self,k):
"""Name of the species with index k."""
"""Name of the species with index *k*."""
return _cantera.phase_getstring(self._phase_id,2,k)
@ -202,7 +203,7 @@ class Phase:
def speciesIndex(self, species):
"""The index of species 'species', which may be specified as
"""The index of species *species*, which may be specified as
a string or an integer index. In the latter case, the index is
checked for validity and returned. If no such species is
present, an exception is thrown."""
@ -238,16 +239,15 @@ class Phase:
def setMoleFractions(self, x, norm = 1):
"""Set the mole fractions.
x - string or array of mole fraction values
norm - If non-zero (default), array values will be
scaled to sum to 1.0.
:param x:
string or array of mole fraction values
:param norm:
If non-zero (default), array values will be scaled to sum to 1.0.
>>> ph.setMoleFractions('CO:1, H2:7, H2O:7.8')
>>> x = [1.0]*ph.nSpecies()
>>> ph.setMoleFractions(x)
>>> ph.setMoleFractions(x, norm = 0) # don't normalize values
"""
if type(x) == types.StringType:
_cantera.phase_setstring(self._phase_id,1,x)
@ -259,7 +259,7 @@ class Phase:
def setMassFractions(self, x, norm = 1):
"""Set the mass fractions.
See: setMoleFractions
See :meth:`~.Phase.setMoleFractions`
"""
if type(x) == types.StringType:
_cantera.phase_setstring(self._phase_id,2,x)
@ -282,6 +282,7 @@ class Phase:
def setState_TNX(self, t, n, x):
"""Set the temperature, molardensity, and mole fractions. The mole
fractions may be entered as a string or array,
>>> ph.setState_TNX(600.0, 2.0e-3, 'CH4:0.4, O2:0.6')
"""
@ -306,6 +307,7 @@ class Phase:
return an array of those values corresponding to species
listed in 'species'. This method is used internally to implement
species selection in methods like moleFractions, massFractions, etc.
>>> f = ph.chemPotentials()
>>> muo2, muh2 = ph.selectSpecies(f, ['O2', 'H2'])
"""
@ -321,9 +323,10 @@ class Phase:
return asarray(f)
def selectElements(self, f, elements):
"""Given an array 'f' of floating-point element properties,
"""Given an array *f* of floating-point element properties,
return a nummodule array of those values corresponding to elements
listed in 'elements'.
listed in *elements*.
>>> f = ph.elementPotentials()
>>> lam_o, lam_h = ph.selectElements(f, ['O', 'H'])
"""

View file

@ -28,9 +28,9 @@ class ReactorBase:
volume = 1.0, energy = 'on',
type = -1, verbose = 0):
"""
See class 'Reactor' for a description of the constructor parameters.
The 'type' parameter specifies whether a Reactor (type = 2) or
Reservoir (type = 1) will be created.
See :class:`.Reactor` for a description of the constructor parameters.
The *type* parameter specifies whether a :class:`.Reactor` (type = 2) or
:class:`.Reservoir` (type = 1) will be created.
"""
self.__reactor_id = _cantera.reactor_new(type)
self._type = type
@ -84,7 +84,7 @@ class ReactorBase:
def insert(self, contents):
"""
Insert 'contents' into the reactor. Sets the objects used to compute
Insert *contents* into the reactor. Sets the objects used to compute
thermodynamic properties and kinetic rates.
"""
# store a reference to contents so that it will live as long
@ -108,7 +108,7 @@ class ReactorBase:
def _setEnergy(self, eflag):
"""Turn the energy equation on or off. If the argument is the
string 'off' or the number 0, the energy equation is disabled,
string ``'off'`` or the number 0, the energy equation is disabled,
and the reactor temperature is held constant at its initial
value."""
ie = 1
@ -158,26 +158,27 @@ class ReactorBase:
def advance(self, time):
"""Deprecated.
Advance the state of the reactor in time from the current
time to time 'time'. Note: this method is deprecated. See
class ReactorNet."""
time to time *time*. Note: this method is deprecated. See
:class:`.ReactorNet`."""
raise "use method advance of class ReactorNet"
#return _cantera.reactor_advance(self.__reactor_id, time)
def step(self, time):
"""Deprecated.
Take one internal time step from the current time toward
time 'time'. Note: this method is deprecated. See class
ReactorNet."""
time *time*. Note: this method is deprecated. See class
:class:`.ReactorNet`."""
raise "use method step of class ReactorNet"
#return _cantera.reactor_step(self.__reactor_id, time)
def massFraction(self, s):
"""The mass fraction of species s, specified either by name or
"""The mass fraction of species *s*, specified either by name or
index number.
>>> y1 = r.massFraction(7)
___0.02
0.02
>>> y2 = r.massFraction('CH3O')
___0.02
0.02
"""
if type(s) == types.StringType:
kk = self._contents.speciesIndex(s)
@ -202,10 +203,11 @@ class ReactorBase:
def moleFraction(self, s):
"""The mole fraction of species s, specified either by name or
index number.
>>> x1 = r.moleFraction(9)
___0.00012
0.00012
>>> x2 = r.moleFraction('CH3')
___0.00012
0.00012
"""
if type(s) == types.StringType:
kk = self._contents.speciesIndex(s)
@ -218,45 +220,53 @@ class ReactorBase:
"""Return the list of flow devices installed on inlets to this reactor.
This method can be used to access information about the flows entering
the reactor:
>>> for n in r.inlets():
... print n.name(), n.massFlowRate()
See: MassFlowController, Valve, PressureController.
See: :class:`.MassFlowController`, :class:`.Valve`,
:class:`.PressureController`.
"""
return self._inlets
def outlets(self):
"""Return the list of flow devices installed on outlets
on this reactor.
>>> for o in r.outlets():
... print o.name(), o.massFlowRate()
See: MassFlowController, Valve, PressureController.
See: :class:`.MassFlowController`, :class:`.Valve`,
:class:`.PressureController`.
"""
return self._outlets
def walls(self):
"""Return the list of walls installed on this reactor.
>>> for w in r.walls():
... print w.name()
See: Wall.
See: :class:`.Wall`.
"""
return self._walls
def _addInlet(self, inlet, other):
"""For internal use. Store a reference to 'inlet'
"""For internal use. Store a reference to *inlet*
so that it will not be deleted before this object."""
self._inlets.append(inlet)
if self._type == 2 and other._type == 1:
self._reservoirs.append(other)
def _addOutlet(self, outlet, other):
"""For internal use. Store a reference to 'outlet'
"""For internal use. Store a reference to *outlet*
so that it will not be deleted before this object."""
self._outlets.append(outlet)
if self._type == 2 and other._type == 1:
self._reservoirs.append(other)
def _addWall(self, wall, other):
"""For internal use. Store a reference to 'wall'
"""For internal use. Store a reference to *wall*
so that it will not be deleted before this object."""
self._walls.append(wall)
if self._type == 2 and other._type == 1:
@ -265,12 +275,14 @@ class ReactorBase:
def syncContents(self):
"""Set the state of the object representing the reactor contents
to the current reactor state.
>>> r = Reactor(gas)
>>> (statements that change the state of object 'gas')
>>> r.syncContents()
After this statement, the state of object 'gas' is synchronized
with the reactor state.
See 'contents'.
See :meth:`.contents`.
"""
self._contents.setState_TRY(self.temperature(),
self.density(),
@ -280,19 +292,21 @@ class ReactorBase:
"""Return an object representing the reactor contents, after first
synchronizing its state with the current reactor state. This method
is useful when some property of the fluid in the reactor is
needed that is not provided by a method of class Reactor.
needed that is not provided by a method of :class:`.Reactor`.
>>> r = Reactor(gas)
>>> (statements that change the state of object 'gas')
>>> c = r.contents()
>>> print c.gibbs_mole(), c.chemPotentials()
Note that after calling method 'contents', object 'c'
references the same underlying kernel object as object 'gas'
does. Therefore, all properties of 'c' and 'gas' are
Note that after calling :meth:`.contents`, object *c*
references the same underlying kernel object as object *gas*
does. Therefore, all properties of *c* and *gas* are
identical. (Remember that Python objects are really C
pointers; at the C level, both point to the same data
structure.)
It is also allowed to write
>>> gas = r.contents()
"""
self.syncContents()
@ -328,44 +342,51 @@ _reservoircount = 0
class Reactor(ReactorBase):
"""
Zero-dimensional reactors. Instances of class Reactor represent
zero-dimensional reactors. By default, they are closed (no inlets
or outlets), have fixed volume, and have adiabatic, chemically-intert
walls. These properties may all be changed by adding appropriate
components.
See classes 'Wall', 'MassFlowController', and 'Valve'.
zero-dimensional reactors. By default, they are closed (no inlets or
outlets), have fixed volume, and have adiabatic, chemically-inert walls.
These properties may all be changed by adding appropriate components.
See :class:`.Wall`, :class:`.MassFlowController`, and :class:`.Valve`.
"""
def __init__(self, contents = None, name = '',
volume = 1.0, energy = 'on',
verbose = 0):
"""
contents - Reactor contents. If not specified, the reactor is
initially empty. In this case, call method 'insert' to specify
the contents.
:param contents:
Reactor contents. If not specified, the reactor is initially empty.
In this case, call :meth:`.insert` to specify the contents.
:param name:
Used only to identify this reactor in output. If not specified,
defaults to ``'Reactor_n'``, where *n* is an integer assigned in
the order :class:`.Reactor` objects are created.
:param volume:
Initial reactor volume. Defaults to 1 m^3.
:param energy:
Set to ``'on'`` or ``'off'``. If set to ``'off'``, the energy
equation is not solved, and the temperature is held at its
initial value. The default in ``'on'``.
:param verbose:
If set to a non-zero value, additional diagnostic information
will be printed.
name - Used only to identify this reactor in output. If not
specified, defaults to 'Reactor_n', where n is an integer
assigned in the order Reactor objects are created.
Some examples showing how to create :class:`Reactor` objects are
shown below.
volume - Initial reactor volume. Defaults to 1 m^3.
energy - Set to 'on' or 'off'. If set to 'off', the energy
equation is not solved, and the temperature is held at its
initial value. The default in 'on'.
verbose - if set to a non-zero value, additional diagnostic
information will be printed.
Some examples showing how to create Reactor objects are shown below.
>>> gas = GRI30()
>>> r1 = Reactor(gas)
This is equivalent to:
>>> r1 = Reactor()
>>> r1.insert(gas)
Arguments may be specified using keywords in any order:
>>> r2 = Reactor(contents = gas, energy = 'off',
... name = 'isothermal_reactor')
>>> r3 = Reactor(contents = gas, name = 'adiabatic_reactor')
Here's an array of reactors:
>>> reactor_array = [Reactor(), Reactor(gas), Reactor(Air())]
"""
global _reactorcount
@ -377,31 +398,28 @@ class Reactor(ReactorBase):
verbose = verbose, type = 2)
class FlowReactor(ReactorBase):
"""
"""
def __init__(self, contents = None, name = '',
volume = 1.0, energy = 'on',
mdot = -1.0,
verbose = 0):
"""
contents - Reactor contents. If not specified, the reactor is
initially empty. In this case, call method 'insert' to specify
the contents.
name - Used only to identify this reactor in output. If not
specified, defaults to 'Reactor_n', where n is an integer
assigned in the order Reactor objects are created.
volume - Initial reactor volume. Defaults to 1 m^3.
energy - Set to 'on' or 'off'. If set to 'off', the energy
equation is not solved, and the temperature is held at its
initial value. The default in 'on'.
verbose - if set to a non-zero value, additional diagnostic
information will be printed.
:param contents:
Reactor contents. If not specified, the reactor is initially empty.
In this case, call :meth:`.insert` to specify the contents.
:param name:
Used only to identify this reactor in output. If not specified,
defaults to ``Reactor_n``, where n is an integer assigned in the
order Reactor objects are created.
:param volume:
Initial reactor volume. Defaults to 1 m^3.
:param energy:
Set to ``'on'`` or ``'off'``. If set to ``'off'``, the energy
equation is not solved, and the temperature is held at its
initial value. The default in ``'on'``.
:param verbose:
if set to a non-zero value, additional diagnostic information
will be printed.
"""
global _reactorcount
if name == '':
@ -418,28 +436,27 @@ class FlowReactor(ReactorBase):
class ConstPressureReactor(ReactorBase):
"""
"""
def __init__(self, contents = None, name = '',
volume = 1.0, energy = 'on',
verbose = 0):
"""
contents - Reactor contents. If not specified, the reactor is
initially empty. In this case, call method 'insert' to specify
the contents.
name - Used only to identify this reactor in output. If not
specified, defaults to 'Reactor_n', where n is an integer
assigned in the order Reactor objects are created.
volume - Initial reactor volume. Defaults to 1 m^3.
energy - Set to 'on' or 'off'. If set to 'off', the energy
equation is not solved, and the temperature is held at its
initial value. The default in 'on'.
verbose - if set to a non-zero value, additional diagnostic
information will be printed.
:param contents:
Reactor contents. If not specified, the reactor is
initially empty. In this case, call :meth:`.insert` to specify
the contents.
:param name:
Used only to identify this reactor in output. If not specified,
defaults to ``'Reactor_n'``, where n is an integer assigned in the
order :class:`.Reactor` objects are created.
:param volume:
Initial reactor volume. Defaults to 1 m^3.
:param energy:
Set to ``'on'`` or ``'off'``. If set to ``'off'``, the energy
equation is not solved, and the temperature is held at its
initial value. The default in ``'on'``.
:param verbose:
If set to a non-zero value, additional diagnostic
information will be printed.
"""
global _reactorcount
if name == '':
@ -458,27 +475,31 @@ class Reservoir(ReactorBase):
"""
def __init__(self, contents = None, name = '', verbose = 0):
"""
contents - Reservoir contents. If not specified, the reservoir is
initially empty. In this case, call method insert to specify
the contents.
name - Used only to identify this reservoir in output. If not
specified, defaults to 'Reservoir_n', where n is an integer
assigned in the order Reservoir objects are created.
verbose - if set to a non-zero value, additional diagnostic
information will be printed.
:param contents:
Reservoir contents. If not specified, the reservoir is initially
empty. In this case, call :meth:`.insert` to specify the contents.
:param name:
Used only to identify this reservoir in output. If not specified,
defaults to ``'Reservoir_n'``, where n is an integer assigned in
the order Reservoir objects are created.
:param verbose:
if set to a non-zero value, additional diagnostic information will
be printed.
Some examples showing how to create Reservoir objects are shown below.
>>> gas = GRI30()
>>> res1 = Reservoir(gas)
This is equivalent to:
>>> res1 = Reactor()
>>> res1.insert(gas)
Arguments may be specified using keywords in any order:
>>> res2 = Reservoir(contents = Air(),
... name = 'environment')
>>> res3 = Reservoir(contents = gas, name = 'upstream_state')
>>> res2 = Reservoir(contents=Air(), name='environment')
>>> res3 = Reservoir(contents=gas, name='upstream_state')
"""
global _reservoircount
if name == '':
@ -492,8 +513,6 @@ class Reservoir(ReactorBase):
pass
#------------------ FlowDevice ---------------------------------
class FlowDevice:
@ -502,7 +521,7 @@ class FlowDevice:
"""
def __init__(self, type, name, verbose):
"""
Create a new instance of type 'type'
Create a new instance of type *type*
"""
self._name = name
self._verbose = verbose
@ -534,7 +553,8 @@ class FlowDevice:
"""
Install the device between the upstream and downstream
reactors or reservoirs.
>>> f.install(upstream = reactor1, downstream = reservoir2)
>>> f.install(upstream=reactor1, downstream=reservoir2)
"""
if self._verbose:
print
@ -557,64 +577,62 @@ class FlowDevice:
_mfccount = 0
class MassFlowController(FlowDevice):
r"""
Mass flow controllers. A mass flow controller maintains a specified mass
flow rate independent of upstream and downstream conditions. The equation
used to compute the mass flow rate is
"""Mass flow controllers. A mass flow controller maintains a
specified mass flow rate independent of upstream and downstream
conditions. The equation used to compute the mass flow rate is
\f[
\dot m = \max(\dot m_0, 0.0),
\f] where \f$ \dot m_0 \f$ is either
a constant value or a function of time. Note that if \f$\dot m_0 <
0\f$, the mass flow rate will be set to zero, since reversal of
the flow direction is not allowed.
.. math::
Unlike a real mass flow controller, a MassFlowController object
will maintain the flow even if the downstream pressure is greater
than the upstream pressure. This allows simple implementation of
loops, in which exhaust gas from a reactor is fed back into it
through an inlet. But note that this capability should be used
with caution, since no account is taken of the work required to do
this.
\dot m = \max(\dot m_0, 0.0),
A mass flow controller is assumed to be adiabatic, non-reactive,
and have negligible volume, so that it is internally always in
steady-state even if the upstream and downstream reactors are
not. The fluid enthalpy, chemical composition, and mass flow rate
are constant across a mass flow controller, and the pressure
difference equals the difference in pressure between the upstream
and downstream reactors.
where :math:`\dot m_0` is either a constant value or a function of time.
Note that if :math:`\dot m_0 < 0`, the mass flow rate will be set to zero,
since reversal of the flow direction is not allowed.
Unlike a real mass flow controller, a MassFlowController object will
maintain the flow even if the downstream pressure is greater than the
upstream pressure. This allows simple implementation of loops, in which
exhaust gas from a reactor is fed back into it through an inlet. But note
that this capability should be used with caution, since no account is
taken of the work required to do this.
A mass flow controller is assumed to be adiabatic, non-reactive, and have
negligible volume, so that it is internally always in steady-state even if
the upstream and downstream reactors are not. The fluid enthalpy, chemical
composition, and mass flow rate are constant across a mass flow controller,
and the pressure difference equals the difference in pressure between the
upstream and downstream reactors.
Examples:
>>> mfc1 = MassFlowController(upstream = res1, downstream = reactr,
... name = 'fuel_mfc', mdot = 0.1)
>>> air_mdot = Gaussian(A = 0.1, t0 = 2.0, FWHM = 0.1)
>>> mfc2 = MassFlowController(upstream = res2, downstream = reactr,
... name = 'air_mfc', mdot = air_mdot)
>>> mfc1 = MassFlowController(upstream=res1, downstream=reactr,
... name='fuel_mfc', mdot = 0.1)
>>> air_mdot = Gaussian(A=0.1, t0=2.0, FWHM=0.1)
>>> mfc2 = MassFlowController(upstream=res2, downstream=reactr,
... name='air_mfc', mdot=air_mdot)
"""
def __init__(self, upstream=None,
downstream=None,
name='',
verbose=0, mdot = 0.0):
"""
upstream - upstream reactor or reservoir.
downstream - downstream reactor or reservoir.
name - name used to identify the mass flow controller in output.
If no name is specified, it defaults to 'MFC_n', where n is an
integer assigned in the order the MassFlowController object
was created.
mdot - Mass flow rate [kg/s]. This mass flow rate, which may
be a constant of a function of time, will be maintained,
independent of unstream and downstream conditions, unless
reset by calling method 'set'.
verbose - if set to a positive integer, additional diagnostic
information will be printed.
:param upstream:
upstream reactor or reservoir.
:param downstream:
downstream reactor or reservoir.
:param name:
name used to identify the mass flow controller in output. If no
name is specified, it defaults to ``MFC_n``, where n is an integer
assigned in the order the MassFlowController object was created.
:param mdot:
Mass flow rate [kg/s]. This mass flow rate, which may be a constant
or a function of time, will be maintained, independent of upstream
and downstream conditions, unless reset by calling method
:meth:`.set`.
:param verbose:
if set to a positive integer, additional diagnostic information
will be printed.
"""
global _mfccount
if name == '':
@ -650,56 +668,51 @@ class MassFlowController(FlowDevice):
_valvecount = 0
class Valve(FlowDevice):
"""Valves. In Cantera, a Valve object is a flow devices with mass
r"""Valves. In Cantera, a Valve object is a flow devices with mass
flow rate that is a function of the pressure drop across it. The default behavior
is linear:
\f[ \dot m = K_v (P_1 - P_2) \f]
if \f$ P_1 > P_2. \f$
Otherwise,
\f$ \dot m = 0 \f$.
However, an arbitrary function \f$ F\f$ can also be specified, such that
\f[
\dot m = F(P_1 - P_2).
\f]
if \f$ P_1 > P_2, \f$
or \f$ \dot m = 0 \f$ otherwise.
It is never possible for the flow to reverse
and go from the downstream to the upstream reactor/reservoir through
a line containing a Valve object.
'Valve' objects are often used between an upstream reactor and a
downstream reactor or reservoir to maintain them both at nearly the
same pressure. By setting the constant \f$ K_v \f$ to a
sufficiently large value, very small pressure differences will
result in flow between the reactors that counteracts the pressure
difference.
.. math:: \dot m = K_v (P_1 - P_2)
A Valve is assumed to be adiabatic, non-reactive, and have
negligible internal volume, so that it is internally always in
steady-state even if the upstream and downstream reactors are
not. The fluid enthalpy, chemical composition, and mass flow rate
are constant across a Valve, and the pressure difference equals
the difference in pressure between the upstream and downstream
reactors.
if :math:`P_1 > P_2.` Otherwise, :math:`\dot m = 0`.
However, an arbitrary function can also be specified, such that
.. math:: \dot m = F(P_1 - P_2)
if :math:`P_1 > P_2`, or :math:`\dot m = 0` otherwise.
It is never possible for the flow to reverse and go from the downstream
to the upstream reactor/reservoir through a line containing a Valve object.
:class:`Valve` objects are often used between an upstream reactor and a
downstream reactor or reservoir to maintain them both at nearly the same
pressure. By setting the constant :math:`K_v` to a sufficiently large
value, very small pressure differences will result in flow between the
reactors that counteracts the pressure difference.
A Valve is assumed to be adiabatic, non-reactive, and have negligible
internal volume, so that it is internally always in steady-state even if
the upstream and downstream reactors are not. The fluid enthalpy, chemical
composition, and mass flow rate are constant across a Valve, and the
pressure difference equals the difference in pressure between the upstream
and downstream reactors.
"""
def __init__(self, upstream=None, downstream=None,
name='', Kv = 0.0, mdot0 = 0.0, verbose=0):
"""
upstream - upstream reactor or reservoir.
downstream - downstream reactor or reservoir.
name - name used to identify the valve in output.
If no name is specified, it defaults to 'Valve_n', where n is an
integer assigned in the order the Valve object
was created.
Kv - the constant in the mass flow rate equation.
verbose - if set to a positive integer, additional diagnostic
information will be printed.
:param upstream:
upstream reactor or reservoir.
:param downstream:
downstream reactor or reservoir.
:param name:
name used to identify the valve in output. If no name is specified,
it defaults to ``Valve_n``, where n is an integer assigned in the
order the Valve object was created.
:param Kv:
the constant in the mass flow rate equation.
:param verbose:
if set to a positive integer, additional diagnostic information
will be printed.
"""
global _valvecount
if name == '':
@ -712,7 +725,7 @@ class Valve(FlowDevice):
def setValveCoeff(self, Kv = -1.0):
"""Set or reset the valve coefficient \f$ K_v \f$."""
"""Set or reset the valve coefficient :math:`K_v`."""
vv = zeros(1,'d')
vv[0] = Kv
if self._verbose:
@ -729,11 +742,12 @@ class Valve(FlowDevice):
raise CanteraError("Wrong type for valve characteristic function.")
def set(self, Kv = -1.0, F = None):
"""Set or reset valve properties. All keywords are optional.
r"""Set or reset valve properties. All keywords are optional.
Kv - constant in linear mass flow rate equation.
F - function of \f$\Delta P\f$.
:param Kv:
constant in linear mass flow rate equation.
:param F:
function of :math:`\Delta P`.
"""
if F:
self.setFunction(F)
@ -745,36 +759,35 @@ class Valve(FlowDevice):
_pccount = 0
class PressureController(FlowDevice):
r"""
A PressureController is designed to be used in conjunction with another
'master' flow controller, typically a :class:`.MassFlowController`. The
master flow controller is installed on the inlet of the reactor, and the
corresponding :class:`.PressureController` is installed on on outlet of the
reactor. The :class:`.PressureController` mass flow rate is equal to the
master mass flow rate, plus a small correction dependent on the pressure
difference:
""" A PressureController is designed to be used in conjunction
with another 'master' flow controller, typically a
MassFlowController. The master flow controller is installed on the
inlet of the reactor, and the corresponding PressureController is
installed on on outlet of the reactor. The PressureController mass
flow rate is equal to the master mass flow rate, plus a
small correction dependent on the pressure difference:
\f[
\dot m = \dot m_{\rm master} + K_v(P_1 - P_2).
\f]
.. math:: \dot m = \dot m_{\rm master} + K_v(P_1 - P_2).
"""
def __init__(self, upstream=None, downstream=None,
name='', master = None, Kv = 0.0, verbose=0):
"""
upstream - upstream reactor or reservoir.
downstream - downstream reactor or reservoir.
name - name used to identify the pressure controller in
output. If no name is specified, it defaults to
'PressureController_n', where n is an integer assigned in the
order the PressureController object was created.
Kv - the constant in the mass flow rate equation.
verbose - if set to a positive integer, additional diagnostic
information will be printed.
:param upstream:
upstream reactor or reservoir.
:param downstream:
downstream reactor or reservoir.
:param name:
name used to identify the pressure controller in output. If no
name is specified, it defaults to ``PressureController_n``, where
n is an integer assigned in the order the PressureController
object was created.
:param Kv:
the constant in the mass flow rate equation.
:param verbose:
if set to a positive integer, additional diagnostic information
will be printed.
"""
global _pccount
if name == '':
@ -788,7 +801,7 @@ class PressureController(FlowDevice):
def setPressureCoeff(self, Kv):
"""Set or reset the pressure coefficient \f$ K_v \f$."""
"""Set or reset the pressure coefficient :math:`K_v`."""
vv = zeros(1,'d')
vv[0] = Kv
if self._verbose:
@ -814,44 +827,40 @@ class PressureController(FlowDevice):
_wallcount = 0
class Wall:
"""
r"""
Reactor walls.
A Wall separates two reactors, or a reactor and a reservoir. A
wall has a finite area, may conduct or radiate heat between the
two reactors on either side, and may move like a piston.
A Wall separates two reactors, or a reactor and a reservoir. A wall has a
finite area, may conduct or radiate heat between the two reactors on either
side, and may move like a piston.
Walls are stateless objects in Cantera, meaning that no
differential equation is integrated to determine any wall
property. Since it is the wall (piston) velocity that enters the
energy equation, this means that it is the velocity, not the
acceleration or displacement, that is specified. The wall
velocity is computed from
\f[
v = K(P_{\\rm left} - P_{\\rm right}) + v_0(t),
\f]
where $K$ is a non-negative constant, and \f$v_0(t)$ is a
Walls are stateless objects in Cantera, meaning that no differential
equation is integrated to determine any wall property. Since it is the wall
(piston) velocity that enters the energy equation, this means that it is
the velocity, not the acceleration or displacement, that is specified.
The wall velocity is computed from
.. math:: v = K(P_{\rm left} - P_{\rm right}) + v_0(t),
where :math:`K` is a non-negative constant, and :math:`v_0(t)` is a
specified function of time. The velocity is positive if the wall is
moving to the right.
The heat flux through the wall is computed from
\f[
q = U(T_{\\rm left} - T_{\\rm right}) + \epsilon\sigma (T_{\\rm left}^4
- T_{\\rm right}^4) + q_0(t),
\f]
where \f$ U \f$ is the overall heat transfer coefficient for
conduction/convection, and \f$ \\epsilon \f$ is the emissivity.
The function \f$ q_0(t)$ is a specified function of time.
The heat flux is positive when heat flows from the reactor on the left
to the reactor on the right.
A heterogeneous reaction mechanism may be specified for one or
both of the wall surfaces. The mechanism object (typically an
instance of class Interface) must be constructed so that it is
properly linked to the object representing the fluid in the
reactor the surface in question faces. The surface temperature on
each side is taken to be equal to the temperature of the reactor
it faces.
.. math:: q = U(T_{\rm left} - T_{\rm right}) + \epsilon\sigma (T_{\rm left}^4 - T_{\rm right}^4) + q_0(t),
where :math:`U` is the overall heat transfer coefficient for
conduction/convection, and :math:`\epsilon` is the emissivity. The function
:math:`q_0(t)` is a specified function of time. The heat flux is positive
when heat flows from the reactor on the left to the reactor on the right.
A heterogeneous reaction mechanism may be specified for one or both of the
wall surfaces. The mechanism object (typically an instance of class
:class:`.Interface`) must be constructed so that it is properly linked to
the object representing the fluid in the reactor the surface in question
faces. The surface temperature on each side is taken to be equal to the
temperature of the reactor it faces.
"""
def __init__(self, left, right, name = '',
@ -859,35 +868,32 @@ class Wall:
Q = None, velocity = None,
kinetics = [None, None]):
"""
Constructor arguments:
left - Reactor or reservoir on the left. Required.
right - Reactor or reservoir on the right. Required.
name - Name string.
If omitted, the name is 'Wall_n', where 'n' is an integer
assigned in the order walls are created.
A - Wall area [m^2]. Defaults to 1.0 m^2.
K - Wall expansion rate parameter [m/s/Pa]. Defaults to 0.0.
U - Overall heat transfer coefficient [W/m^2]. Defaults to 0.0
(adiabbatic wall).
Q - Heat flux function \f$ q_0(t) \f$ [W/m^2]. Optional. Default:
\f$ q_0(t) = 0.0 \f$.
velocity - Wall velocity function \f$ v_0(t) \f$ [m/s].
Default: \f$ v_0(t) = 0.0 \f$.
kinetics - Surface reaction mechanisms for the left-facing and
right-facing surface, respectively. These must be instances of
class Kinetics, or of a class derived from Kinetics, such as
Interface. If chemistry occurs on only one side, enter 'None'
for the non-reactive side.
:param left:
Reactor or reservoir on the left. Required.
:param right:
Reactor or reservoir on the right. Required.
:param name:
Name string. If omitted, the name is ``'Wall_n'``, where ``'n'``
is an integer assigned in the order walls are created.
:param A:
Wall area [m^2]. Defaults to 1.0 m^2.
:param K:
Wall expansion rate parameter [m/s/Pa]. Defaults to 0.0.
:param U:
Overall heat transfer coefficient [W/m^2]. Defaults to 0.0
(adiabbatic wall).
:param Q:
Heat flux function :math:`q_0(t)` [W/m^2]. Optional. Default:
:math:`q_0(t) = 0.0`.
:param velocity:
Wall velocity function :math:`v_0(t)` [m/s].
Default: :math:`v_0(t) = 0.0`.
:param kinetics:
Surface reaction mechanisms for the left-facing and right-facing
surface, respectively. These must be instances of class Kinetics,
or of a class derived from Kinetics, such as Interface. If
chemistry occurs on only one side, enter ``None`` for the
non-reactive side.
"""
typ = 0
self.__wall_id = _cantera.wall_new(typ)
@ -916,7 +922,7 @@ class Wall:
def __del__(self):
""" Delete the Wall instance. This method is called
automatically when no Python object stores a reference to this
Wall. Since reactors and reserviors store references to all
Wall. Since reactors and reservoirs store references to all
Walls installed on them, this method will only be called after
the reactors/reservoirs have been deleted. """
@ -936,7 +942,8 @@ class Wall:
def setArea(self, a):
"""
Set the area (m^2). The wall area may be changed manually at any time during a simulation.
Set the area (m^2). The wall area may be changed manually at any time
during a simulation.
"""
_cantera.wall_setArea(self.__wall_id, a)
@ -960,8 +967,7 @@ class Wall:
def setHeatFlux(self, qfunc):
"""
Specify the time-dependent heat flux function [W/m2].
'qfunc' must be a functor (an instance of a subclass of Cantera.Func1).
See: Func1.
*qfunc* must be a functor (an instance of :class:`.Func1`).
"""
n = 0
if qfunc: n = qfunc.func_id()
@ -974,9 +980,8 @@ class Wall:
def setVelocity(self, vfunc):
"""
Specify the velocity function [m/s]. 'vfunc' must
be a functor (an instance of a subclass of Cantera.Func1)
See: Func1.
Specify the velocity function [m/s]. *vfunc* must
be a functor (an instance of :class:`.Func1`)
"""
n = 0
if vfunc: n = vfunc.func_id()
@ -1027,7 +1032,7 @@ class Wall:
raise CanteraError("side must be 'left' or 'right'")
def set(self, **p):
"""Set various wall parameters: 'A', 'U', 'K', 'Q'. 'velocity'.
"""Set various wall parameters: *A*, *U*, *K*, *Q*, *velocity*.
These have the same meanings as in the constructor.
"""
for item in p.keys():
@ -1063,7 +1068,6 @@ class Wall:
class ReactorNet:
"""Networks of reactors. ReactorNet objects are used to
simultaneously advance the state of a set of coupled reactors.
@ -1075,10 +1079,7 @@ class ReactorNet:
>>> reactor_network = ReactorNet([r1, r2])
>>> reactor_network.advance(time)
"""
def __init__(self, reactorlist = None):
"""
Create a new ReactorNet instance. If a list of reactors is supplied,
@ -1134,7 +1135,7 @@ class ReactorNet:
return _cantera.reactornet_advance(self.__reactornet_id, time)
def step(self, time):
"""Take a single internal time step toward time 'time'.
"""Take a single internal time step toward time *time*.
The time after taking the step is returned."""
return _cantera.reactornet_step(self.__reactornet_id, time)
@ -1151,22 +1152,20 @@ class ReactorNet:
def sensitivity(self, component = '', parameter = -1, reactor = ''):
"""Sensitivity of solution component 'component' with respect
"""Sensitivity of solution component *component* with respect
to one or more parameters.
component -- name of the species or other variable for which
sensitivity information is desired.
parameter -- single integer or sequence of integers specifying
the parameters. The parameters are numbered from zero,
beginning with the parameters for the first reactor and
continuing through those for the last reactor in the
network. If omitted, the sensitivity with respect to all
parameters will be returned.
reactor -- reactor containing the desired component.
:param component:
name of the species or other variable for which sensitivity
information is desired.
:param parameter:
single integer or sequence of integers specifying the parameters.
The parameters are numbered from zero, beginning with the parameters
for the first reactor and continuing through those for the last
reactor in the network. If omitted, the sensitivity with respect
to all parameters will be returned.
:param reactor:
reactor containing the desired component.
"""
n = 0

View file

@ -19,7 +19,7 @@ class SurfacePhase(ThermoPhase):
return _cantera.surf_sitedensity(self._phase_id)
def setCoverages(self, theta):
"""Set the surface coverages to the values in array 'theta'."""
"""Set the surface coverages to the values in array *theta*."""
nt = len(theta)
if nt == self.nSpecies():
_cantera.surf_setcoverages(self._phase_id,
@ -34,7 +34,7 @@ class SurfacePhase(ThermoPhase):
def setConcentrations(self, conc):
"""Set the surface concentrations to the values in
array 'conc'."""
array *conc*."""
_cantera.surf_setconcentrations(self._phase_id, conc)
def concentrations(self):

View file

@ -18,9 +18,8 @@ class ThermoPhase(Phase):
providing methods that require knowledge of the equation of state.
Class ThermoPhase is not usually instantiated directly. It is used
as base class for classes Solution and Interface.
@see Solution, Interface
as base class for classes :class:`~Cantera.Solution` and
:class:`~Cantera.Interface.Interface`.
"""
# used in the 'equilibrate' method
@ -30,12 +29,13 @@ class ThermoPhase(Phase):
def __init__(self, xml_phase=None, index=-1):
"""
xml_phase - CTML node specifying the attributes of this phase
index - optional. If positive, create only a Python wrapper for
an existing kernel object, instead of creating a new kernel object.
The value of 'index' is the integer index number to reference the
existing kernel object.
:param xml_phase:
CTML node specifying the attributes of this phase
:param index:
optional. If positive, create only a Python wrapper for an existing
kernel object, instead of creating a new kernel object. The value
of *index* is the integer index number to reference the existing
kernel object.
"""
self._phase_id = 0
@ -43,8 +43,8 @@ class ThermoPhase(Phase):
self.idtag = ""
if index >= 0:
# create a Python wrapper for an existing kernel
# ThermoPhase instance
# create a Python wrapper for an existing kernel
# ThermoPhase instance
self._phase_id = index
elif xml_phase:
@ -280,36 +280,38 @@ class ThermoPhase(Phase):
def equilibrate(self, XY, solver = -1, rtol = 1.0e-9,
maxsteps = 1000, maxiter = 100, loglevel = 0):
""" Set to a state of chemical equilibrium holding property pair
'XY' constant.
"""
Set to a state of chemical equilibrium holding property pair
*XY* constant.
:param XY:
A two-letter string, which must be one of the set::
['TP','TV','HP','SP','SV','UV','PT','VT','PH','PS','VS','VU']
XY --- A two-letter string, which must be one of the set
['TP','TV','HP','SP','SV','UV','PT','VT','PH','PS','VS','VU'].
If H, U, S, or V is specified, the value must be the specific
value (per unit mass)
solver --- Specifies the equilibrium solver to use. If solver =
0, a fast solver using the element potential method will be
used. If solver > 0, a slower but more robust Gibbs
minimization solver will be used. If solver < 0 or
unspecified, the fast solver will be tried first, then if it
fails the other will be tried.
rtol -- the relative error tolerance.
maxsteps -- maximum number of steps in composition to take to
find a converged solution.
maxiter -- for the Gibbs minimization solver only, this
specifies the number of 'outer' iterations on T or P when some
property pair other than TP is specified.
loglevel -- set to a value > 0 to write diagnostic output to a
file in HTML format. Larger values generate more detailed
information. The file will be named 'equilibrate_log.html.'
Subsequent files will be named 'equillibrate_log1.html', etc.,
so that log files are not overwritten.
:param solver:
Specifies the equilibrium solver to use. If solver = 0, a fast
solver using the element potential method will be used. If
solver > 0, a slower but more robust Gibbs minimization solver
will be used. If solver < 0 or unspecified, the fast solver will
be tried first, then if it fails the other will be tried.
:param rtol:
the relative error tolerance.
:param maxsteps:
maximum number of steps in composition to take to find a converged
solution.
:param maxiter:
For the Gibbs minimization solver only, this specifies the number
of 'outer' iterations on T or P when some property pair other than
TP is specified.
:param loglevel:
Set to a value > 0 to write diagnostic output to a file in HTML
format. Larger values generate more detailed information. The file
will be named ``equilibrate_log.html.`` Subsequent files will be
named ``equilibrate_log1.html``, etc., so that log files are
not overwritten.
"""
_cantera.thermo_equil(self._phase_id, XY, solver,
rtol, maxsteps, maxiter, loglevel)

View file

@ -23,7 +23,6 @@ from Cantera.num import asarray
import exceptions
class Transport:
"""Transport properties.
This class provides the Python interface to the family of
@ -34,8 +33,8 @@ class Transport:
In the C++ kernel, a transport manager implements a single
transport model, and is an instance of a subclass of the base
class 'Transport'. The structure in Python is a little
different. A single class 'Transport' represents any kernel-level
class ``Transport``. The structure in Python is a little
different. A single class ``Transport`` represents any kernel-level
transport manager. In addition, multiple kernel-kevel transport
managers may be installed in one Python transport manager,
although only one is active at any one time. This feature allows
@ -45,13 +44,16 @@ class Transport:
phase=None, model = "", loglevel=0):
"""Create a transport property manager.
xml_phase --- XML phase element
phase --- ThermoPhase instance representing the phase that the
transport properties are for
model --- string specifying transport model. If omitted or
set to 'Default', the model will be read from the
input file.
loglevel --- controls the amount of diagnostic output
:param xml_phase:
XML phase element
:param phase:
:class:`.ThermoPhase` instance representing the phase that the
transport properties are for
:param model:
String specifying transport model. If omitted or set to ``Default``,
the model will be read from the input file.
:param loglevel:
controls the amount of diagnostic output
"""
# if the transport model is not specified, look for attribute
@ -84,7 +86,7 @@ class Transport:
pass
def addTransportModel(self, model, loglevel=1):
"""Add a new transport model. Note that if 'model' is the
"""Add a new transport model. Note that if *model* is the
name of an already-installed transport model, the new
transport manager will take the place of the old one, which
will no longer be accessible. This method does not change the

View file

@ -22,7 +22,7 @@ if not os.getenv('PYTHON_CMD'):
def writeCSV(f, list):
"""
Write list items to file 'f' in
Write list items to file *f* in
comma-separated-value format. Strings will be written as-is, and
other types of objects will be converted to strings and then
written. Each call to writeCSV writes one line of the file.

View file

@ -7,43 +7,43 @@ the Cantera kernel.
import math
## One atmosphere in Pascals
#: One atmosphere in Pascals
OneAtm = 101325.0
## The ideal gas constant in J/kmo-K
#: The ideal gas constant in J/kmo-K
GasConstant = 8314.47215
## Avogadro's Number, /kmol
#: Avogadro's Number, /kmol
Avogadro = 6.02214179e26
## The ideal gas constant in cal/mol-K
#: The ideal gas constant in cal/mol-K
GasConst_cal_mol_K = 1.987
## Boltzmann-s constant
#: Boltzmann-s constant
Boltzmann = GasConstant / Avogadro
## The Stefan-Boltzmann constant, W/m^2K^4
#: The Stefan-Boltzmann constant, W/m^2K^4
StefanBoltz = 5.6704004e-8
## The charge on an electron (C)
#: The charge on an electron (C)
ElectronCharge = 1.60217648740e-19
## The mass of an electron (kg)
#: The mass of an electron (kg)
ElectronMass = 9.1093821545e-31
Pi = 3.1415926
## Faraday's constant, C/kmol
#: Faraday's constant, C/kmol
Faraday = ElectronCharge * Avogadro
## Planck's constant (J/s)
#: Planck's constant (J/s)
Planck = 6.6262e-34
## Permittivity of free space
#: Permittivity of free space
epsilon_0 = 8.85417817e-12 ## Farads/m = C^2/N/m^2
## Permeability of free space \f$ \mu_0 \f$ in N/A^2.
#: Permeability of free space :math:`\mu_0` in N/A^2.
permeability_0 = 4.0e-7*Pi; ## N/A^2
## Speed of Light (m/s).
#: Speed of Light (m/s).
lightSpeed = 1.0/math.sqrt(epsilon_0 * permeability_0);

View file

@ -14,16 +14,18 @@ from Cantera.solution import Solution
import os
def IdealGasMix(src="", id = "", loglevel = 0):
"""Return a Solution object representing an ideal gas mixture.
"""Return a :class:`.Solution` object representing an ideal gas mixture.
src --- input file
id --- XML id tag for phase
:param src:
input file
:param id:
XML id tag for phase
"""
return Solution(src=src,id=id,loglevel=loglevel)
def GRI30(transport = ""):
"""Return a Solution instance implementing reaction mechanism
"""Return a :class:`.Solution` instance implementing reaction mechanism
GRI-Mech 3.0."""
if transport == "":
return Solution(src="gri30.cti", id="gri30")
@ -34,12 +36,12 @@ def GRI30(transport = ""):
def Air():
"""Return a Solution instance implementing the O/N/Ar portion of
"""Return a :class:`.Solution` instance implementing the O/N/Ar portion of
reaction mechanism GRI-Mech 3.0. The initial composition is set to
that of air"""
return Solution(src="air.cti", id="air")
def Argon():
"""Return a Solution instance representing pure argon."""
"""Return a :class:`.Solution` instance representing pure argon."""
return Solution(src="argon.cti", id="argon")

View file

@ -34,6 +34,7 @@ def importInterface(file, name = '', phases = []):
The 'phases' argument is a list of objects representing the other phases
that participate in the interfacial reactions, for example an object
representing a gas phase or a solid.
>>> gas1, cryst1 = importPhases('diamond.cti', ['gas', 'solid'])
>>> diamond_surf = importInterface('diamond.cti', [gas1, cryst1])

View file

@ -41,7 +41,6 @@ class Mixture:
"""
def __init__(self, phases=[]):
""" init """
self.__mixid = _cantera.mix_new()
self._spnames = []
self._phases = []
@ -89,7 +88,7 @@ class Mixture:
return self._phases[n]
def phaseName(self, n):
"""Name of phase n."""
"""Name of phase *n*."""
return self._phases[n].name()
def phaseNames(self):
@ -101,7 +100,7 @@ class Mixture:
return nm
def phaseIndex(self, phase):
"""Index of phase with name 'phase'"""
"""Index of phase with name *phase*"""
np = self.nPhases()
if type(phase) <> types.StringType:
return phase
@ -116,9 +115,9 @@ class Mixture:
def elementIndex(self, element):
"""Index of element with name 'element'.
>>> mix.elementIndex('H')
2
>>>
"""
if type(element) == types.StringType:
return _cantera.mix_elementIndex(self.__mixid, element)
@ -131,7 +130,7 @@ class Mixture:
return _cantera.mix_nSpecies(self.__mixid)
def speciesName(self, k):
"""Name of the species with index k. Note that index numbers
"""Name of the species with index *k*. Note that index numbers
are assigned in order as phases are added."""
return self._spnames[k]
@ -143,7 +142,7 @@ class Mixture:
return s
def speciesIndex(self, species):
"""Index of species with name 'species'. If 'species' is not a string,
"""Index of species with name *species*. If *species* is not a string,
then it is simply returned."""
if type(species) == types.StringType:
return self._spnames.index(species)
@ -151,7 +150,7 @@ class Mixture:
return species
def nAtoms(self, k, m):
"""Number of atoms of element m in species k. Both the species and
"""Number of atoms of element *m* in species *k*. Both the species and
the element may be referenced either by name or by index number.
>>> n = mix.nAtoms('CH4','H')
@ -188,7 +187,7 @@ class Mixture:
return _cantera.mix_charge(self.__mixid)
def phaseCharge(self, p):
"""The charge of phase p (Coulombs)."""
"""The charge of phase *p* (Coulombs)."""
return _cantera.mix_phaseCharge(self.__mixid, p)
def setPressure(self, p):
@ -201,7 +200,7 @@ class Mixture:
return _cantera.mix_pressure(self.__mixid)
def phaseMoles(self, n = -1):
"""Moles of phase n."""
"""Moles of phase *n*."""
if n == -1:
np = self.nPhases()
moles = zeros(np,'d')
@ -212,7 +211,7 @@ class Mixture:
return _cantera.mix_phaseMoles(self.__mixid, n)
def setPhaseMoles(self, n, moles):
"""Set the number of moles of phase n."""
"""Set the number of moles of phase *n*."""
_cantera.mix_setPhaseMoles(self.__mixid, n, moles)
def setSpeciesMoles(self, moles):
@ -238,7 +237,7 @@ class Mixture:
return self.selectSpecies(moles, species)
def elementMoles(self, m):
"""Total number of moles of element m, summed over all species.
"""Total number of moles of element *m*, summed over all species.
The element may be referenced either by index number or by name.
"""
mm = self.elementIndex(m)
@ -271,46 +270,45 @@ class Mixture:
mixture, subject to element conservation constraints. For a
description of the theory, see Smith and Missen, "Chemical
Reaction Equilibrium." The VCS algorithm is implemented in
Cantera kernel class MultiPhaseEquil.
Cantera kernel class ``MultiPhaseEquil``.
The VCS algorithm solves for the equilibrium composition for
specified temperature and pressure. If any other property pair
other than "TP" is specified, then an outer iteration loop is
other than ``TP`` is specified, then an outer iteration loop is
used to adjust T and/or P so that the specified property
values are obtained.
XY - Two-letter string specifying the two properties to hold fixed.
Currently, 'TP', 'HP', and 'SP' are implemented. Default: 'TP'.
err - Error tolerance. Iteration will continue until (Delta
mu)/RT is less than this value for each reaction. Default:
1.0e-9. Note that this default is very conservative, and good
equilibrium solutions may be obtained with larger error
tolerances.
maxsteps - Maximum number of steps to take while solving the
equilibrium problem for specified T and P. Default: 1000.
maxiter - Maximum number of temperature and/or pressure iterations.
This is only relevant if a property pair other than (T,P) is
specified. Default: 200.
loglevel - Controls the amount of diagnostic output. If
loglevel = 0, no diagnostic output is written. For values > 0,
more detailed information is written to the log file as
loglevel increases. The default is loglevel = 0.
The logfile is written in HTML format, and may be viewed with
any web browser. The default log file name is
"equilibrium_log.html", but if this file exists, the log
information will be written to "equilibrium_log{n}.html",
where {n} is an integer chosen so that the log file does not
already exist. Therefore, if 'equilibrate' is called multiple
times, multiple log files will be written, with names
"equilibrate_log.html", "equilibrate_log1.html",
"equilibrate_log2.html", and so on. Existing log files will
not be overwritten.
:param XY:
Two-letter string specifying the two properties to hold fixed.
Currently, ``'TP'``, ``'HP'``, and ``'SP'`` are implemented.
Default: ``'TP'``.
:param err:
Error tolerance. Iteration will continue until (Delta mu)/RT is
less than this value for each reaction. Default: 1.0e-9. Note that
this default is very conservative, and good equilibrium solutions
may be obtained with larger error tolerances.
:param maxsteps:
Maximum number of steps to take while solving the equilibrium
problem for specified *T* and *P*. Default: 1000.
:param maxiter:
Maximum number of temperature and/or pressure iterations.
This is only relevant if a property pair other than (T,P) is
specified. Default: 200.
:param loglevel:
Controls the amount of diagnostic output. If loglevel = 0, no
diagnostic output is written. For values > 0, more detailed
information is written to the log file as loglevel increases.
The default is loglevel = 0.
The logfile is written in HTML format, and may be viewed with
any web browser. The default log file name is
``equilibrium_log.html``, but if this file exists, the log
information will be written to "equilibrium_log{n}.html", where
{n} is an integer chosen so that the log file does not already
exist. Therefore, if 'equilibrate' is called multiple times,
multiple log files will be written, with names
``equilibrate_log.html``, ``equilibrate_log1.html``,
``equilibrate_log2.html``, and so on. Existing log files will
not be overwritten.
>>> mix.equilibrate('TP')
>>> mix.equilibrate('TP', err = 1.0e-6, maxiter = 500)
@ -333,62 +331,62 @@ class Mixture:
The VCS algorithm solves for the equilibrium composition for
specified temperature and pressure. If any other property pair
other than "TP" is specified, then an outer iteration loop is
other than ``'TP'`` is specified, then an outer iteration loop is
used to adjust T and/or P so that the specified property
values are obtained.
XY - Two-letter string specifying the two properties to hold fixed.
Currently, 'TP', 'HP', and 'SP' are implemented. Default: 'TP'.
printLvl - Controls the amount of diagnostic output written to cout. If
printLvl = 0, no diagnostic output is written. For values > 0,
more detailed information is written to cout.
The default is printLvl = 0.
solver - Determines which solver is used.
- 1 MultiPhaseEquil solver
- 2 VCSnonideal Solver (default)
err - Error tolerance. Iteration will continue until (Delta
mu)/RT is less than this value for each reaction. Default:
1.0e-9. Note that this default is very conservative, and good
equilibrium solutions may be obtained with larger error
tolerances.
maxsteps - Maximum number of steps to take while solving the
equilibrium problem for specified T and P. Default: 1000.
maxiter - Maximum number of temperature and/or pressure iterations.
This is only relevant if a property pair other than (T,P) is
specified. Default: 200.
loglevel - Controls the amount of diagnostic output written to html. If
loglevel = 0, no diagnostic output is written. For values > 0,
more detailed information is written to the log file as
loglevel increases. The default is loglevel = 0.
The logfile is written in HTML format, and may be viewed with
any web browser. The default log file name is
"equilibrium_log.html", but if this file exists, the log
information will be written to "equilibrium_log{n}.html",
where {n} is an integer chosen so that the log file does not
already exist. Therefore, if 'equilibrate' is called multiple
times, multiple log files will be written, with names
"equilibrate_log.html", "equilibrate_log1.html",
"equilibrate_log2.html", and so on. Existing log files will
not be overwritten.
:param XY:
Two-letter string specifying the two properties to hold fixed.
Currently, ``'TP'``, ``'HP'``, and ``'SP'`` are implemented.
Default: ``'TP'``.
:param printLvl:
Controls the amount of diagnostic output written to cout. If
printLvl = 0, no diagnostic output is written. For values > 0,
more detailed information is written to cout.
The default is printLvl = 0.
:param solver:
Determines which solver is used.
- 1 MultiPhaseEquil solver
- 2 VCSnonideal Solver (default)
:param err:
Error tolerance. Iteration will continue until (Delta mu)/RT is
less than this value for each reaction. Default: 1.0e-9. Note that
this default is very conservative, and good equilibrium solutions
May be obtained with larger error tolerances.
:param maxsteps:
Maximum number of steps to take while solving the equilibrium
problem for specified T and P. Default: 1000.
:param maxiter:
Maximum number of temperature and/or pressure iterations. This is
only relevant if a property pair other than (T,P) is specified.
Default: 200.
:param loglevel:
Controls the amount of diagnostic output written to html. If
loglevel = 0, no diagnostic output is written. For values > 0,
more detailed information is written to the log file as
loglevel increases. The default is loglevel = 0.
The logfile is written in HTML format, and may be viewed with
any web browser. The default log file name is
"equilibrium_log.html", but if this file exists, the log
information will be written to "equilibrium_log{n}.html",
where {n} is an integer chosen so that the log file does not
already exist. Therefore, if 'equilibrate' is called multiple
times, multiple log files will be written, with names
"equilibrate_log.html", "equilibrate_log1.html",
"equilibrate_log2.html", and so on. Existing log files will
not be overwritten.
"""
i = _cantera.mix_vcs_equilibrate(self.__mixid, XY, estimateEquil,
printLvl, solver, rtol, maxsteps,
maxiter, loglevel)
def selectSpecies(self, f, species):
"""Given an array 'f' of floating-point species properties,
"""Given an array *f* of floating-point species properties,
return an array of those values corresponding to species
listed in 'species'. This method is used internally to implement
species selection in methods like moleFractions, massFractions, etc.
listed in *species*. This method is used internally to implement
species selection in methods like :meth:`~.Phase.moleFractions`,
:meth:`~.Phase.massFractions`, etc.
>>> f = mix.chemPotentials()
>>> muo2, muh2 = mix.selectSpecies(f, ['O2', 'H2'])
"""

View file

@ -17,12 +17,12 @@ class Solution(ThermoPhase, Kinetics, Transport):
mixture of gases, a liquid solution, or a solid solution, for
example.
Class Solution derives from classes ThermoPhase, Kinetics, and
Transport. It defines very few methods of its own, and is
Class Solution derives from classes :class:`.ThermoPhase`, :class:`.Kinetics`,
and :class:`.Transport`. It defines very few methods of its own, and is
provided largely for convenience, so that a single object can be
used to compute thermodynamic, kinetic, and transport properties
of a solution. Functions like IdealGasMix and others defined in
module gases return objects of class Solution.
of a solution. Functions like :func:`.IdealGasMix` and others defined in
module gases return objects of class :class:`.Solution`.
"""
@ -70,16 +70,28 @@ class Solution(ThermoPhase, Kinetics, Transport):
def set(self, **options):
"""Set various properties.
T --- temperature [K]
P --- pressure [Pa]
Rho --- density [kg/m3]
V --- specific volume [m3/kg]
H --- specific enthalpy [J/kg]
U --- specific internal energy [J/kg]
S --- specific entropy [J/kg/K]
X --- mole fractions (string or array)
Y --- mass fractions (string or array)
Vapor --- saturated vapor fraction
Liquid --- saturated liquid fraction
:param T:
temperature [K]
:param P:
pressure [Pa]
:param Rho:
density [kg/m3]
:param V:
specific volume [m3/kg]
:param H:
specific enthalpy [J/kg]
:param U:
specific internal energy [J/kg]
:param S:
specific entropy [J/kg/K]
:param X:
mole fractions (string or array)
:param Y:
mass fractions (string or array)
:param Vapor:
saturated vapor fraction
:param Liquid:
saturated liquid fraction
"""
setByName(self, options)