*** empty log message ***

This commit is contained in:
Dave Goodwin 2004-12-10 05:07:14 +00:00
parent d5d13be7d4
commit 83b08d7a26
9 changed files with 280 additions and 21 deletions

View file

@ -96,10 +96,18 @@ extern "C" {
return _mix(i)->nElements();
}
int DLL_EXPORT mix_elementIndex(int i, char* name) {
return _mix(i)->elementIndex(string(name));
}
int DLL_EXPORT mix_nSpecies(int i) {
return _mix(i)->nSpecies();
}
int DLL_EXPORT mix_speciesIndex(int i, int k, int p) {
return _mix(i)->speciesIndex(k, p);
}
doublereal DLL_EXPORT mix_nAtoms(int i, int k, int m) {
bool ok = (checkSpecies(i,k) && checkElement(i,m));
if (ok)
@ -120,6 +128,24 @@ extern "C" {
return 0;
}
int DLL_EXPORT mix_setMoles(int i, int nlen, double* n) {
try {
if (nlen < _mix(i)->nSpecies())
throw CanteraError("setMoles","array size too small.");
_mix(i)->setMoles(n);
return 0;
}
catch (CanteraError) {
return ERR;
}
}
int DLL_EXPORT mix_setMolesByName(int i, char* n) {
_mix(i)->setMolesByName(string(n));
return 0;
}
int DLL_EXPORT mix_setTemperature(int i, double t) {
if (t < 0.0) return -1;
_mix(i)->setTemperature(t);

View file

@ -11,6 +11,8 @@ extern "C" {
int DLL_IMPORT mix_assign(int i, int j);
int DLL_IMPORT mix_addPhase(int i, int j, double moles);
int DLL_IMPORT mix_nElements(int i);
int DLL_IMPORT mix_elementIndex(int i, char* name);
int DLL_IMPORT mix_speciesIndex(int i, int k, int p);
int DLL_IMPORT mix_nSpecies(int i);
int DLL_IMPORT mix_setTemperature(int i, double t);
double DLL_IMPORT mix_temperature(int i);
@ -19,6 +21,8 @@ extern "C" {
double DLL_IMPORT mix_nAtoms(int i, int k, int m);
double DLL_IMPORT mix_phaseMoles(int i, int n);
int DLL_IMPORT mix_setPhaseMoles(int i, int n, double v);
int DLL_IMPORT mix_setMoles(int i, int nlen, double* n);
int DLL_IMPORT mix_setMolesByName(int i, char* n);
double DLL_IMPORT mix_speciesMoles(int i, int k);
double DLL_IMPORT mix_elementMoles(int i, int m);
double DLL_IMPORT mix_equilibrate(int i, char* XY,

View file

@ -5,7 +5,7 @@
#define CT_EQUIL_INCL
#include "kernel/ChemEquil.h"
//#ifdef DEV_EQUIL
//#include "kernel/MultiPhaseEquil.h"
#include "kernel/MultiPhaseEquil.h"
//#endif
#endif

View file

@ -3,4 +3,6 @@
#include "kernel/transport/TransportFactory.h"
#include "kernel/transport/DustyGasTransport.h"
#include "kernel/transport/MultiTransport.h"
#include "kernel/transport/MixTransport.h"
#endif

View file

@ -1,9 +1,39 @@
import _cantera
import types
from Numeric import zeros
from Numeric import zeros, array, asarray
from exceptions import CanteraError
class Mixture:
"""Class Mixture represents mixtures of one or more phases of matter."""
"""
Multiphase mixtures. Class Mixture represents
mixtures of one or more phases of matter. To construct a mixture,
supply a list of phases to the constructor, each paired with the
number of moles for that phase:
>>> gas = importPhase('gas.cti')
>>> gas.speciesNames()
['H2', 'H', 'O2', 'O', 'OH']
>>> graphite = importPhase('graphite.cti')
>>> graphite.speciesNames()
['C(g)']
>>> mix = Mixture([(gas, 1.0), (graphite, 0.1)])
>>> mix.speciesNames()
['H2', 'H', 'O2', 'O', 'OH', 'C(g)']
Note that the objects representing each phase compute only the
intensive state of the phase -- they do not store any information
on the amount of this phase. Mixture objects, on the other hand, represent
the full extensive state.
Mixture objects are 'lightweight' in the sense that they do not
store parameters needed to compute thermodynamic or kinetic
properties of the phases. These are contained in the
('heavyweight') phase objects. Multiple mixture objects may be
constructed using the same set of phase objects. Each one stores
its own state information locally, and synchronizes the phases
objects whenever it requires phase properties.
"""
def __init__(self, phases=[]):
self.__mixid = _cantera.mix_new()
@ -17,67 +47,194 @@ class Mixture:
except:
ph = p
moles = 0
self.addPhase(ph, moles)
self._addPhase(ph, moles)
self._phases.append(ph)
self.setTemperature(self._phases[0].temperature())
self.setPressure(self._phases[0].pressure())
def __del__(self):
"""Delete the Mixture instance. The phase objects are not deleted."""
_cantera.mix_del(self.__mixid)
def __repr__(self):
s = ''
for p in range(len(self._phases)):
s += '\n******************* Phase '+`p`+' ******************************\n'
s += '\n******************* Phase '+self._phases[p].name()+' ******************************\n'
s += '\n Moles: '+`self.phaseMoles(p)`+'\n'
s += self._phases[p].__repr__()+'\n\n'
return s
def addPhase(self, phase = None, moles = 0.0):
def _addPhase(self, phase = None, moles = 0.0):
"""Add a phase to the mixture."""
for k in range(phase.nSpecies()):
self._spnames.append(phase.speciesName(k))
self._spnames.append(phase.speciesName(k))
_cantera.mix_addPhase(self.__mixid, phase.thermo_hndl(), moles)
def nElements(self):
"""Total number of elements present in the mixture."""
return _cantera.mix_nElements(self.__mixid)
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)
else:
return element
def nSpecies(self):
"""Total number of species present in the mixture. This is the
sum of the numbers of species in each phase."""
return _cantera.mix_nSpecies(self.__mixid)
def speciesName(self, k):
"""Name of the species with index k. Note that index numbers
are assigned in order as phases are added."""
return self._spnames[k]
def speciesNames(self):
n = self.nSpecies()
s = []
for k in range(n):
s.append(self.speciesName(k))
return s
def speciesIndex(self, species):
"""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)
else:
return species
def nAtoms(self, k, m):
"""Number of atoms of element m in species k."""
return _cantera.mix_nAtoms(self.__mixid, k, m)
"""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')
4.0
"""
kk = self.speciesIndex(k)
mm = self.elementIndex(m)
return _cantera.mix_nAtoms(self.__mixid, kk, mm)
def setTemperature(self, t):
"""Set the temperature [K]. The temperatures of all phases are
set to this value, holding the pressure fixed."""
return _cantera.mix_setTemperature(self.__mixid, t)
def temperature(self):
"""The temperature [K]."""
return _cantera.mix_temperature(self.__mixid)
def setPressure(self, p):
"""Set the pressure [Pa]. The pressures of all phases are set
to the specified value, holding the temperature fixed."""
return _cantera.mix_setPressure(self.__mixid, p)
def pressure(self):
"""The pressure [Pa]."""
return _cantera.mix_pressure(self.__mixid)
def phaseMoles(self, n):
"""Moles of phase n."""
return _cantera.mix_phaseMoles(self.__mixid, n)
def setPhaseMoles(self, n, moles):
"""Set the moles of phase n."""
return _cantera.mix_setPhaseMoles(self.__mixid, n, moles)
def speciesMoles(self, species):
"""Set the number of moles of phase n."""
_cantera.mix_setPhaseMoles(self.__mixid, n, moles)
def setMoles(self, moles):
"""Set the moles of the species [kmol]. The moles may be
specified either as a string, or as an array. If an array is
used, it must be dimensioned at least as large as the total
number of species in the mixture. Note that the species may
belong to any phase, and unspecified species are set to zero.
>>> mix.setMoles('C(s):1.0, CH4:2.0, O2:0.2')
"""
if type(moles) == types.StringType:
_cantera.mix_setMolesByName(self.__mixid, moles)
else:
_cantera.mix_setMoles(self.__mixid, asarray(moles))
def speciesMoles(self, species = ""):
"""Moles of species k."""
k = self.speciesIndex(species)
return _cantera.mix_speciesMoles(self.__mixid, k)
moles = array(self.nSpecies(),'d')
for k in range(self.nSpecies()):
moles[k] = _cantera.mix_speciesMoles(self.__mixid, k)
return self.selectSpecies(moles, species)
def elementMoles(self, m):
return _cantera.mix_elementMoles(self.__mixid, m)
def chemPotentials(self):
"""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)
return _cantera.mix_elementMoles(self.__mixid, mm)
def chemPotentials(self, species=[]):
"""The chemical potentials of all species [J/kmol]."""
mu = zeros(self.nSpecies(),'d')
_cantera.mix_getChemPotentials(self.__mixid, mu)
return mu
return self.selectSpecies(mu, species)
def set(self, **p):
for o in p.keys():
v = p[o]
if o == 'T' or o == 'Temperature':
self.setTemperature(v)
elif o == 'P' or o == 'Pressure':
self.setPressure(v)
elif o == 'Moles' or o == 'N':
self.setSpeciesMoles(v)
else:
raise CanteraError("unknown property: "+o)
def equilibrate(self, XY = "TP", err = 1.0e-9, maxiter = 1000):
"""Set the mixture to a state of chemical equilibrium.
This method uses the VCS algorithm to find the composition
that minimizes the total Gibbs free energy of the 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.
XY - Two-letter string specifying the two properties to hold fixed.
Currently, only TP (constant T and P) is 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.
maxiter - Maximum number of iterations to attempt. Default: 1000.
>>> mix.equilibrate('TP')
>>> mix.equilibrate('TP', err = 1.0e-6, maxiter = 500)
"""
return _cantera.mix_equilibrate(self.__mixid, XY, err, maxiter)
def selectSpecies(self, f, species):
"""Given an array 'f' of floating-point species properties,
return a Numeric 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 = mix.chemPotentials()
>>> muo2, muh2 = mix.selectSpecies(f, ['O2', 'H2'])
"""
sp = []
if species:
if type(species) == types.StringType:
sp = [sp]
else:
sp = species
fs = []
k = 0
for s in s:
k = self.speciesIndex(s)
fs.append(f[k])
return Numeric.asarray(fs)
else:
return f

View file

@ -64,6 +64,9 @@ class ThermoPhase(Phase):
if self._owner:
_cantera.thermo_delete(self._phase_id)
def name(self):
return self.idtag
def refPressure(self):
"""Reference pressure [Pa].
All standard-state thermodynamic properties are for this pressure.

View file

@ -37,6 +37,8 @@ try:
except:
pass
from Mixture import Mixture
def writeCSV(f, list):
"""Write list items to file 'f' in comma-separated-value format."""
for item in list:

View file

@ -51,6 +51,20 @@ py_mix_nElements(PyObject *self, PyObject *args)
return Py_BuildValue("i",_val);
}
static PyObject *
py_mix_elementIndex(PyObject *self, PyObject *args)
{
int _val;
int i;
char* name;
if (!PyArg_ParseTuple(args, "is:mix_elementIndex", &i, &name))
return NULL;
_val = mix_elementIndex(i,name);
if (int(_val) < -900) return reportCanteraError();
return Py_BuildValue("i",_val);
}
static PyObject *
py_mix_nSpecies(PyObject *self, PyObject *args)
{
@ -64,6 +78,18 @@ py_mix_nSpecies(PyObject *self, PyObject *args)
return Py_BuildValue("i",_val);
}
static PyObject *
py_mix_speciesIndex(PyObject *self, PyObject *args)
{
int _val;
int i, k, p;
if (!PyArg_ParseTuple(args, "iii:mix_speciesIndex", &i, &k, &p))
return NULL;
_val = mix_speciesIndex(i,k,p);
if (int(_val) < -900) return reportCanteraError();
return Py_BuildValue("i",_val);
}
static PyObject *
py_mix_nAtoms(PyObject *self, PyObject *args)
@ -192,11 +218,46 @@ py_mix_elementMoles(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "ii:mix_elementMoles", &i, &m))
return NULL;
_val = mix_elementMoles(i,m);
//if (int(_val) < -900) return reportCanteraError();
_val = mix_elementMoles(i,m);
if (int(_val) < -900) return reportCanteraError();
return Py_BuildValue("d",_val);
}
static PyObject *
py_mix_setMoles(PyObject *self, PyObject *args)
{
int _val;
int i;
PyObject* n;
if (!PyArg_ParseTuple(args, "iO:mix_setMoles", &i, &n))
return NULL;
PyArrayObject* n_array = (PyArrayObject*)n;
double* n_data = (double*)n_array->data;
int n_len = n_array->dimensions[0];
_val = mix_setMoles(i,n_len,n_data);
if (int(_val) < -900) return reportCanteraError();
return Py_BuildValue("i",_val);
}
static PyObject *
py_mix_setMolesByName(PyObject *self, PyObject *args)
{
int _val;
int i;
char* n;
if (!PyArg_ParseTuple(args, "is:mix_setMolesByName", &i, &n))
return NULL;
_val = mix_setMolesByName(i,n);
if (int(_val) < -900) return reportCanteraError();
return Py_BuildValue("i",_val);
}
static PyObject *
py_mix_equilibrate(PyObject *self, PyObject *args)
{

View file

@ -255,6 +255,8 @@ static PyMethodDef ct_methods[] = {
{"mix_del", py_mix_del, METH_VARARGS},
{"mix_addPhase", py_mix_addPhase, METH_VARARGS},
{"mix_nElements", py_mix_nElements, METH_VARARGS},
{"mix_elementIndex", py_mix_elementIndex, METH_VARARGS},
{"mix_speciesIndex", py_mix_speciesIndex, METH_VARARGS},
{"mix_nSpecies", py_mix_nSpecies, METH_VARARGS},
{"mix_nAtoms", py_mix_nAtoms, METH_VARARGS},
{"mix_setTemperature", py_mix_setTemperature, METH_VARARGS},
@ -263,6 +265,8 @@ static PyMethodDef ct_methods[] = {
{"mix_pressure", py_mix_pressure, METH_VARARGS},
{"mix_phaseMoles", py_mix_phaseMoles, METH_VARARGS},
{"mix_setPhaseMoles", py_mix_setPhaseMoles, METH_VARARGS},
{"mix_setMoles", py_mix_setMoles, METH_VARARGS},
{"mix_setMolesByName", py_mix_setMolesByName, METH_VARARGS},
{"mix_speciesMoles", py_mix_speciesMoles, METH_VARARGS},
{"mix_elementMoles", py_mix_elementMoles, METH_VARARGS},
{"mix_equilibrate", py_mix_equilibrate, METH_VARARGS},