flame_params['F'] = 'CH4' flame_params['p'] = 1. flame_params['a'] = 100. flame_params['phif'] = 'inf' flame_params['phio'] = 0. flame_params['tf'] = 300. flame_params['to'] = 300. case_name = None for a in strain: for phi in phif: flame_params['phio'] = 0. flame_params['phif'] = phi case_name = params2name(flame_params) counterflow_flame(strain_rate=a, phi_f=phi, phi_o=0., solution='{}.xml'.format(case_name)) for phi in phio: flame_params['phio'] = phi flame_params['phif'] = 'inf' case_name = params2name(flame_params) counterflow_flame(strain_rate=a, phi_f='inf', phi_o=phi, solution='{}.xml'.format(case_name)) flame_params['a'] = a
params['tres'] = tres_log for tmix_ratio in mix_res_ratio: tmix = tmix_ratio * tres params['tmix'] = tmix_ratio for phi in equiv_ratio: params['eqv'] = phi Z_fuel = equiv2Z(equiv_ratio_fuel) Z_pilot = equiv2Z(equiv_ratio_pilot) Z_fp = (Z_fuel * m_fuel + Z_pilot * m_pilot) / (m_fuel + m_pilot) m_air = air_flow_rate(Z_fp, equiv2Z(phi)) * (m_fuel + m_pilot) case = params2name(params) if os.path.isdir(case): os.chdir(case) # pasr namelist with open('pasr.nml', 'w') as nml: for line in lines_nml: line = re.sub('@ANRES@', '{:g}'.format(anres), line) line = re.sub('@MIXMODEL@', '{:g}'.format(mix_v), line) line = re.sub('@TRES@', '{:e}'.format(tres), line) line = re.sub('@TMIX@', '{:e}'.format(tmix), line) line = re.sub('@AIRRATE@', '{:g}'.format(m_air), line)
npts = 1000 a = 50 variance = [0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5] eqv_ratio = [0.8,0.9,1.0,1.1,1.2,1.3,1.4] flame_params = {} flame_params['F'] = 'CH4' flame_params['p'] = 1 flame_params['a'] = a flame_params['phif'] = 1.3 flame_params['phio'] = 0 flame_params['tf'] = 300 flame_params['to'] = 300 flame = params2name(flame_params) # read the species names from chem.inp, guarantee the sequence comp_names = [] spe_end = False with open('chem.inp','r') as f: for line in f: if line[:7] == 'SPECIES': while True: newline = f.readline()[:-1].split() if newline[0] == 'END': break else: comp_names.extend(newline) break comp_names.append('T')
def counterflow_flame(mech='gri30.xml', transport='Multi', flag_soret=True, flag_radiation=False, fuel={'CH4': 1}, oxy={ 'O2': 1, 'N2': 3.76 }, strain_rate=100., width=0.01, p=1., phi_f='inf', phi_o=0., tin_f=300., tin_o=300., solution=None): ################################################################################ # Create the gas object used to evaluate all thermodynamic, kinetic, and # transport properties. gas = ct.Solution(mech) phi_f = float(phi_f) if phi_f <= 1.: sys.exit('Equivalence ratio of fuel side {:g}'.format(phi_f)) if phi_o >= 1.: sys.exit('Equivalence ratio of oxidizer side {:g}'.format(phi_o)) # construct case name flame_params = {} flame_params['p'] = p flame_params['a'] = strain_rate flame_params['phif'] = phi_f flame_params['phio'] = phi_o flame_params['tf'] = tin_f flame_params['to'] = tin_o case_name = params2name(flame_params) p *= ct.one_atm # pressure ################################################################################ #fuel = { 'H2':1., 'N2':1. } # fuel composition #oxy = {'O2':1., 'N2':3.76} # air composition Z_element = ['C', 'H', 'O'] for e in Z_element: if e not in gas.element_names: Z_element.remove(e) # get stoichiometric coefficients element_nu = {'C': 2, 'O': -1, 'H': 0.5} o_fuel = 0. for k, v in fuel.items(): for e in gas.element_names: if e in element_nu.keys(): o_fuel += v * gas.n_atoms(k, e) * element_nu[e] o_oxy = 0. for k, v in oxy.items(): for e in gas.element_names: if e in element_nu.keys(): o_oxy += v * gas.n_atoms(k, e) * element_nu[e] stoich_nu = -o_fuel / o_oxy # composition for two streams comp_f = {} comp_o = {} for k in fuel.keys(): comp_f[k] = 0. comp_o[k] = 0. for k in oxy.keys(): comp_f[k] = 0. comp_o[k] = 0. for k, v in fuel.items(): comp_f[k] += v comp_o[k] += v * phi_o / stoich_nu for k, v in oxy.items(): comp_o[k] += v comp_f[k] += v * stoich_nu / phi_f # fuel and oxidizer streams have the same velocity u = strain_rate * width / 2. # get mass flow rate gas.TPX = tin_f, p, comp_o dens_o = gas.density mdot_o = u * dens_o gas.TPX = tin_o, p, comp_f dens_f = gas.density mdot_f = u * dens_f # kg/m^2/s # 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. f = ct.CounterflowDiffusionFlame(gas, width=width) if solution is not None: try: f.restore(solution, loglevel=0) except Exception as e: print(e, 'Start to solve from initialization') f.transport_model = transport # Set the state of the two inlets f.fuel_inlet.mdot = mdot_f f.fuel_inlet.X = comp_f f.fuel_inlet.T = tin_f f.oxidizer_inlet.mdot = mdot_o f.oxidizer_inlet.X = comp_o f.oxidizer_inlet.T = tin_o # Set the boundary emissivities f.set_boundary_emissivities(0.0, 0.0) # Turn radiation off f.radiation_enabled = False f.set_refine_criteria(ratio=2, slope=0.1, curve=0.1, prune=0.01) # Solve the problem try: f.solve(loglevel=0, auto=True) except Exception as e: print('Error: not converge for case:', e) return -1 if flag_radiation: f.radiation_enabled = True try: f.solve(loglevel=0, auto=True) except Exception as e: print('Error: not converge for case:', e) return -1 if flag_soret: f.soret_enabled = True try: f.solve(loglevel=0, auto=True) except Exception as e: print('Error: not converge for case:', e) return -1 f.save('{}.xml'.format(case_name)) ################################################################################ # post-processing # Calculate Bilger's mixture fraction # fuel gas.TPX = tin_f, p, comp_f z_f = 0 for e in Z_element: z_f += (element_nu[e] * gas.elemental_mass_fraction(e) / gas.atomic_weight(e)) comp_fuel = np.hstack((gas.T, gas.Y)) fuel_str = ' '.join([format(x, '12.6e') for x in comp_fuel]) # oxidizer gas.TPX = tin_o, p, comp_o z_o = 0 for e in Z_element: z_o += (element_nu[e] * gas.elemental_mass_fraction(e) / gas.atomic_weight(e)) comp_oxy = np.hstack((gas.T, gas.Y)) oxy_str = ' '.join([format(x, '12.6e') for x in comp_oxy]) # stoichiometric mixture comp_st = {} for k in fuel.keys(): comp_st[k] = 0. for k in oxy.keys(): comp_st[k] = 0. for k, v in fuel.items(): comp_st[k] += v for k, v in oxy.items(): comp_st[k] += v * stoich_nu gas.TPX = tin_o, p, comp_st z_st = 0 for e in Z_element: z_st += (element_nu[e] * gas.elemental_mass_fraction(e) / gas.atomic_weight(e)) Zst = (z_st - z_o) / (z_f - z_o) z = np.zeros(f.T.shape) for e in Z_element: z += (element_nu[e] * f.elemental_mass_fraction(e) / gas.atomic_weight(e)) Z = (z - z_o) / (z_f - z_o) # thermal diffusivity alpha = f.thermal_conductivity / (f.cp_mass * f.density) # kinetic viscosity nu = f.viscosity / f.density # a mixture fraction based on fuel stream is pure fuel gas.TPX = tin_f, p, fuel z_f = 0 for e in Z_element: z_f += (element_nu[e] * gas.elemental_mass_fraction(e) / gas.atomic_weight(e)) gas.TPX = tin_o, p, oxy z_o = 0 for e in Z_element: z_o += (element_nu[e] * gas.elemental_mass_fraction(e) / gas.atomic_weight(e)) Z1st = (z_st - z_o) / (z_f - z_o) z = np.zeros(f.T.shape) for e in Z_element: z += (element_nu[e] * f.elemental_mass_fraction(e) / gas.atomic_weight(e)) Z1 = (z - z_o) / (z_f - z_o) # heat release rate Q = f.heat_release_rate ################################################################################ # output data = np.column_stack((f.grid, f.T, f.Y.transpose(), Z, Z1, Q, alpha, nu)) data_names = (['grid', 'T'] + gas.species_names + ['Z', 'Z1', 'Q', 'alpha', 'nu']) np.savetxt('{}.dat'.format(case_name), data, header=('FUEL: {0}\nOXIDIZER: {1}\n'.format(fuel_str, oxy_str) + 'Zst = {:g}; Z1st = {:g}\n'.format(Zst, Z1st) + ' '.join(data_names)), comments='') if np.max(f.T) < np.max((tin_f, tin_o)) + 100: return 1 else: return 0
def counterflow_flame(mech='gri30.xml', transport='Multi', flag_soret=True, flag_radiation=False, fuel_name='CH4', strain_rate=100., width=0.01, p=1., phi_f='inf', phi_o=0., tin_f=300., tin_o=300., solution=None): ################################################################################ # Create the gas object used to evaluate all thermodynamic, kinetic, and # transport properties. gas = ct.Solution(mech) phi_f = float(phi_f) if phi_f <= 1.: sys.exit('Equivalence ratio of fuel side {:g}'.format(phi_f)) if phi_o >= 1.: sys.exit('Equivalence ratio of oxidizer side {:g}'.format(phi_o)) # construct case name flame_params = {} flame_params['F'] = fuel_name flame_params['p'] = p flame_params['a'] = strain_rate flame_params['phif'] = phi_f flame_params['phio'] = phi_o flame_params['tf'] = tin_f flame_params['to'] = tin_o # flame_params_str = [] # for k, v in flame_params.items(): # try: # param_str = '{0}-{1:g}'.format(k,v) # except ValueError: # param_str = '{0}-{1}'.format(k,v) # flame_params_str.append(param_str) # # case_name = '_'.join(flame_params_str) case_name = params2name(flame_params) p *= ct.one_atm # pressure # if phi_f < 10.0: # case_name = '{0}_p{1:g}_a{2:g}_phif{3:g}_phio{4:g}_tf{5:g}_to{6:g}'\ # .format(fuel_name,p/ct.one_atm,strain_rate, # phi_f,phi_o,tin_f,tin_o) # else: # case_name = '{0}_p{1:g}_a{2:g}_phifinf_phio{3:g}_tf{4:g}_to{5:g}'\ # .format(fuel_name,p/ct.one_atm,strain_rate, # phi_f,phi_o,tin_f,tin_o) # ## parameters of the counterflow flame ## a = (U_f+U+o)/width #strain_rate = 100 # 1/s # #width = 0.01 # Distance between inlets is 2 cm # ## single fuel #fuel_name = 'CH4' # #phi_f = 1.7 # equivalence ratio of the fuel side stream #phi_o = 0. # equivalence ratio of the oxidizer side stream # #tin_f = 300.0 # fuel inlet temperature #tin_o = 300.0 # oxidizer inlet temperature # ################################################################################ oxy = {'O2': 1., 'N2': 3.76} # air composition fuel_index = gas.species_index(fuel_name) stoich_nu = gas.n_atoms(fuel_index, 'C') + gas.n_atoms(fuel_index, 'H') / 4. comp_f = {} comp_o = {} comp_f[fuel_name] = 1 for k, v in oxy.items(): comp_o[k] = v comp_f[k] = v * stoich_nu / phi_f comp_o[fuel_name] = phi_o # fuel and oxidizer streams have the same velocity u = strain_rate * width / 2. # get mass flow rate gas.TPX = tin_f, p, comp_o dens_o = gas.density mdot_o = u * dens_o gas.TPX = tin_o, p, comp_f dens_f = gas.density mdot_f = u * dens_f # kg/m^2/s # 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. f = ct.CounterflowDiffusionFlame(gas, width=width) if solution is not None: try: f.restore(solution, loglevel=0) except Exception as e: print(e, 'Start to solve from initialization') f.transport_model = transport # Set the state of the two inlets f.fuel_inlet.mdot = mdot_f f.fuel_inlet.X = comp_f f.fuel_inlet.T = tin_f f.oxidizer_inlet.mdot = mdot_o f.oxidizer_inlet.X = comp_o f.oxidizer_inlet.T = tin_o # Set the boundary emissivities f.set_boundary_emissivities(0.0, 0.0) # Turn radiation off f.radiation_enabled = False f.set_refine_criteria(ratio=2, slope=0.1, curve=0.1, prune=0.01) # Solve the problem try: f.solve(loglevel=0, auto=True) except Exception as e: print('Error: not converge for case:', e) return -1 if flag_radiation: f.radiation_enabled = True try: f.solve(loglevel=0, auto=True) except Exception as e: print('Error: not converge for case:', e) return -1 if flag_soret: f.soret_enabled = True try: f.solve(loglevel=0, auto=True) except Exception as e: print('Error: not converge for case:', e) return -1 f.save('{}.xml'.format(case_name)) ################################################################################ # post-processing # Calculate Bilger's mixture fraction # fuel gas.TPX = tin_f, p, comp_f YC_f = gas.elemental_mass_fraction('C') YH_f = gas.elemental_mass_fraction('H') YO_f = gas.elemental_mass_fraction('O') comp_fuel = np.hstack((gas.T, gas.Y)) fuel_str = ' '.join([format(x, '12.6e') for x in comp_fuel]) # oxidizer gas.TPX = tin_o, p, comp_o YC_o = gas.elemental_mass_fraction('C') YH_o = gas.elemental_mass_fraction('H') YO_o = gas.elemental_mass_fraction('O') comp_oxy = np.hstack((gas.T, gas.Y)) oxy_str = ' '.join([format(x, '12.6e') for x in comp_oxy]) # stoichiometric mixture comp_st = {} comp_st[fuel_name] = 1 for k, v in oxy.items(): comp_st[k] = v * stoich_nu gas.TPX = tin_o, p, comp_st YC_st = gas.elemental_mass_fraction('C') YH_st = gas.elemental_mass_fraction('H') YO_st = gas.elemental_mass_fraction('O') Zst = (2.*(YC_st-YC_o)/gas.atomic_weight('C') +(YH_st-YH_o)/2./gas.atomic_weight('H') -(YO_st-YO_o)/gas.atomic_weight('O')) / \ (2.*(YC_f-YC_o)/gas.atomic_weight('C') +(YH_f-YH_o)/2./gas.atomic_weight('H') -(YO_f-YO_o)/gas.atomic_weight('O')) YC = f.elemental_mass_fraction('C') YH = f.elemental_mass_fraction('H') YO = f.elemental_mass_fraction('O') Z = (2.*(YC-YC_o)/gas.atomic_weight('C') +(YH-YH_o)/2./gas.atomic_weight('H') -(YO-YO_o)/gas.atomic_weight('O')) / \ (2.*(YC_f-YC_o)/gas.atomic_weight('C') +(YH_f-YH_o)/2./gas.atomic_weight('H') -(YO_f-YO_o)/gas.atomic_weight('O')) # thermal diffusivity alpha = f.thermal_conductivity / (f.cp_mass * f.density) # kinetic viscosity nu = f.viscosity / f.density # a mixture fraction based on fuel stream is pure CH4 gas.TPX = tin_f, p, {fuel_name: 1} YC_f = gas.elemental_mass_fraction('C') YH_f = gas.elemental_mass_fraction('H') YO_f = gas.elemental_mass_fraction('O') gas.TPX = tin_o, p, oxy YC_o = gas.elemental_mass_fraction('C') YH_o = gas.elemental_mass_fraction('H') YO_o = gas.elemental_mass_fraction('O') Z1st = (2.*(YC_st-YC_o)/gas.atomic_weight('C') +(YH_st-YH_o)/2./gas.atomic_weight('H') -(YO_st-YO_o)/gas.atomic_weight('O')) / \ (2.*(YC_f-YC_o)/gas.atomic_weight('C') +(YH_f-YH_o)/2./gas.atomic_weight('H') -(YO_f-YO_o)/gas.atomic_weight('O')) Z1 = (2.*(YC-YC_o)/gas.atomic_weight('C') +(YH-YH_o)/2./gas.atomic_weight('H') -(YO-YO_o)/gas.atomic_weight('O')) / \ (2.*(YC_f-YC_o)/gas.atomic_weight('C') +(YH_f-YH_o)/2./gas.atomic_weight('H') -(YO_f-YO_o)/gas.atomic_weight('O')) # progress variable # C_o: mass fractio of O in products CO2, CO, H2O # C_4spe: mass fraction of CO2, CO, H2O, H2 # C_2spe: mass fraction of CO2 and CO index_H2O = gas.species_index('H2O') index_CO2 = gas.species_index('CO2') index_CO = gas.species_index('CO') index_H2 = gas.species_index('H2') MW_H2O = gas.molecular_weights[index_H2O] MW_CO2 = gas.molecular_weights[index_CO2] MW_CO = gas.molecular_weights[index_CO] MW_H2 = gas.molecular_weights[index_H2] C_o = gas.atomic_weight('O') * (f.Y[index_H2O] / MW_H2O + 2. * f.Y[index_CO2] / MW_CO2 + f.Y[index_CO] / MW_CO) C_4spe = f.Y[index_CO2] + f.Y[index_CO] + f.Y[index_H2O] + f.Y[index_H2] C_2spe = f.Y[index_CO2] + f.Y[index_CO] # heat release rate Q = f.heat_release_rate ################################################################################ # output data = np.column_stack((f.grid, f.T, f.Y.transpose(), Z, Z1, C_o, C_4spe, C_2spe, Q, alpha, nu)) data_names = (['grid', 'T'] + gas.species_names + ['Z', 'Z1', 'C_o', 'C_4spe', 'C_2spe', 'Q', 'alpha', 'nu']) np.savetxt('{}.dat'.format(case_name), data, header=('FUEL: {0}\nOXIDIZER: {1}\n'.format(fuel_str, oxy_str) + 'Zst = {:g}; Z1st = {:g}\n'.format(Zst, Z1st) + ' '.join(data_names)), comments='') if np.max(f.T) < np.max((tin_f, tin_o)) + 100: return 1 else: return 0
mix_res_ratio = [0.02, 0.05, 0.1, 0.2, 0.5] equiv_ratio = [1.0, 1.2] Zf_variance = [0.01, 0.02, 0.05, 0.1] dtmix = [0.01, 0.04] phif = 4.76 params = {} for mix in mixing_models: params['MIX'] = mix for tres in time_res: params['tres'] = tres for tmix_ratio in mix_res_ratio: params['tmix'] = tmix_ratio for eqv in equiv_ratio: params['eqv'] = eqv for var in Zf_variance: params['Zfvar'] = var for dt in dtmix: params['dtmix'] = dt name_old = params2name(params) params['phif'] = phif name_new = params2name(params) shutil.move(name_old,name_new) del params['phif']