*** empty log message ***
This commit is contained in:
parent
754d098884
commit
9b779faab9
6 changed files with 585 additions and 180 deletions
162
Cantera/python/examples/catcomb.py
Normal file
162
Cantera/python/examples/catcomb.py
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
# CATCOMB -- Catalytic combustion on platinum.
|
||||
#
|
||||
# This script solves a catalytic combustion problem. A stagnation flow
|
||||
# is set up, with a gas inlet 10 cm from a platinum surface at 900
|
||||
# K. The lean, premixed methane/air mixture enters at ~ 6 cm/s (0.06
|
||||
# kg/m2/s), and burns catalytically on the platinum surface. Gas-phase
|
||||
# chemistry is included too, and has some effect very near the
|
||||
# surface.
|
||||
#
|
||||
# The catalytic combustion mechanism is from Deutschman et al., 26th
|
||||
# Symp. (Intl.) on Combustion,1996 pp. 1747-1754
|
||||
#
|
||||
# On a Mac G4, this example takes about 20 sec.
|
||||
#
|
||||
|
||||
from Cantera import *
|
||||
from Cantera.OneD import *
|
||||
import math
|
||||
|
||||
###############################################################
|
||||
#
|
||||
# Parameter values are collected here to make it easier to modify
|
||||
# them
|
||||
|
||||
p = OneAtm # pressure
|
||||
tinlet = 300.0 # inlet temperature
|
||||
tsurf = 900.0 # surface temperature
|
||||
mdot = 0.06 # kg/m^2/s
|
||||
|
||||
transport = 'Mix' # transport model
|
||||
|
||||
|
||||
# We will solve first for a hydrogen/air case to
|
||||
# use as the initial estimate for the methane/air case
|
||||
|
||||
# composition of the inlet premixed gas for the hydrogen/air case
|
||||
comp1 = 'H2:0.05, O2:0.21, N2:0.78, AR:0.01'
|
||||
|
||||
# composition of the inlet premixed gas for the methane/air case
|
||||
comp2 = 'CH4:0.095, O2:0.21, N2:0.78, AR:0.01'
|
||||
|
||||
# the initial grid, in meters. The inlet/surface separation is 10 cm.
|
||||
initial_grid = [0.0, 0.02, 0.04, 0.06, 0.08, 0.1] # m
|
||||
|
||||
|
||||
# numerical parameters
|
||||
tol_ss = [1.0e-5, 1.0e-9] # [rtol, atol] for steady-state problem
|
||||
tol_ts = [1.0e-4, 1.0e-9] # [rtol, atol] for time stepping
|
||||
|
||||
loglevel = 1 # amount of diagnostic output
|
||||
# (0 to 5)
|
||||
|
||||
refine_grid = 1 # 1 to enable refinement, 0 to
|
||||
# disable
|
||||
|
||||
################ create the gas object ########################
|
||||
#
|
||||
# This object will be used to evaluate all thermodynamic, kinetic,
|
||||
# and transport properties
|
||||
#
|
||||
# The gas phase will be taken from the definition of phase 'gas' in
|
||||
# input file 'ptcombust.cti,' which is a stripped-down version of
|
||||
# GRI-Mech 3.0.
|
||||
gas = importPhase('ptcombust.cti','gas')
|
||||
gas.setState_TPX(tinlet, p, comp1)
|
||||
|
||||
|
||||
################ create the interface object ##################
|
||||
#
|
||||
# This object will be used to evaluate all surface chemical production
|
||||
# rates. It will be created from the interface definition 'Pt_surf'
|
||||
# in input file 'ptcombust.cti,' which implements the reaction
|
||||
# mechanism of Deutschmann et al., 1995 for catalytic combustion on
|
||||
# platinum.
|
||||
#
|
||||
surf_phase = importInterface('ptcombust.cti','Pt_surf', [gas])
|
||||
surf_phase.setTemperature(tsurf)
|
||||
|
||||
|
||||
# integrate the coverage equations in time for 1 s, holding the gas
|
||||
# composition fixed to generate a good starting estimate for the
|
||||
# coverages.
|
||||
surf_phase.advanceCoverages(1.0)
|
||||
|
||||
sim = StagnationFlow(gas = gas, surfchem = surf_phase,
|
||||
grid = initial_grid)
|
||||
|
||||
sim.inlet.set(mdot = mdot, T = tinlet, X = comp1)
|
||||
sim.surface.set(T = tsurf)
|
||||
|
||||
sim.set(tol = tol_ss, tol_time = tol_ts)
|
||||
|
||||
sim.init()
|
||||
sim.showSolution()
|
||||
|
||||
# start with the energy equation on
|
||||
sim.set(energy = 'on')
|
||||
|
||||
# disable the surface coverage equations, and turn off all gas and
|
||||
# surface chemistry
|
||||
sim.surface.setCoverageEqs('off')
|
||||
surf_phase.setMultiplier(0.0);
|
||||
gas.setMultiplier(0.0);
|
||||
|
||||
# solve the problem, refining the grid if needed
|
||||
sim.solve(loglevel, refine_grid)
|
||||
|
||||
# now turn on the surface coverage equations, and turn the
|
||||
# chemistry on slowly
|
||||
sim.surface.setCoverageEqs('on')
|
||||
for iter in range(6):
|
||||
mult = math.pow(10.0,(iter - 5));
|
||||
surf_phase.setMultiplier(mult);
|
||||
gas.setMultiplier(mult);
|
||||
print 'Multiplier = ',mult
|
||||
sim.solve(loglevel, refine_grid);
|
||||
|
||||
# At this point, we should have the solution for the hydrogen/air
|
||||
# problem.
|
||||
sim.showSolution()
|
||||
|
||||
#Now switch the inlet to the methane/air composition.
|
||||
sim.inlet.set(X = comp2)
|
||||
|
||||
# set more stringent grid refinement criteria
|
||||
sim.setRefineCriteria(100.0, 0.15, 0.2, 0.0)
|
||||
|
||||
# solve the problem for the final time
|
||||
sim.solve(loglevel, refine_grid)
|
||||
|
||||
# show the solution
|
||||
sim.showSolution()
|
||||
|
||||
# save the solution in XML format. The 'restore' method can be used to restart
|
||||
# a simulation from a solution stored in this form.
|
||||
sim.save("catcomb.xml", "soln1")
|
||||
|
||||
# save selected solution components in a CSV file for plotting in
|
||||
# Excel or MATLAB.
|
||||
|
||||
z = sim.flow.grid()
|
||||
T = sim.T()
|
||||
u = sim.u()
|
||||
V = sim.V()
|
||||
f = open('catcomb.csv','w')
|
||||
writeCSV(f, ['z (m)', 'u (m/s)', 'V (1/s)', 'T (K)']
|
||||
+ list(gas.speciesNames()))
|
||||
for n in range(sim.flow.nPoints()):
|
||||
sim.setGasState(n)
|
||||
writeCSV(f, [z[n], u[n], V[n], T[n]]+list(gas.moleFractions()))
|
||||
|
||||
# write the surface coverages to the CSV file
|
||||
cov = sim.coverages()
|
||||
names = surf_phase.speciesNames()
|
||||
for n in range(len(names)):
|
||||
writeCSV(f, [names[n], cov[n]])
|
||||
|
||||
f.close()
|
||||
|
||||
print 'solution saved to catcomb.csv'
|
||||
|
||||
sim.showStats()
|
||||
49
Cantera/python/examples/diamond.py
Normal file
49
Cantera/python/examples/diamond.py
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#
|
||||
# A CVD example. This example computes the growth rate of a diamond film according to
|
||||
# a simplified version of a particular published growth mechanism (see file diamond.cti
|
||||
# for details). Only the surface coverage equations are solved here; the gas composition
|
||||
# is fixed. (For an example of coupled gas-phase and surface, see catcomb.py.)
|
||||
#
|
||||
# Atomic hydrogen plays an important role in diamond CVD, and this
|
||||
# example computes the growth rate and surface coverages as a function
|
||||
# of [H] at the surface for fixed temperature and [CH3].
|
||||
|
||||
from Cantera import *
|
||||
import math
|
||||
|
||||
print '\n\b****** CVD Diamond Example ******\n'
|
||||
|
||||
# import the models for the gas and bulk diamond
|
||||
g, dbulk = importPhases('diamond.cti',['gas','diamond'])
|
||||
|
||||
# import the model for the diamond (100) surface
|
||||
d = importInterface('diamond.cti','diamond_100',phases = [g, dbulk])
|
||||
|
||||
ns = d.nSpecies()
|
||||
mw = dbulk.molarMasses()[0]
|
||||
|
||||
t = 1200.0
|
||||
x = g.moleFractions()
|
||||
p = 20.0*OneAtm/760.0 # 20 Torr
|
||||
g.setState_TPX(t, p, x)
|
||||
|
||||
ih = g.speciesIndex('H')
|
||||
|
||||
xh0 = x[ih]
|
||||
f = open('diamond.csv','w')
|
||||
writeCSV(f, ['H mole Fraction', 'Growth Rate (microns/hour)']+d.speciesNames())
|
||||
for n in range(20):
|
||||
x[ih] /= 1.4
|
||||
g.setState_TPX(t, p, x)
|
||||
d.advanceCoverages(10.0) # iintegrate the coverages to steady state
|
||||
carbon_dot = d.netProductionRates(phase = dbulk)[0]
|
||||
mdot = mw*carbon_dot
|
||||
rate = mdot/dbulk.density()
|
||||
writeCSV(f,[x[ih],rate*1.0e6*3600.0]+list(d.coverages()))
|
||||
f.close()
|
||||
|
||||
print 'H concentration, growth rate, and surface coverages written to file diamond.csv'
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,79 +1,85 @@
|
|||
########################################################
|
||||
#
|
||||
# A burner-stabilized hydrogen/oxygen flame
|
||||
# FLAME1 - A burner-stabilized flat flame
|
||||
#
|
||||
########################################################
|
||||
# This script simulates a burner-stablized lean hydrogen-oxygen flame
|
||||
# at low pressure.
|
||||
#
|
||||
from Cantera import *
|
||||
from Cantera.OneD import *
|
||||
|
||||
# note that SI units (m, kg, J, kmol) are used, not cgs units.
|
||||
import os
|
||||
from Cantera import units
|
||||
from Cantera.flame import *
|
||||
################################################################
|
||||
#
|
||||
# parameter values
|
||||
#
|
||||
p = 0.05*OneAtm # pressure
|
||||
tburner = 373.0 # burner temperature
|
||||
mdot = 0.06 # kg/m^2/s
|
||||
|
||||
gas = IdealGasMix(src = 'h2o2.cti')
|
||||
rxnmech = 'h2o2.cti' # reaction mechanism file
|
||||
comp = 'H2:1.8, O2:1, AR:7' # premixed gas composition
|
||||
|
||||
# create a burner-stabilized flame in the domain z = 0 to z = 20 cm,
|
||||
# define the fuel to be pure hydrogen, and the oxidizer to be
|
||||
# oxygen diluted in argon.
|
||||
# The solution domain is chosen to be 50 cm, and a point very near the
|
||||
# downstream boundary is added to help with the zero-gradient boundary
|
||||
# condition at this boundary.
|
||||
initial_grid = [0.0, 0.02, 0.04, 0.06, 0.08, 0.1,
|
||||
0.15, 0.2, 0.4, 0.49, 0.5] # m
|
||||
|
||||
flame = BurnerFlame(
|
||||
domain = (0, 0.4),
|
||||
fuel = 'H2:1',
|
||||
oxidizer = 'O2:1, AR:7',
|
||||
gas = gas,
|
||||
grid = [0, 0.02, 0.04, 0.06, 0.08, 0.1, 0.15, 0.2, 0.49, 0.5]
|
||||
)
|
||||
tol_ss = [1.0e-5, 1.0e-13] # [rtol atol] for steady-state
|
||||
# problem
|
||||
tol_ts = [1.0e-4, 1.0e-9] # [rtol atol] for time stepping
|
||||
|
||||
# Set some parameters.
|
||||
# mdot -- mass flow rate in kg/m^2/s
|
||||
# T0 -- burner temperature
|
||||
# pressure -- P in pascals
|
||||
# tol -- (relative, absolute)
|
||||
# timesteps -- ( [sequence of number of steps], initial step size )
|
||||
# refine -- (max size ratio between adj cells, slope parameter,
|
||||
# curvature parameter)
|
||||
# jac_age -- (steady age, transient age)
|
||||
|
||||
flame.set(mdot = 0.04,
|
||||
equiv_ratio = 0.9,
|
||||
T_burner = 373.0,
|
||||
pressure = 0.05 * units.atm,
|
||||
tol = (1.e-5, 1.e-12),
|
||||
timesteps = ([1,2,5,10,20], 1.e-5),
|
||||
refine = (2.0, 0.8, 0.9),
|
||||
jac_age = (20, 10),
|
||||
)
|
||||
loglevel = 1 # amount of diagnostic output (0
|
||||
# to 5)
|
||||
|
||||
refine_grid = 1 # 1 to enable refinement, 0 to
|
||||
# disable
|
||||
|
||||
|
||||
# if you want to start from a previously saved solution, uncomment
|
||||
# this line and modify as necessary
|
||||
#flame.restore(src = 'h2o2_flame1.xml', solution = 'energy_1')
|
||||
################ create the gas object ########################
|
||||
#
|
||||
# This object will be used to evaluate all thermodynamic, kinetic,
|
||||
# and transport properties
|
||||
#
|
||||
gas = IdealGasMix(rxnmech)
|
||||
|
||||
# set its state to that of the unburned gas at the burner
|
||||
gas.setState_TPX(tburner, p, comp)
|
||||
|
||||
f = BurnerFlame(gas = gas, grid = initial_grid)
|
||||
|
||||
# set the properties at the burner
|
||||
f.burner.set(massflux = mdot, mole_fractions = comp, temperature = tburner)
|
||||
|
||||
f.set(tol = tol_ss, tol_time = tol_ts)
|
||||
f.setMaxJacAge(5, 10)
|
||||
f.set(energy = 'off')
|
||||
f.init()
|
||||
f.showSolution()
|
||||
|
||||
f.solve(loglevel, refine_grid)
|
||||
|
||||
f.setRefineCriteria(ratio = 200.0, slope = 0.05, curve = 0.1)
|
||||
f.set(energy = 'on')
|
||||
f.solve(loglevel,refine_grid)
|
||||
|
||||
f.save('flame1.xml')
|
||||
f.showSolution()
|
||||
|
||||
|
||||
# turn the energy equation off (default)
|
||||
flame.set(energy = 'off')
|
||||
# write the velocity, temperature, and mole fractions to a CSV file
|
||||
z = f.flame.grid()
|
||||
T = f.T()
|
||||
u = f.u()
|
||||
V = f.V()
|
||||
fcsv = open('flame1.csv','w')
|
||||
writeCSV(fcsv, ['z (m)', 'u (m/s)', 'V (1/s)', 'T (K)']
|
||||
+ list(gas.speciesNames()))
|
||||
for n in range(f.flame.nPoints()):
|
||||
f.setGasState(n)
|
||||
writeCSV(fcsv, [z[n], u[n], V[n], T[n]]+list(gas.moleFractions()))
|
||||
fcsv.close()
|
||||
|
||||
# solve the flame, with output level 1
|
||||
flame.solve(1)
|
||||
print 'solution saved to flame1.csv'
|
||||
|
||||
# save the solution
|
||||
flame.save('no_energy','solution with the energy equation disabled',
|
||||
'h2o2_flame1.xml')
|
||||
f.showStats()
|
||||
|
||||
# turn the energy equation on, and change the grid refinement parameters
|
||||
flame.set(energy = 'on', refine = (2.0, 0.05, 0.1))
|
||||
|
||||
# solve it again
|
||||
flame.solve(1)
|
||||
|
||||
# save it to the same file, but with a different solution id.
|
||||
flame.save('energy','solution with the energy equation enabled',
|
||||
'h2o2_flame1.xml')
|
||||
|
||||
# write plot files
|
||||
flame.plot(plotfile = 'flame1.dat', title = 'H2/O2 flame', fmt = 'TECPLOT')
|
||||
flame.plot(plotfile = 'flame1.csv', title = 'H2/O2 flame', fmt = 'EXCEL')
|
||||
print ' TECPLOT file flame1.dat and Excel CSV file flame1.csv written'
|
||||
print ' Directory: '+os.getcwd()
|
||||
|
||||
# show statistics -- number of Jacobians, etc.
|
||||
flame.showStatistics()
|
||||
|
|
|
|||
|
|
@ -1,49 +1,89 @@
|
|||
#
|
||||
# rich methane/air flame
|
||||
# FLAME1 - A burner-stabilized flat flame
|
||||
#
|
||||
import os
|
||||
from Cantera.flame import *
|
||||
from Cantera import units
|
||||
#from Cantera.gases import H_O_AR
|
||||
# This script simulates a burner-stablized lean hydrogen-oxygen flame
|
||||
# at low pressure.
|
||||
#
|
||||
from Cantera import *
|
||||
from Cantera.OneD import *
|
||||
|
||||
################################################################
|
||||
#
|
||||
# parameter values
|
||||
#
|
||||
p = OneAtm # pressure
|
||||
tburner = 373.7 # burner temperature
|
||||
mdot = 0.04 # kg/m^2/s
|
||||
|
||||
comp = 'CH4:0.65, O2:1, N2:3.76' # premixed gas composition
|
||||
|
||||
# The solution domain is chosen to be 1 cm, and a point very near the
|
||||
# downstream boundary is added to help with the zero-gradient boundary
|
||||
# condition at this boundary.
|
||||
initial_grid = [0.0, 0.0025, 0.005, 0.0075, 0.0099, 0.01] # m
|
||||
|
||||
tol_ss = [1.0e-5, 1.0e-9] # [rtol atol] for steady-state
|
||||
# problem
|
||||
tol_ts = [1.0e-5, 1.0e-4] # [rtol atol] for time stepping
|
||||
|
||||
loglevel = 1 # amount of diagnostic output (0
|
||||
# to 5)
|
||||
|
||||
refine_grid = 1 # 1 to enable refinement, 0 to
|
||||
# disable
|
||||
|
||||
|
||||
gas = GRI30(transport='Mix')
|
||||
################ create the gas object ########################
|
||||
#
|
||||
# This object will be used to evaluate all thermodynamic, kinetic,
|
||||
# and transport properties
|
||||
#
|
||||
gas = GRI30('Mix')
|
||||
|
||||
flame = BurnerFlame(
|
||||
domain = (0, 0.01),
|
||||
fuel = 'CH4:1',
|
||||
oxidizer = 'O2:1, N2:3.76',
|
||||
gas = gas,
|
||||
grid = [0.0, 0.0025, 0.005, 0.0075, 0.0099, 0.01]
|
||||
)
|
||||
# set its state to that of the unburned gas at the burner
|
||||
gas.setState_TPX(tburner, p, comp)
|
||||
|
||||
f = BurnerFlame(gas = gas, grid = initial_grid)
|
||||
|
||||
# set the properties at the burner
|
||||
f.burner.set(massflux = mdot, mole_fractions = comp, temperature = tburner)
|
||||
|
||||
f.set(tol = tol_ss, tol_time = tol_ts)
|
||||
f.showSolution()
|
||||
|
||||
f.set(energy = 'off')
|
||||
f.setRefineCriteria(ratio = 10.0, slope = 1, curve = 1)
|
||||
f.setMaxJacAge(50, 50)
|
||||
f.setTimeStep(1.0e-5, [1, 2, 5, 10, 20])
|
||||
|
||||
f.solve(loglevel,refine_grid)
|
||||
f.save('ch4_flame1.xml','no_energy',
|
||||
'solution with the energy equation disabled')
|
||||
|
||||
f.set(energy = 'on')
|
||||
f.setRefineCriteria(ratio = 3.0, slope = 0.1, curve = 0.2)
|
||||
f.solve(loglevel,refine_grid)
|
||||
f.save('ch4_flame1.xml','energy',
|
||||
'solution with the energy equation enabled')
|
||||
|
||||
# write the velocity, temperature, and mole fractions to a CSV file
|
||||
z = f.flame.grid()
|
||||
T = f.T()
|
||||
u = f.u()
|
||||
V = f.V()
|
||||
fcsv = open('flame2.csv','w')
|
||||
writeCSV(fcsv, ['z (m)', 'u (m/s)', 'V (1/s)', 'T (K)']
|
||||
+ list(gas.speciesNames()))
|
||||
for n in range(f.flame.nPoints()):
|
||||
f.setGasState(n)
|
||||
writeCSV(fcsv, [z[n], u[n], V[n], T[n]]+list(gas.moleFractions()))
|
||||
fcsv.close()
|
||||
|
||||
print 'solution saved to flame2.csv'
|
||||
|
||||
f.showStats()
|
||||
|
||||
flame.set(mdot = 0.04,
|
||||
equiv_ratio = 1.3,
|
||||
T_burner = 373.7,
|
||||
pressure = 1.0 * units.atm,
|
||||
tol = (1.e-4, 1.e-9),
|
||||
rtol = (1.e-5, 1.e-5),
|
||||
timesteps = ([1,2,5,10,20], 1.e-5),
|
||||
refine = (10.0, 1, 1),
|
||||
jac_age = (50, 50),
|
||||
nsteps = [1,2,5,10,20]
|
||||
)
|
||||
|
||||
flame.set(energy = 'off')
|
||||
flame.solve(1)
|
||||
flame.save('no_energy','solution with the energy equation disabled',
|
||||
'ch4_flame1.xml')
|
||||
|
||||
flame.set(energy = 'on', refine = (3.0, 0.1, 0.2))
|
||||
flame.solve(1)
|
||||
|
||||
flame.save('energy','solution with the energy equation enabled',
|
||||
'ch4_flame1.xml')
|
||||
|
||||
# write plot files
|
||||
flame.plot(plotfile = 'flame2.dat', title = 'methane/air flame',
|
||||
fmt = 'TECPLOT')
|
||||
flame.plot(plotfile = 'flame2.csv', fmt = 'EXCEL')
|
||||
print ' Solution written to TECPLOT file flame2.dat and Excel CSV file flame2.csv'
|
||||
print ' Directory: '+os.getcwd()
|
||||
flame.showStatistics()
|
||||
|
|
|
|||
121
Cantera/python/examples/npflame1.py
Normal file
121
Cantera/python/examples/npflame1.py
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
# NPFLAME1 - A nonpremixed counterflow flame.
|
||||
#
|
||||
# This script computes an atmospheric-pressure ethane/air
|
||||
# counterflow flame using GRI-Mech 3.0.
|
||||
# Run time on a Mac G4: ~ 5 minutes
|
||||
#
|
||||
from Cantera import *
|
||||
from Cantera.OneD import *
|
||||
|
||||
##################################################################
|
||||
# parameter values
|
||||
#
|
||||
# These are grouped here to simplify changing flame conditions
|
||||
|
||||
p = OneAtm # pressure
|
||||
tin_f = 300.0 # fuel inlet temperature
|
||||
tin_o = 300.0 # oxidizer inlet temperature
|
||||
mdot_o = 0.72 # kg/m^2/s
|
||||
mdot_f = 0.24 # kg/m^2/s
|
||||
|
||||
comp_o = 'O2:0.21, N2:0.78, AR:0.01'; # air composition
|
||||
comp_f = 'C2H6:1'; # fuel composition
|
||||
|
||||
# distance between inlets is 2 cm; start with an evenly-spaced 6-point
|
||||
# grid
|
||||
initial_grid = 0.02*array([0.0, 0.2, 0.4, 0.6, 0.8, 1.0],'d')
|
||||
|
||||
|
||||
tol_ss = [1.0e-5, 1.0e-9] # [rtol, atol] for steady-state
|
||||
# problem
|
||||
tol_ts = [1.0e-3, 1.0e-9] # [rtol, atol] for time stepping
|
||||
|
||||
loglevel = 1 # amount of diagnostic output (0
|
||||
# to 5)
|
||||
|
||||
refine_grid = 1 # 1 to enable refinement, 0 to
|
||||
# disable
|
||||
|
||||
|
||||
################ create the gas object ########################
|
||||
#
|
||||
# This object will be used to evaluate all thermodynamic, kinetic,
|
||||
# and transport properties
|
||||
#
|
||||
|
||||
# Here we use GRI-Mech 3.0 with mixture-averaged transport
|
||||
# properties. To use your own mechanism, use function
|
||||
# IdealGasMix('mech.cti') to read a mechanism in Cantera format. If
|
||||
# you need to convert from Chemkin format, use the ck2cti utility
|
||||
# program first.
|
||||
gas = GRI30('Mix')
|
||||
|
||||
# create an object representing the counterflow flame configuration,
|
||||
# which consists of a fuel inlet on the left, the flow in the middle,
|
||||
# and the oxidizer inlet on the right. Class CounterFlame creates this
|
||||
# configuration.
|
||||
|
||||
f = CounterFlame(gas = gas, grid = initial_grid)
|
||||
|
||||
# Set the state of the two inlets
|
||||
|
||||
f.fuel_inlet.set(massflux = mdot_f,
|
||||
mole_fractions = comp_f,
|
||||
temperature = tin_f)
|
||||
|
||||
f.oxidizer_inlet.set(massflux = mdot_o,
|
||||
mole_fractions = comp_o,
|
||||
temperature = tin_o)
|
||||
|
||||
# set the error tolerances
|
||||
f.set(tol = tol_ss, tol_time = tol_ts)
|
||||
|
||||
# construct the initial solution estimate. To do so, it is necessary
|
||||
# to specify the fuel species. If a fuel mixture is being used,
|
||||
# specify a representative species here for the purpose of
|
||||
# constructing an initial guess.
|
||||
f.init(fuel = 'C2H6')
|
||||
|
||||
# show the starting estimate
|
||||
f.showSolution()
|
||||
|
||||
# First disable the energy equation and solve the problem without
|
||||
# refining the grid
|
||||
f.set(energy = 'off')
|
||||
f.solve(loglevel, 0)
|
||||
|
||||
# Now specify grid refinement criteria, turn on the energy equation,
|
||||
# and solve the problem again. The ratio parameter controls the
|
||||
# maximum size ratio between adjacent cells; slope and curve should be
|
||||
# between 0 and 1 and control adding points in regions of high
|
||||
# gradients and high curvature, respectively. If prune > 0, points
|
||||
# will be removed if the relative slope and curvature for all
|
||||
# components fall below the prune level. Set prune < min(slope,
|
||||
# curve), or to zero to disable removing grid points.
|
||||
f.setRefineCriteria(ratio = 200.0, slope = 0.1, curve = 0.2, prune = 0.0)
|
||||
f.set(energy = 'on')
|
||||
f.solve(1)
|
||||
|
||||
# Save the solution
|
||||
f.save('npflame1.xml')
|
||||
|
||||
# write the velocity, temperature, and mole fractions to a CSV file
|
||||
z = f.flame.grid()
|
||||
T = f.T()
|
||||
u = f.u()
|
||||
V = f.V()
|
||||
fcsv = open('npflame1.csv','w')
|
||||
writeCSV(fcsv, ['z (m)', 'u (m/s)', 'V (1/s)', 'T (K)']
|
||||
+ list(gas.speciesNames()))
|
||||
for n in range(f.flame.nPoints()):
|
||||
f.setGasState(n)
|
||||
writeCSV(fcsv, [z[n], u[n], V[n], T[n]]+list(gas.moleFractions()))
|
||||
fcsv.close()
|
||||
|
||||
print 'solution saved to npflame1.csv'
|
||||
|
||||
f.showSolution()
|
||||
f.showStats()
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,89 +1,116 @@
|
|||
"""
|
||||
#
|
||||
# STFLAME1 - A detached flat flame stabilized at a stagnation point
|
||||
#
|
||||
|
||||
A hydrogen/oxygen flame stabilized in an axisymmetric stagnation
|
||||
flow.
|
||||
# This script simulates a lean hydrogen-oxygen flame stabilized in
|
||||
# a strained flowfield at an axisymmetric stagnation point on a
|
||||
# non-reacting surface. The solution begins with a flame attached
|
||||
# to the inlet (burner), and the mass flow rate is progressively
|
||||
# increased, causing the flame to detach and move closer to the
|
||||
# surface. This example illustrates use of the new 'prune' grid
|
||||
# refinement parameter, which allows grid points to be removed if
|
||||
# they are no longer required to resolve the solution. This is
|
||||
# important here, since the flamefront moves as the mass flowrate
|
||||
# is increased. Without using 'prune', a large number of grid
|
||||
# points would be concentrated upsteam of the flame, where the
|
||||
# flamefront had been previously. (To see this, try setting prune
|
||||
# to zero.)
|
||||
|
||||
"""
|
||||
from Cantera import *
|
||||
from Cantera.OneD import *
|
||||
|
||||
from Cantera import units
|
||||
from Cantera.flame import *
|
||||
################################################################
|
||||
#
|
||||
# parameter values
|
||||
#
|
||||
p = 0.05*OneAtm # pressure
|
||||
tburner = 373.0 # burner temperature
|
||||
tsurf = 600.0
|
||||
|
||||
# Import the hydrogen/oxygen reaction mechanism
|
||||
# The input file is in directory 'data/inputs'.
|
||||
# each mdot value will be solved to convergence, with grid refinement,
|
||||
# and then that solution will be used for the next mdot
|
||||
mdot = [0.06, 0.07, 0.08, 0.09, 0.1, 0.11, 0.12] # kg/m^2/s
|
||||
|
||||
gas = IdealGasMix('h2o2.cti')
|
||||
rxnmech = 'h2o2.cti' # reaction mechanism file
|
||||
comp = 'H2:1.8, O2:1, AR:7' # premixed gas composition
|
||||
|
||||
# The solution domain is chosen to be 50 cm, and a point very near the
|
||||
# downstream boundary is added to help with the zero-gradient boundary
|
||||
# condition at this boundary.
|
||||
initial_grid = [0.0, 0.02, 0.04, 0.06, 0.08, 0.1,
|
||||
0.15, 0.2] # m
|
||||
|
||||
tol_ss = [1.0e-5, 1.0e-13] # [rtol atol] for steady-state
|
||||
# problem
|
||||
tol_ts = [1.0e-4, 1.0e-9] # [rtol atol] for time stepping
|
||||
|
||||
loglevel = 1 # amount of diagnostic output (0
|
||||
# to 5)
|
||||
|
||||
refine_grid = 1 # 1 to enable refinement, 0 to
|
||||
# disable
|
||||
ratio = 5.0
|
||||
slope = 0.1
|
||||
curve = 0.2
|
||||
prune = 0.05
|
||||
|
||||
|
||||
# Create a stagnation-point flame in the domain z = 0 (the inlet) to z
|
||||
# = 20 cm (the surface). The fuel stream will be pure hydrogen,
|
||||
# and the oxidizer stream oxygen diluted in argon.
|
||||
|
||||
flame = StagnationFlame(
|
||||
domain = (0, 0.2),
|
||||
fuel = 'H2:1',
|
||||
oxidizer = 'O2:1, AR:7',
|
||||
gas = gas,
|
||||
grid = [0, 0.02, 0.04, 0.06, 0.08, 0.1, 0.15, 0.2] # initial grid
|
||||
)
|
||||
################ create the gas object ########################
|
||||
#
|
||||
# This object will be used to evaluate all thermodynamic, kinetic,
|
||||
# and transport properties
|
||||
#
|
||||
gas = IdealGasMix(rxnmech)
|
||||
|
||||
# set its state to that of the unburned gas at the burner
|
||||
gas.setState_TPX(tburner, p, comp)
|
||||
|
||||
# Create the stagnation flow object with a non-reactive surface. (To
|
||||
# make the surface reactive, supply a surface reaction mechanism. see
|
||||
# example catcomb.py for how to do this.)
|
||||
f = StagnationFlow(gas = gas, grid = initial_grid)
|
||||
|
||||
# set the properties at the inlet
|
||||
f.inlet.set(massflux = mdot[0], mole_fractions = comp, temperature = tburner)
|
||||
|
||||
# set the surface state
|
||||
f.surface.setTemperature(tsurf)
|
||||
|
||||
f.set(tol = tol_ss, tol_time = tol_ts)
|
||||
f.setMaxJacAge(5, 10)
|
||||
f.set(energy = 'off')
|
||||
f.init(products = 'equil') # assume adiabatic equilibrium products
|
||||
f.showSolution()
|
||||
|
||||
f.solve(loglevel, refine_grid)
|
||||
|
||||
f.setRefineCriteria(ratio = ratio, slope = slope,
|
||||
curve = curve, prune = prune)
|
||||
f.set(energy = 'on')
|
||||
|
||||
m = 0
|
||||
for md in mdot:
|
||||
f.inlet.set(mdot = md)
|
||||
f.solve(loglevel,refine_grid)
|
||||
m = m + 1
|
||||
f.save('stflame1.xml','mdot'+`m`,'mdot = '+`md`+' kg/m2/s')
|
||||
|
||||
|
||||
# Set some parameters.
|
||||
# mdot -- mass flow rate in kg/m^2/s
|
||||
# T_burner -- burner temperature
|
||||
# T_surface -- surface temperature
|
||||
# pressure -- P in pascals
|
||||
# tol -- (relative, absolute)
|
||||
# timesteps -- ( [sequence of number of steps], initial step size )
|
||||
# refine -- (max size ratio between adj cells, slope parameter,
|
||||
# curvature parameter)
|
||||
# jac_age -- (steady age, transient age)
|
||||
# write the velocity, temperature, and mole fractions to a CSV file
|
||||
z = f.flow.grid()
|
||||
T = f.T()
|
||||
u = f.u()
|
||||
V = f.V()
|
||||
fcsv = open('stflame1_'+`m`+'.csv','w')
|
||||
writeCSV(fcsv, ['z (m)', 'u (m/s)', 'V (1/s)', 'T (K)']
|
||||
+ list(gas.speciesNames()))
|
||||
for n in range(f.flow.nPoints()):
|
||||
f.setGasState(n)
|
||||
writeCSV(fcsv, [z[n], u[n], V[n], T[n]]+list(gas.moleFractions()))
|
||||
fcsv.close()
|
||||
|
||||
flame.set(mdot = 0.1,
|
||||
equiv_ratio = 1.2,
|
||||
T_burner = 373.0,
|
||||
T_surface = 600.0,
|
||||
pressure = 0.05 * units.atm,
|
||||
tol = (1.e-7, 1.e-9),
|
||||
timesteps = ([1,2,5,10], 1.e-5),
|
||||
refine = (2.0, 0.5, 0.5),
|
||||
jac_age = (20, 10),
|
||||
)
|
||||
print 'solution saved to flame1.csv'
|
||||
|
||||
|
||||
# if you want to start from a previously saved solution, uncomment
|
||||
# this line and modify as necessary
|
||||
# flame.restore(src = 'h2o2_flame1.xml', solution = 'energy_1')
|
||||
|
||||
# turn the energy equation off (default)
|
||||
flame.set(energy = 'off')
|
||||
flame.show()
|
||||
|
||||
# solve the flame, with output level 1
|
||||
flame.solve(1)
|
||||
flame.show()
|
||||
|
||||
# save the solution
|
||||
flame.save('no_energy','solution with the energy equation disabled',
|
||||
'h2o2_stflame1.xml')
|
||||
|
||||
# turn the energy equation on, and change the grid refinement parameters
|
||||
flame.set(energy = 'on', refine = (2.0, 0.1, 0.2))
|
||||
|
||||
# solve it again
|
||||
flame.solve(1)
|
||||
|
||||
# save it to the same file, but with a different solution id.
|
||||
flame.save('energy','solution with the energy equation enabled',
|
||||
'h2o2_stflame1.xml')
|
||||
|
||||
# write a TECPLOT plot file
|
||||
flame.plot(plotfile = 'stflame1.dat', title = 'H2/O2 flame', fmt = 'TECPLOT')
|
||||
|
||||
# write an Excel CSV file
|
||||
flame.plot(plotfile = 'stflame1.csv', title = 'H2/O2 flame', fmt = 'EXCEL')
|
||||
|
||||
print 'TECPLOT file stflame1.dat and Excel CSV file stflame1.csv written'
|
||||
|
||||
# show statistics -- number of Jacobians, etc.
|
||||
flame.showStatistics()
|
||||
f.showStats()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue