def solve(self, phi, T, width, P): gas = ct.Solution('h2o2.xml') gas.TPX = T, ct.one_atm * P, {'H2': phi, 'O2': 0.5, 'AR': 1.5} sim = ct.BurnerFlame(gas=gas, width=width) sim.burner.mdot = gas.density * 0.15 sim.solve(loglevel=0, auto=True) self.assertGreater(sim.T[1], T)
def test_blowoff(self): gas = ct.Solution('h2o2.cti') gas.set_equivalence_ratio(0.4, 'H2', 'O2:1.0, AR:5') gas.TP = 300, ct.one_atm sim = ct.BurnerFlame(gas=gas, width=0.1) sim.burner.mdot = 1.2 sim.set_refine_criteria(ratio=3, slope=0.3, curve=0.5, prune=0) sim.solve(loglevel=0, auto=True) # nonreacting solution self.assertNear(sim.T[-1], sim.T[0], 1e-6) self.assertNear(sim.velocity[-1], sim.velocity[0], 1e-6) self.assertArrayNear(sim.Y[:, 0], sim.Y[:, -1], 1e-6, atol=1e-6)
def test_fixed_temp(self): gas = ct.Solution('h2o2.xml') gas.TPX = 400, 2 * ct.one_atm, {'H2': 0.7, 'O2': 0.5, 'AR': 1.5} sim = ct.BurnerFlame(gas=gas, width=0.05) sim.burner.mdot = gas.density * 0.15 sim.flame.set_fixed_temp_profile([0, 0.1, 0.9, 1], [400, 1100, 1100, 500]) sim.energy_enabled = False sim.solve(loglevel=0, refine_grid=True) self.assertNear(sim.T[0], 400) self.assertNear(sim.T[-1], 500) self.assertNear(max(sim.T), 1100)
def test_restart(self): gas = ct.Solution('h2o2.cti') gas.set_equivalence_ratio(0.4, 'H2', 'O2:1.0, AR:5') gas.TP = 300, ct.one_atm sim = ct.BurnerFlame(gas=gas, width=0.1) sim.burner.mdot = 1.2 sim.set_refine_criteria(ratio=3, slope=0.3, curve=0.5, prune=0) sim.solve(loglevel=0, auto=True) arr = sim.to_solution_array() sim.burner.mdot = 1.1 sim.set_initial_guess(data=arr) sim.solve(loglevel=0, auto=True) # Check continuity rhou = sim.burner.mdot for rhou_j in sim.density * sim.velocity: self.assertNear(rhou_j, rhou, 1e-4)
def setup(phi): # parameter values p = ct.one_atm # pressure tburner = 300.0 # burner temperature mdot = 1.2 # kg/m^2/s width = 0.05 # m gas = ct.Solution('h2o2.cti') # set state to that of the unburned gas at the burner gas.set_equivalence_ratio(phi, 'H2', 'O2:1.0, AR:5') gas.TP = tburner, p # Create the stagnation flow object with a non-reactive surface. sim = ct.BurnerFlame(gas=gas, width=width) # set the mass flow rate at the inlet sim.burner.mdot = mdot sim.set_refine_criteria(ratio=3, slope=0.16, curve=0.3, prune=0.1) return sim
Requires: cantera >= 2.5.0 """ import cantera as ct p = 0.05 * ct.one_atm tburner = 373.0 mdot = 0.06 reactants = 'H2:1.5, O2:1, AR:7' # premixed gas composition width = 0.5 # m loglevel = 1 # amount of diagnostic output (0 to 5) gas = ct.Solution('h2o2.yaml') gas.TPX = tburner, p, reactants f = ct.BurnerFlame(gas, width=width) f.burner.mdot = mdot f.set_refine_criteria(ratio=3.0, slope=0.05, curve=0.1) f.show_solution() f.transport_model = 'Mix' f.solve(loglevel, auto=True) f.save('h2_burner_flame.xml', 'mix', 'solution with mixture-averaged transport') f.transport_model = 'Multi' f.solve(loglevel) # don't use 'auto' on subsequent solves f.show_solution() f.save('h2_burner_flame.xml', 'multi', 'solution with multicomponent transport')
sensSpecies = 'CO' initial_grid = np.linspace(0.0, 0.03, 10) # m #initial_grid = np.linspace(0.0, 0.01805882, 10) # m tol_ss = [1.0e-5, 1.0e-13] # [rtol atol] for steady-state problem tol_ts = [1.0e-4, 1.0e-10] # [rtol atol] for time stepping loglevel = 1 # amount of diagnostic output (0 to 5) filename = 'C:\\Users\\HP USER\\Google Drive\\Burke Group\\Codes\\TMRP codes\\dooley\\chem' gas = ct.Solution(filename+'.cti') gas.TPX = tburner, p, reactants v=0.909 gas2=ct.Solution(filename+'.cti') gas2.TPX=300,p,reactants mdot=v*gas2.density #mdot=0.021 f = ct.BurnerFlame(gas, initial_grid) f.burner.mdot = mdot f.set_initial_guess() # read temperature vs. position data from a file. # The file is assumed to have one z, T pair per line, separated by a comma. #zloc, tvalues = np.genfromtxt('C:\\Users\\HP USER\\Google Drive\\Burke group\\codes\\paperFigs\\mf1p0_T_profile.csv', delimiter=',', comments='#').T #zloc, tvalues = np.genfromtxt('C:\\Users\\HP USER\\Desktop\\kevin\\t_profile_38torr.txt', delimiter=',', comments='#').T data=pd.read_csv('C:\\Users\\HP USER\\Google Drive\\Burke group\\codes\\paperFigs\\mf1p0_T_profile.csv',header=3) zloc=data['z'] tvalues=data['T'] zloc /= max(zloc) #print(tvalues)
p = 0.12 * ct.one_atm tburner = 300.0 reactants = 'AR:0.55, O2:0.2143, C2H2:0.2357, A4:0' # premixed gas composition grid = np.linspace(0, 0.09, 20) # m grid_points = len(grid) loglevel = 1 # amount of diagnostic output (0 to 5) # Create gas object gas = ct.Solution('abf_mech90torr.cti') gas.TPX = tburner, p, reactants mdot = 0.204 * gas.density # kg/(m^2*s) # Create flame object f = ct.BurnerFlame(gas, grid=grid) f.burner.mdot = mdot f.energy_enabled = False zloc, tvalues = get_temp_prof(t_distance_vals, temp_vals, points=grid_points) f.flame.set_fixed_temp_profile(zloc, tvalues) conc_grid, cvalues = get_conc_prof(c_distance_vals, concentration_vals, points=grid_points) f.X[gas.species_index('A4'), :] = cvalues f.set_refine_criteria(ratio=3.0, slope=0.05, curve=0.1) f.show_solution() f.transport_model = 'Mix' f.solve(loglevel, refine_grid=False) f.save('c2h2_o2_ar_burner_flame.xml', 'mix', 'solution with mixture-averaged transport')
loglevel = 1 # amount of diagnostic output (0 to 5) refine_grid = True # 'True' to enable refinement ################ create the gas object ######################## # # This object will be used to evaluate all thermodynamic, kinetic, and # transport properties. It is created with two transport managers, to enable # switching from mixture-averaged to multicomponent transport on the last # solution. gas = ct.Solution('gri30.xml', 'gri30_mix') # set its state to that of the unburned gas at the burner gas.TPX = tburner, p, comp # create the BurnerFlame object. f = ct.BurnerFlame(gas=gas, grid=initial_grid) # set the properties at the burner f.burner.mdot = mdot f.burner.X = comp f.burner.T = tburner # read in the fixed temperature profile [zloc, tvalues] = getTempData('tdata.dat') # set the temperature profile to the values read in f.flame.set_fixed_temp_profile(zloc, tvalues) f.flame.set_steady_tolerances(default=tol_ss) f.flame.set_transient_tolerances(default=tol_ts)
def burner_flame(gas,grid,mdot,data=pd.DataFrame(columns=['z','T']),kinetic_sens=0,physical_sens=0,observables=[],physical_params=['T','P'],energycon=False,soret=True): #when energycon is off treat flame as burner stabilized, with known T-profile simtype = 'burner flame' baseConditions=gas.TPX tol_ss = [1.0e-5, 1.0e-13] # [rtol atol] for steady-state problem tol_ts = [1.0e-4, 1.0e-10] # [rtol atol] for time stepping loglevel = 1 # amount of diagnostic output (0 to 5) f = ct.BurnerFlame(gas, width=grid) f.burner.mdot = mdot f.set_initial_guess() # read temperature vs. position data from a file. # The file is assumed to have one z, T pair per line, separated by a comma. if data.empty==False and energycon==False: zloc=data['z'] tvalues=data['T'] #zloc, tvalues = np.genfromtxt('C:\\Users\\HP USER\\Desktop\\kevin\\harrington_78torr_Tprofile_chemkin.txt', delimiter=',', comments='#').T #zloc, tvalues = np.genfromtxt('C:\\Users\\HP USER\\Desktop\\kevin\\t_profile_38torr.txt', delimiter=',', comments='#').T zloc /= max(zloc) #print(tvalues) f.flame.set_fixed_temp_profile(zloc, tvalues) #sets a fixed temperature profile for the flame simulation. May come from a measurement. Requires no energy conservation elif data.empty==False and energycon!='off': raise Exception('User has supplied fixed temperature dataset but energy conservation is not off. Remove dataset or turn energy conservation off') f.flame.set_steady_tolerances(default=tol_ss) #Set steady tolerances f.flame.set_transient_tolerances(default=tol_ts) #Set transient tolerances f.show_solution() f.energy_enabled = energycon #This must be set to false for a burner stabilized flame with known T-profile f.transport_model = 'Multi' #Sets to multicomponent transport for simulation. Needs to be set this way to use Soret effect f.set_max_jac_age(10, 10) #Age limits on Jacobian-leave as is for best results f.solve(loglevel, refine_grid=False) #Solve for initial estimate without grid refinement f.soret_enabled = soret #Enable Soret effect. Remember transport must be set to multi. Mix causes failure f.set_refine_criteria(ratio=2.0, slope=0.05, curve=0.5) #Establishes refinement criteria for grid #print('mixture-averaged flamespeed = ', f.u[0]) f.transport_model = 'Multi' #This block solves problem again with grid refinement on f.solve(loglevel, refine_grid=True) f.show_solution() print('multicomponent flamespeed = ', f.u[0]) #solution = f ##Begin section to calculate sensitivities dk = 0.010 solution = f.X if kinetic_sens==1 and bool(observables): #Calculate kinetic sensitivities sensIndex = [f.grid.tolist(),gas.reaction_equations(),observables] S = np.zeros((len(f.grid),gas.n_reactions,len(observables))) #print(solution.X[solution.flame.component_index(observables[0])-4,len(f.grid)-1]) #a=solution.X[solution.flame.component_index(observables[0])-4,len(f.grid)-1] for m in range(gas.n_reactions): gas.set_multiplier(1.0) gas.set_multiplier(1+dk,m) f.solve(loglevel=1,refine_grid=False) for i in np.arange(len(observables)): for k in np.arange(len(f.grid)): S[k,m,i]=f.X[f.flame.component_index(observables[i])-4,k]-solution[f.flame.component_index(observables[i])-4,k] #print(solution.X[solution.flame.component_index(observables[i])-4,k]) #print(f.X[f.flame.component_index(observables[i])-4,k]) S[k,m,i]=np.divide(S[k,m,i],solution[f.flame.component_index(observables[i])-4,k]) S[k,m,i]=np.divide(S[k,m,i],dk) if physical_sens==1 and bool(observables): #Calculate physical sensitivities gas.set_multiplier(1.0) psensIndex = [f.grid.tolist(),physical_params,observables] pS = np.zeros((len(f.grid),len(physical_params),len(observables))) for m in range(len(physical_params)): gas.TPX=baseConditions if physical_params[m]=='T': gas.TPX=baseConditions[0]+dk,baseConditions[1],baseConditions[2] elif physical_params[m]=='P': gas.TPX=baseConditions[0],baseConditions[1]+dk,baseConditions[2] f.solve(loglevel=1,refine_grid=False) for i in np.arange(len(observables)): for k in np.arange(len(f.grid)): pS[k,m,i] =np.log10(solution[f.flame.component_index(observables[i])-4,k])-np.log10(f.X[f.flame.component_index(observables[i])-4,k]) pS[k,m,i] = np.divide(pS[k,m,i],np.log10(dk)) elif kinetic_sens==1 and bool(observables)==False: raise Exception('Please supply a list of observables in order to run kinetic sensitivity analysis') elif physical_sens==1 and bool(observables)==False: raise Exception('Please supply a list of observables in order to run physical sensitivity analysis') gas.set_multiplier(1.0) gas.TP = baseConditions[0],baseConditions[1] f.solve(loglevel=1,refine_grid=False) solution=pd.DataFrame(columns=f.flame.component_names) #for i in f.flame.component_names: #solution[i]=f.solution(i) for i in np.arange(len(f.flame.component_names)): if i<=3: solution[f.flame.component_names[i]]=f.solution(i) else: solution[f.flame.component_names[i]]=f.X[i-4,:] if kinetic_sens==1 and bool(observables) and physical_sens!=1: results = model_data(simtype,kinetic_sens=S,Solution=solution,Index=sensIndex) return results elif physical_sens==1 and bool(observables) and kinetic_sens!=1: results = model_data(simtype,Solution=solution,pIndex=psensIndex,physical_sens=pS) return results elif kinetic_sens==1 and physical_sens==1 and bool(observables): results = model_data(simtype,Solution=solution,pIndex=psensIndex,Index=sensIndex,physical_sens=pS,kinetic_sens=S) return results elif kinetic_sens!=1 and physical_sens!=1: Index = [f.grid.tolist()] results = model_data(simtype,Solution=solution,Index=Index) return results else: print('Something went wrong with the parameters given. Kinetic and physical sens may be set to either 0 or 1, and require a list of observables')