*** empty log message ***

This commit is contained in:
Dave Goodwin 2003-04-24 08:55:11 +00:00
parent 4f3912b7b1
commit f0b91575da
11 changed files with 228 additions and 16 deletions

View file

@ -66,6 +66,15 @@ extern "C" {
return 0;
}
double DLL_EXPORT bndry_spreadrate(int i) {
return ((Inlet1D*)_bndry(i))->spreadRate();
}
int DLL_EXPORT bndry_setSpreadRate(int i, double v) {
((Inlet1D*)_bndry(i))->setSpreadRate(v);
return 0;
}
int DLL_EXPORT bndry_setmdot(int i, double mdot) {
try {
_bndry(i)->setMdot(mdot);

View file

@ -9,6 +9,8 @@ extern "C" {
int DLL_IMPORT bndry_del(int i);
double DLL_IMPORT bndry_temperature(int i);
int DLL_IMPORT bndry_settemperature(int i, double t);
double DLL_IMPORT bndry_spreadrate(int i);
int DLL_IMPORT bndry_setSpreadRate(int i, double v);
int DLL_IMPORT bndry_setmdot(int i, double mdot);
double DLL_IMPORT bndry_mdot(int i);
int DLL_IMPORT bndry_setxin(int i, double* xin);

View file

@ -557,6 +557,44 @@ class Flow1D:
return nin
def prune(self, loglevel = 2):
"""Prune the grid.
"""
r = self.refiner
r.components = range(4,self.nsp+4)
if self.energy:
r.components.append(2)
znew, xn = r.prune(grid = self.z, solution = self.x)
nout = len(self.z) - len(znew)
if nout > 0:
self.setGrid(znew)
self.x = array(xn,'d')
self.xnew = zeros(shape(xn),'d')
# update the fixed temperature values if the energy
# equation is not being solved
if self.energy == 0:
for j in range(self.npts):
zz, tt = self.initial['T']
t = interp.interp(self.z[j],zz,tt)
self.holdTemperature(j,t)
else:
for j in range(self.npts):
self.holdTemperature(j,self.x[j,2])
self.setEnergyEqn('on')
if loglevel > 0:
print 'Prune: ',
print 'removed',nout,'points.'
print 'Grid size = ',len(self.z)
return nout
def save(self, filename, id, desc="", append=0):
"""Save a solution to a file.

View file

@ -321,6 +321,28 @@ class OneDim:
self._end.append(self._loc)
return new_points
def prune(self, loglevel = 2):
"""Prune the grid of every flow domain."""
rem_points = 0
for f in self._flow:
rem_points += f.prune(loglevel)
if rem_points > 0:
self.collect()
_cantera.onedim_resize(self.__onedim_id)
self._shape = []
self._size = []
self._start = []
self._end = []
self._loc = 0
for d in self._domain:
np, nv = d.shape()
self._shape.append((np, nv))
self._size.append(np*nv)
self._start.append(self._loc)
self._loc += np*nv
self._end.append(self._loc)
return rem_points
def setEnergyFactor(self, e):
for f in self._flow:
f.setEnergyFactor(e)

View file

@ -34,6 +34,9 @@ class Boundary1D:
self.T = T
self.x[0,1] = T
_cantera.bndry_settemperature(self.__bndry_id, T)
if V <> -999.0:
self.V = V
_cantera.bndry_setspreadrate(self.__bndry_id, V)
if X:
self.X = X
if type(X) == types.StringType:

View file

@ -17,6 +17,19 @@ class BurnerFlame:
flame = BurnerFlame(gas, domain, fuel, oxidizer, inert, grid, pressure)
arguments:
gas --- an object representing the gas mixture
domain --- [zmin, zmax]
fuel --- a string specifying the fuel stream composition
oxidizer --- a string specifying the oxidizer stream composition
inert --- a string specifying the composition of an inert
stream (optional)
grid --- a sequence defining the initial grid. The first point
should be zmin, and the last one zmax. If omitted,
a default grid will be used.
pressure --- the pressure, which is treated as constant.
example:
flame = BurnerFlame(gas = GRI30(),
domain = [0.0, 10.0*units.cm],
@ -31,6 +44,7 @@ class BurnerFlame:
fuel = '', oxidizer = '', inert = '',
grid = None, pressure = -1.0):
# check that all required inputs have been specified
if not gas or not domain or not fuel or not oxidizer or not pressure:
raise self.__doc__
@ -38,18 +52,26 @@ class BurnerFlame:
self.p = pressure
dx = (domain[1] - domain[0])
# if no grid specified, use this one that concentrates points
# near the burner
if grid == None:
grid = dx * array([0.0, 0.01, 0.03, 0.1, 0.3, 0.6, 1.0])
self.__flow = Flow1D(flow_type = 'OneDim', gas = gas,
grid = grid, pressure = self.p)
#------ these methods are deprecated, but still needed for now.
self.inlet = Inlet(gas)
self.outlet = Outlet(gas)
self.__flow.setBoundaries(left = self.inlet, right = self.outlet)
#----------------------------------------------------------------
# The container contains only the Flow1D object. Should be
# modified at some point to contain an Inlet1D and an Outlet1D
# object.
self.__container = OneDim([self.__flow])
self.start = 0
@ -57,7 +79,6 @@ class BurnerFlame:
# get the compositions of the fuel and oxidizer streams, and
# calculate the fuel/oxidizer ratio for stoichiometric
# combustion
gas.setMoleFractions(fuel)
self._xfuel = gas.moleFractions()
@ -73,18 +94,28 @@ class BurnerFlame:
self._stoich_FO = stoich.stoich_fuel_to_oxidizer(gas, fuel, oxidizer)
# TODO: accout for inert stream
def setEquivRatio(self, phi):
"""Set the equivalence ratio."""
f_flow = self._stoich_FO * phi
comp = f_flow * self._xfuel + self._xox
self.gas.setState_PX(self.p, comp)
self.inlet.set(X = self.gas.moleFractions())
def setEquilProducts(self):
"""Set the flame state to chemical equilibrium.
"""Generate a starting estimate for the flame state.
The following procedure is used:
1) At the burner, the composition is the specified inlet
composition;
2) The last 80% of the domain has constant composition and
temperature corresponding to the adiabatic equilibrium
solution;
3) In the initial 20%, the composition and temperature vary linearly
from the inlet values to the equilibrium values.
This is useful to generate a starting estimate.
"""
x0 = self.inlet.X
self.gas.setState_TPX(self.inlet.T, self.p, x0)
@ -104,30 +135,84 @@ class BurnerFlame:
xinit[nm] = x
self.__flow.setInitialProfiles(xinit)
def plot(self, plotfile = '', title = '', fmt = 'TECPLOT',
zone = 'c0', append = 0):
"""Plot the current solution."""
self.__flow.plotter.plot(fname = plotfile, title = title,
fmt = fmt, zone = zone, append=append)
def setInitialProfiles(self, **init):
"""Specify estimates for the initial profiles.
"""
self.__flow.setInitialProfiles(init)
self.start = 1
def restore(self, src = '', solution = ''):
"""Start from a previously-saved solution."""
self.__container.restore(0, src, solution)
self.start = 1
def setTolerances(self, V = None, T = None, Y = None):
"""Set tolerances for convergence for velocity, temperature,
and mass fractions."""
self.__flow.setTolerances( V, V, T, Y)
def prune(self, loglevel = 2):
"""Remove unneeded grid points.
This method attempts to remove each grid point one by one, and
calls 'refine' each time to see whether it puts it back. If it does,
the point is not removed, otherwise it is.
"""
self.__container.prune(loglevel)
def refine(self, loglevel = 2):
"""Refine the grid using the current grid refinement parameters."""
self.__container.refine(loglevel)
def show(self):
"""Print a summary of the current solution to the screen."""
self.__flow.show()
def stretch(self, factor):
"""Stretch the grid by 'factor'"""
self.__flow.setGrid(factor*self.__flow.z)
def set(self, **opt):
"""Set options.
The options that may be set are:
energy --- 'on' or 'off'. If 'on', the energy equation is
solved; otherwise, the temperature is held to the specified
profile.
pressure --- the pressure in Pa.
mdot --- the inlet mass flow rate per unit area.
equiv_ratio --- the equivalence ratio
T_burner --- the burner surface temperature [K].
refine --- a triplet specifying the refinement criteria.
See refine.py for more information.
tol --- error tolerances for u, V, T, and Y.
max_jac_age --- the maximum number of times to use a Jacobian
before recomputing it.
timesteps --- number and duration of time steps to take
when Newton iteration fails. The format is
( number_sequence, initial_stepsize )
These parameters can be changed as the solution proceeds."""
# TODO: is this necessary?
if self.__container == None:
self.__container = OneDim([self.__flow,])
@ -153,23 +238,38 @@ class BurnerFlame:
elif o == 'timesteps':
self.__container.setOptions(nsteps = v[0], timestep = v[1])
def solve(self, loglevel = 0):
""" Solve the flame equations.
If no starting estimate has been given, setEquilProducts()
is called to generate one.
"""
if not self.start:
self.setEquilProducts()
self.start = 1
solve(self.__container, loglevel = loglevel, refine_grid = 1)
def esolve(self, loglevel = 0, efactor = 1.0e4):
if not self.start:
self.setEquilProducts()
self.start = 1
esolve(self.__container, efactor = efactor, loglevel = loglevel, refine_grid = 1)
## def esolve(self, loglevel = 0, efactor = 1.0e4):
## if not self.start:
## self.setEquilProducts()
## self.start = 1
## esolve(self.__container, efactor = efactor, loglevel = loglevel, refine_grid = 1)
def save(self, soln, desc, file = 'flame.xml'):
"""Save the current solution.
soln --- string to identify this solution in the file.
desc --- descriptive text string.
file --- file name.
"""
self.__container.save(file, soln, desc)
def showStatistics(self):
"""Show numerical statistics."""
self.__container.showStatistics()
@ -312,7 +412,13 @@ class StagnationFlame:
def enableEnergy(self, pt):
self.__flow.setEnergyEqn('on',loglevel=1,pt=pt)
def prune(self, loglevel = 2):
self.__container.prune(loglevel)
def refine(self, loglevel = 2):
self.__container.refine(loglevel)
def set(self, **opt):
if self.__container == None:
@ -331,6 +437,8 @@ class StagnationFlame:
self.setEquivRatio(v)
elif o == 'T_burner':
self.__left.set(T = v)
elif o == 'spreadingRate':
self.__left.set(V = v)
elif o == 'T_surface':
self.__right.set(T = v)
elif o == 'refine':

View file

@ -108,7 +108,7 @@ class Refiner:
np = len(g)
self.direction = 1
gnew, snew = self.refine(g, sol, threshold)
gnew, gn, snew, ok = self.refine(g, sol, threshold)
if (len(gnew) > np):
g = g0
sol = s0
@ -124,7 +124,7 @@ class Refiner:
return (g, sol)
def refine(self, grid = None, solution = None, threshold = None):
def refine(self, grid = None, solution = None, threshold = None, prune = 1):
self.ok = 0
# grid parameters

View file

@ -68,6 +68,28 @@ py_bndry_settemperature(PyObject *self, PyObject *args)
return Py_BuildValue("i",0);
}
static PyObject*
py_bndry_spreadrate(PyObject *self, PyObject *args)
{
int n;
if (!PyArg_ParseTuple(args, "i:bndry_spreadrate", &n))
return NULL;
double v = bndry_spreadrate(n);
return Py_BuildValue("d",v);
}
static PyObject*
py_bndry_setspreadrate(PyObject *self, PyObject *args)
{
int n;
double v;
if (!PyArg_ParseTuple(args, "id:bndry_setspreadrate", &n, &v))
return NULL;
int iok = bndry_setspreadrate(n, v);
if (iok < 0) return reportError(iok);
return Py_BuildValue("i",0);
}
static PyObject*
py_bndry_mdot(PyObject *self, PyObject *args)
{
@ -124,6 +146,8 @@ static PyMethodDef ct_methods[] = {
{"bndry_setxin", py_bndry_setxin, METH_VARARGS},
{"bndry_setxinbyname", py_bndry_setxinbyname, METH_VARARGS},
{"bndry_settemperature", py_bndry_settemperature, METH_VARARGS},
{"bndry_setspreadrate", py_bndry_setspreadrate, METH_VARARGS},
{"bndry_spreadrate", py_bndry_spreadrate, METH_VARARGS},
{"bndry_new", py_bndry_new, METH_VARARGS},
{"bndry_del", py_bndry_del, METH_VARARGS},
{"bndry_mdot", py_bndry_mdot, METH_VARARGS},

View file

@ -83,6 +83,11 @@ namespace Cantera {
needJacUpdate();
}
/// spreading rate
virtual double spreadRate() {
return m_V0;
}
/// Temperature [K].
doublereal temperature() {return m_temp;}

View file

@ -156,7 +156,8 @@ depends:
export:
@INSTALL@ -d $(export_dir)
if (test -d $(ct)); then rm -r -f $(ct); fi
cd $(export_dir); cvs export -D 1/01/2010 cantera-export-$(version)
cd $(export_dir); cvs export -D 1/01/2010 cantera
cd $(export-dir); mv cantera $(ct)
cd $(ct); rm -r -f Cantera/matlab/cantera/@Thermo
pack: export

2
configure vendored
View file

@ -150,7 +150,7 @@ LAPACK_FTN_STRING_LEN_AT_END='y'
CXX=${CXX:=g++}
# C++ compiler flags
CXXFLAGS=${CXXFLAGS:="-O0 -Wall"}
CXXFLAGS=${CXXFLAGS:="-O2 -Wall"}
# the C++ flags required for linking
#LCXX_FLAGS=