*** empty log message ***
This commit is contained in:
parent
d5d13be7d4
commit
83b08d7a26
9 changed files with 280 additions and 21 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue