def create_reactors(self, add_Q=False, add_mdot=False, add_surf=False): self.gas = ct.Solution('gri30.xml') self.gas.TPX = 900, 25*ct.one_atm, 'CO:0.5, H2O:0.2' self.gas1 = ct.Solution('gri30.xml') self.gas1.ID = 'gas' self.gas2 = ct.Solution('gri30.xml') self.gas2.ID = 'gas' resGas = ct.Solution('gri30.xml') solid = ct.Solution('diamond.xml', 'diamond') T0 = 1200 P0 = 25*ct.one_atm X0 = 'CH4:0.5, H2O:0.2, CO:0.3' self.gas1.TPX = T0, P0, X0 self.gas2.TPX = T0, P0, X0 self.r1 = ct.IdealGasReactor(self.gas1) self.r2 = self.reactorClass(self.gas2) self.r1.volume = 0.2 self.r2.volume = 0.2 resGas.TP = T0 - 300, P0 env = ct.Reservoir(resGas) U = 300 if add_Q else 0 self.w1 = ct.Wall(self.r1, env, K=1e3, A=0.1, U=U) self.w2 = ct.Wall(self.r2, env, A=0.1, U=U) if add_mdot: mfc1 = ct.MassFlowController(env, self.r1, mdot=0.05) mfc2 = ct.MassFlowController(env, self.r2, mdot=0.05) if add_surf: self.interface1 = ct.Interface('diamond.xml', 'diamond_100', (self.gas1, solid)) self.interface2 = ct.Interface('diamond.xml', 'diamond_100', (self.gas2, solid)) C = np.zeros(self.interface1.n_species) C[0] = 0.3 C[4] = 0.7 self.surf1 = ct.ReactorSurface(self.interface1, A=0.2) self.surf2 = ct.ReactorSurface(self.interface2, A=0.2) self.surf1.coverages = C self.surf2.coverages = C self.surf1.install(self.r1) self.surf2.install(self.r2) self.net1 = ct.ReactorNet([self.r1]) self.net2 = ct.ReactorNet([self.r2]) self.net1.set_max_time_step(0.05) self.net2.set_max_time_step(0.05) self.net2.max_err_test_fails = 10
def get_steady_state_starting_coverages( self, temperature_c, pressure, feed_mole_fractions, gas_volume_per_reactor, cat_area_per_gas_volume, ): """ To find the starting coverages, we run the gas to equilibrium, (i.e mostly burned products) then put that in steady state with the surface. May not be working """ gas, surf = self.gas, self.surf gas.TPX = temperature_c + 273.15, pressure, feed_mole_fractions TPY = gas.TPY # store to restore # gas.equilibrate('TP') r = ct.IdealGasReactor(gas, energy="off") r.volume = gas_volume_per_reactor cat_area_per_reactor = cat_area_per_gas_volume * gas_volume_per_reactor rsurf = ct.ReactorSurface(surf, r, A=cat_area_per_reactor) sim = ct.ReactorNet([r]) sim.advance(1e-3) surf() starting_coverages = surf.coverages gas.TPY = TPY # restore to starting conditions del (r, rsurf) return starting_coverages
def setup(): net = ct.ReactorNet() gas.TPX = 900, 101325, 'H2:0.1, OH:1e-7, O2:0.1, AR:1e-5' r = ct.Reactor(gas) net.addReactor(r) return r, net
def run_single(self): gas=self.processor.solution reactorPressure=gas.P self.reactorPressure=self.processor.solution.P pressureValveCoefficient=self.pvalveCoefficient maxPressureRiseAllowed=self.maxPrise print(maxPressureRiseAllowed,self.reactorPressure,pressureValveCoefficient) #Build the system components for JSR fuelAirMixtureTank=ct.Reservoir(self.processor.solution) exhaust=ct.Reservoir(self.processor.solution) stirredReactor=ct.IdealGasReactor(self.processor.solution,energy=self.energycon,volume=self.reactor_volume) massFlowController=ct.MassFlowController(upstream=fuelAirMixtureTank, downstream=stirredReactor,mdot=stirredReactor.mass/self.residence_time) pressureRegulator=ct.Valve(upstream=stirredReactor,downstream=exhaust,K=pressureValveCoefficient) reactorNetwork=ct.ReactorNet([stirredReactor]) if bool(self.observables) and self.kineticSens==1: for i in range(gas.n_reactions): stirredReactor.add_sensitivity_reaction(i) if self.kineticSens and bool(self.observables)==False: #except: print('Please supply a non-empty list of observables for sensitivity analysis or set kinetic_sens=0') if self.physicalSens==1 and bool(self.observables)==False:
def runsim(tmax, temp, pres, ics, sensitivity): dt = tmax / Npoints gas.TPX = temp, pres, ics r = ct.IdealGasReactor(gas, name='R1') sim = ct.ReactorNet([r]) nr = gas.n_reactions for i in range(0, nr): r.add_sensitivity_reaction(i) sim.rtol = 1.0e-8 sim.atol = 1.0e-14 sim.rtol_sensitivity = 1.0e-8 sim.atol_sensitivity = 1.0e-8 states = ct.SolutionArray(gas, extra=['t', 'sens']) for i in range(0, int(Npoints)): t = i * dt sim.advance(t) print("%5f" % (t / tmax), end='\r') sys.stdout.flush() sensitivities = [] for i in range(0, nr): sensitivities.append(sim.sensitivity(sensitivity, i)) states.append(r.thermo.state, t=t, sens=sensitivities) return states
def setup_reactor(self): self.gas = ct.Solution(self.rxnmech) self.xinit = {"O2": 0.21, "N2": 0.79} self.gas.TPX = self.T0, self.p0, self.xinit self.injection_gas, _ = setup_injection_gas(self.rxnmech, self.fuel, pure_fuel=True) self.injection_gas.TP = self.T0, self.p0 fuel_res = ct.Reservoir(self.injection_gas) # Create the reactor object self.reactor = ct.Reactor(self.gas) self.rempty = ct.Reactor(self.gas) # Set the initial states of the reactor self.reactor.chemistry_enabled = True self.reactor.volume = self.history["V"][0] # Add in a fuel injector self.injector = ct.MassFlowController(fuel_res, self.reactor) # Add in a wall that moves according to piston velocity self.piston = ct.Wall( left=self.reactor, right=self.rempty, A=np.pi / 4.0 * self.bore**2, U=0.0, velocity=self.history["piston_velocity"][0], ) # Create the network object self.sim = ct.ReactorNet([self.reactor])
def save_flux_diagrams(solution, times, conditions=None, condition_type='adiabatic-constant-volume', path='.', element='C', filename='flux_diagram', filetype='png'): """ This method is similar to run_simulation but it saves reaction path diagrams instead of returning objects. """ if conditions is not None: solution.TPX = conditions if condition_type == 'adiabatic-constant-volume': reactor = ct.IdealGasReactor(solution) elif condition_type == 'constant-temperature-and-pressure': reactor = ct.IdealGasConstPressureReactor(solution, energy='off') else: raise NotImplementedError( 'only "adiabatic-constant-volume" or "constant-temperature-and-pressure" is supported. {} input' .format(condition_type)) simulator = ct.ReactorNet([reactor]) solution = reactor.kinetics for time in times: simulator.advance(time) save_flux_diagram(solution, filename=filename + '_{:.2e}s'.format(simulator.time), path=path, element=element, filetype=filetype)
def __init__(self, reactor, gas, total_mass, timestep, method): """ Parameters ---------- reactor : `BatchPaSR` The reactor that this PFC acts as an inlet for gas : `cantera.Solution` Thermochemical state of gas to be entrained total_mass : `float` Total amount of mass that can be entrained in timestep : `float` Time between entrainment steps (continue to add particles if there's still mass left) method : `string` or `function` Function of time that describes entrainment rate (i.e. '0.5' or '0.12*t**2-0.6*t') The expression must be in terms of 't' in seconds and in Python syntax Alternatively, pass in a function to be called that only takes in a time and returns a mass flow rate Returns ------- None """ self.bp = reactor self.gas = gas self.rn = ct.ReactorNet([ct.ConstPressureReactor(self.gas)]) self.mass = total_mass self.dt = timestep self.mdotexp = method # self.nextstep = timestep/2 # Which time to add the next particle (using trapezoidal sum) self.nextstep = 0
def make_reactors(self, independent=True, n_reactors=2, T1=300, P1=101325, X1='O2:1.0', T2=300, P2=101325, X2='O2:1.0'): self.net = ct.ReactorNet() self.gas1 = ct.Solution('h2o2.xml') self.gas1.TPX = T1, P1, X1 self.r1 = self.reactorClass(self.gas1) self.net.add_reactor(self.r1) if independent: self.gas2 = ct.Solution('h2o2.xml') else: self.gas2 = self.gas1 if n_reactors >= 2: self.gas2.TPX = T2, P2, X2 self.r2 = self.reactorClass(self.gas2) self.net.add_reactor(self.r2)
def runSinglePSR(T, P, moleFraction, factor, reactionIndex, targetSpc): start = time.time() # create the gas mixture gas = ct.Solution('HXD15_Battin_mech.xml') gas.TPX = T, P, moleFraction # create an upstream reservoir that will supply the reactor. The temperature, # pressure, and composition of the upstream reservoir are set to those of the # 'gas' object at the time the reservoir is created. upstream = ct.Reservoir(gas) # Now create the reactor object with the same initial state cstr = ct.IdealGasReactor(gas) # Set its volume to 80 cm^3. In this problem, the reactor volume is fixed, so # the initial volume is the volume at all later times. cstr.volume = 80.0*1.0e-6 # Connect the upstream reservoir to the reactor with a mass flow controller # (constant mdot). Set the mass flow rate. vdot = 40* 1.0e-6 # m^3/s mdot = gas.density * vdot # kg/s mfc = ct.MassFlowController(upstream, cstr, mdot=mdot) # now create a downstream reservoir to exhaust into. downstream = ct.Reservoir(gas) # connect the reactor to the downstream reservoir with a valve, and set the # coefficient sufficiently large to keep the reactor pressure close to the # downstream pressure. v = ct.Valve(cstr, downstream, K=1.0e-9) # create the network network = ct.ReactorNet([cstr]) # modify the A factor of the given reaction gas.set_multiplier(factor,reactionIndex-1) # now integrate in time t = 0.0 dt = 0.1 print "\n\n\n**************************\n***** Solving case %d *****\n"%(reactionIndex) while t < 30.0: print t t += dt network.advance(t) results = [] for spc in targetSpc: results.append(cstr.thermo[spc].X[0]*1.0e6) end = time.time() print 'Execution time is:' print end - start return [gas.reaction_equation(reactionIndex-1)] + results
def setup_ignition_delay(self): gas = ct.Solution('h2o2.xml') gas.TP = 900, 5*ct.one_atm gas.set_equivalence_ratio(0.4, 'H2', 'O2:1.0, AR:4.0') r = ct.IdealGasReactor(gas) net = ct.ReactorNet([r]) return gas, r, net
def setUp(self): self.referenceFile = pjoin(os.path.dirname(__file__), 'data', 'WallTest-integrateWithAdvance.csv') # reservoir to represent the environment self.gas0 = ct.Solution('air.xml') self.gas0.TP = 300, ct.one_atm self.env = ct.Reservoir(self.gas0) # reactor to represent the side filled with Argon self.gas1 = ct.Solution('air.xml') self.gas1.TPX = 1000.0, 30*ct.one_atm, 'AR:1.0' self.r1 = ct.Reactor(self.gas1) # reactor to represent the combustible mixture self.gas2 = ct.Solution('h2o2.xml') self.gas2.TPX = 500.0, 1.5*ct.one_atm, 'H2:0.5, O2:1.0, AR:10.0' self.r2 = ct.Reactor(self.gas2) # Wall between the two reactors self.w1 = ct.Wall(self.r2, self.r1, A=1.0, K=2e-4, U=400.0) # Wall to represent heat loss to the environment self.w2 = ct.Wall(self.r2, self.env, A=1.0, U=2000.0) # Create the reactor network self.sim = ct.ReactorNet([self.r1, self.r2])
def averageChemicalPower(gas, tMax): ''' Function: averageChemicalPower ====================================================================== This function returns the average chemical Power of a HP reaction with respect to the temperature ''' #find the equilibrium value (T0, p0, X0) = gas.TPX gas.equilibrate('HP') try: iH2O = gas.species_index('H2O') H2O = 'H2O' except: iH2O = gas.species_index('h2o') H2O = 'h2o' H2Oeq = gas.Y[iH2O] gas.TPX = (T0, p0, X0) alpha = 0.98 #arbitrary percentage #initiate the reactor network r = ct.IdealGasConstPressureReactor(gas) sim = ct.ReactorNet([r]) time = 0.0 qDotMean = 0.0 T = gas.T dt = tMax / 100.0 #advance simulation with guessed timestep while r.thermo[H2O].Y < (alpha * H2Oeq): time += dt sim.advance(time) qDotMean += (gas.T - T) * chemicalPower(gas, 'hp') T = gas.T return qDotMean / (gas.T - T0)
def setup(order): gas1.TPX = 1200, 1e3, 'H:0.002, H2:1, CH4:0.01, CH3:0.0002' gas2.TPX = 900, 101325, 'H2:0.1, OH:1e-7, O2:0.1, AR:1e-5' net = ct.ReactorNet() rA = ct.IdealGasReactor(gas1) rB = ct.IdealGasReactor(gas2) if order % 2 == 0: surfX = ct.ReactorSurface(interface, rA, A=0.1) surfY = ct.ReactorSurface(interface, rA, A=10) else: surfY = ct.ReactorSurface(interface, rA, A=10) surfX = ct.ReactorSurface(interface, rA, A=0.1) C1 = np.zeros(interface.n_species) C2 = np.zeros(interface.n_species) C1[0] = 0.3 C1[4] = 0.7 C2[0] = 0.9 C2[4] = 0.1 surfX.coverages = C1 surfY.coverages = C2 if order // 2 == 0: net.add_reactor(rA) net.add_reactor(rB) else: net.add_reactor(rB) net.add_reactor(rA) return rA, rB, surfX, surfY, net
def solve(gas, t): # Set the temperature and pressure for gas # t is different from t0 gas.TPX = t, pressure, composition surf.TP = t, pressure TDY = gas.TDY cov = surf.coverages # create a new reactor gas.TDY = TDY r = ct.IdealGasReactor(gas, energy='on') r.volume = rvol upstream = ct.Reservoir(gas, name='upstream') downstream = ct.Reservoir(gas, name='downstream') rsurf = ct.ReactorSurface(surf, r, A=cat_area) m = ct.MassFlowController(upstream, r, mdot=mass_flow_rate) v = ct.PressureController(r, downstream, master=m, K=1e-5) sim = ct.ReactorNet([r]) sim.max_err_test_fails = 20 sim.rtol = 1.0e-9 sim.atol = 1.0e-21 # define time, space, and other information vectors z2 = (np.arange(NReactors)) * rlen * 1e3 t_r2 = np.zeros_like(z2) # residence time in each reactor t2 = np.zeros_like(z2) states2 = ct.SolutionArray(gas) for n in range(NReactors): # Set the state of the reservoir to match that of the previous reactor gas.TDY = r.thermo.TDY upstream.syncState() sim.reinitialize() sim.advance_to_steady_state() dist = n * rlen * 1.0e3 # distance in mm t_r2[n] = r.mass / mass_flow_rate # residence time in this reactor t2[n] = np.sum(t_r2) states2.append(gas.state) print('Temperature of Gas :', t, ' residence time :', t2[-1]) MolFrac_CH4 = states2('CH4').X MolFrac_CO2 = states2('CO2').X MolFrac_CO = states2('CO').X MolFrac_H2 = states2('H2').X MolFrac_H2O = states2('H2O').X MolFrac_O2 = states2('O2').X kq = np.zeros(6) kq[0] = MolFrac_CH4[-1] * 100 kq[1] = MolFrac_CO2[-1] * 100 kq[2] = MolFrac_CO[-1] * 100 kq[3] = MolFrac_H2[-1] * 100 kq[4] = MolFrac_H2O[-1] * 100 kq[5] = MolFrac_O2[-1] * 100 return kq
def setup(self, T0, P0, mdot_fuel, mdot_ox): self.gas = ct.Solution('gri30.xml') # fuel inlet self.gas.TPX = T0, P0, "CH4:1.0" self.fuel_in = ct.Reservoir(self.gas) # oxidizer inlet self.gas.TPX = T0, P0, "N2:3.76, O2:1.0" self.oxidizer_in = ct.Reservoir(self.gas) # reactor, initially filled with N2 self.gas.TPX = T0, P0, "N2:1.0" self.combustor = ct.IdealGasReactor(self.gas) self.combustor.volume = 1.0 # outlet self.exhaust = ct.Reservoir(self.gas) # connect the reactor to the reservoirs self.fuel_mfc = ct.MassFlowController(self.fuel_in, self.combustor) self.fuel_mfc.set_mass_flow_rate(mdot_fuel) self.oxidizer_mfc = ct.MassFlowController(self.oxidizer_in, self.combustor) self.oxidizer_mfc.set_mass_flow_rate(mdot_ox) self.valve = ct.Valve(self.combustor, self.exhaust) self.valve.set_valve_coeff(1.0) self.net = ct.ReactorNet() self.net.add_reactor(self.combustor) self.net.max_err_test_fails = 10
def states_new_init(A): R_new = ct.Reaction.fromCti('''reaction('O2 + 2 H2 => 2 H2O', [%e, 0.0, 0.0])''' % (A)) #print(type(R_new)) #print(type(gas.reactions())) gas2 = ct.Solution(thermo='IdealGas', kinetics='GasKinetics', species=gas.species(), reactions=[R_new]) gas2.TPX = initial_state r_new = ct.IdealGasConstPressureReactor(gas2, energy='off') t_new = 0.0 states_new = ct.SolutionArray(gas2, extra=['t']) sim_new = ct.ReactorNet([r_new]) tt = [] TT = [] for n in range(100): '''t_new += 1.e-5 sim_new.advance(t_new) #print(t_new) tt.append(1000 * t_new*1000) TT.append(r_new.T)''' t_new += 1.e-5 sim_new.advance(t_new) states_new.append(r_new.thermo.state, t=t_new * 1e3) return states_new, gas2
def plug_flow_reactor(self, gas, details, length, area, u_0, **kwargs): # set default values var = {'observable': {'main': 'Concentration', 'sub': 0}, 't_lab_save': None, 'rtol': 1E-4, 'atol': 1E-7} var.update(kwargs) # Modify reactor if necessary for frozen composition and isothermal reactor.energy_enabled = var['solve_energy'] reactor.chemistry_enabled = not var['frozen_comp'] # Create Sim sim = ct.ReactorNet([reactor]) sim.atol = var['atol'] sim.rtol = var['rtol'] # set up times and observables ind_var = 't_lab' # INDEPENDENT VARIABLE CURRENTLY HARDCODED FOR t_lab if var['t_lab_save'] is None: t_all = [t_end] else: t_all = np.sort(np.unique(np.concatenate(([t_end], var['t_lab_save'])))) # combine t_end and t_save, sort, only unique values self.ODE_success = True details['success'] = True states = ct.SolutionArray(gas, extra=['t']) states.append(reactor.thermo.state, t = 0.0) for t in t_all: if not self.ODE_success: break while sim.time < t: # integrator step until time > target time try: sim.step() if sim.time > t: # force interpolation to target time sim.advance(t) states.append(reactor.thermo.state, t=sim.time) except: self.ODE_success = False details['success'] = False explanation = '\nCheck for: Fast rates or bad thermo data' checkRxns = self.checkRxnRates(gas) if len(checkRxns) > 0: explanation += '\nSuggested Reactions: ' + ', '.join([str(x) for x in checkRxns]) details['message'] = '\nODE Error: {:s}\n{:s}\n'.format(str(sys.exc_info()[1]), explanation) break reactor_vars = ['t_lab', 'T', 'P', 'h_tot', 'h', 's_tot', 's', 'rho', 'Y', 'X', 'conc', 'wdot', 'wdotfor', 'wdotrev', 'HRR_tot', 'HRR', 'delta_h', 'delta_s', 'eq_con', 'rate_con', 'rate_con_rev', 'net_ROP', 'for_ROP', 'rev_ROP'] num = {'reac': np.sum(gas.reactant_stoich_coeffs(), axis=0), 'prod': np.sum(gas.product_stoich_coeffs(), axis=0), 'rxns': gas.n_reactions} SIM = Simulation_Result(num, states, reactor_vars) SIM.finalize(self.ODE_success, ind_var, var['observable'], units='CGS') return SIM, details
def test_Reactor(self): phase = ct.PureFluid('liquidvapor.xml', 'oxygen') air = ct.Solution('air.xml') phase.TP = 93, 4e5 r1 = ct.Reactor(phase) r1.volume = 0.1 air.TP = 300, 4e5 r2 = ct.Reactor(air) r2.volume = 10.0 air.TP = 500, 4e5 env = ct.Reservoir(air) w1 = ct.Wall(r1,r2) w1.expansion_rate_coeff = 1e-3 w2 = ct.Wall(env,r1, Q=500000, A=1) net = ct.ReactorNet([r1,r2]) net.atol = 1e-10 net.rtol = 1e-6 states = ct.SolutionArray(phase, extra='t') for t in np.arange(0.0, 60.0, 1): net.advance(t) states.append(TD=r1.thermo.TD, t=net.time) self.assertEqual(states.X[0], 0) self.assertEqual(states.X[-1], 1) self.assertNear(states.X[30], 0.54806, 1e-4)
def get_ignition_delay(cantera_file_path, temperature, pressure, stoichiometry=1.0, isomer='N'): """ Get the ignition delay at temperature (K) and pressure (bar) and stochiometry (phi), for the butanol isomer (n,s,t,i) """ try: ct.suppress_thermo_warnings(True) except AttributeError: print("Sorry about the warnings...") gas = ct.Solution(cantera_file_path) assert isomer in ['N', 'S', 'T', 'I' ], "Expecting isomer N, S, T, or I not {}".format(isomer) oxygen_mole = 1.0 butanol_mole = stoichiometry * oxygen_mole / 6. X_string = isomer + 'C7H16:{0}, O2:{1}'.format(butanol_mole, oxygen_mole) gas.TPX = temperature, pressure * 1e5, X_string reactor = ct.IdealGasReactor(gas) reactor_network = ct.ReactorNet([reactor]) time = 0.0 end_time = 1000e-3 times = [] concentrations = [] pressures = [] temperatures = [] print_data = True while time < end_time: time = reactor_network.time times.append(time) temperatures.append(reactor.T) pressures.append(reactor.thermo.P) concentrations.append(reactor.thermo.concentrations) reactor_network.step(end_time) print("reached end time {0:.4f} ms in {1} steps ".format( times[-1] * 1e3, len(times))) concentrations = np.array(concentrations) times = np.array(times) pressures = np.array(pressures) temperatures = np.array(temperatures) dTdt = (temperatures[1:] - temperatures[:-1]) / (times[1:] - times[:-1]) step_with_fastest_T_rise = dTdt.argmax() if step_with_fastest_T_rise > 1 and step_with_fastest_T_rise < len( times) - 2: ignition_time_ms = 1e3 * times[step_with_fastest_T_rise] print( "At {0} K {1} bar, ignition delay time is {2} ms for {3}-butanol". format(temperature, pressure, ignition_time_ms, isomer)) return ignition_time_ms else: print( "At {0} K {1} bar, no ignition is detected for {2}-butanol".format( temperature, pressure, isomer)) return np.infty
def eval_idt(args): mech, options, x = args gas = global_var.gases[mech] t_fin = options.t_fin time_vec = [] temp_vec = [] # DCN Conditions p = options.pres # Pa t = options.temp # K phi = options.phi # Add air to the mixture stoich_o2 = 0.0 for idx, species in enumerate(options.palette): stoich_o2 += x[idx] * (gas.n_atoms(species, 'C') + 0.25 * gas.n_atoms(species, 'H')) # Set gas composition with air x_mod = (options.phi / stoich_o2) * x comp_string = set_gas_using_palette(gas, options, t, p, x_mod) comp_string += ',O2:1,N2:3.76' gas.TPX = t, p, comp_string # Create reactor network r = ct.Reactor(gas) sim = ct.ReactorNet([r]) # Advance the reactor time = 0.0 time_vec.append(time) while time < t_fin: time = sim.step() time_vec.append(time) temp_vec.append(r.T) # Find maximum slope of temperature max_der = 0.0 der = 0.0 index = 0 for idx, val in enumerate(temp_vec): der = (temp_vec[idx] - temp_vec[idx-1]) / \ (time_vec[idx] - time_vec[idx-1]) if abs(der) > max_der: max_der = der index = idx if temp_vec[index] < t: return -1 else: print str(["{:0.3f}".format(y) for y in x]) + ", " + str("{:0.7e}".format(time_vec[index])) #print str(options.pres) + ", " + str(options.temp) + ", " + str(options.phi) + ", " + str("{:0.7e}".format(time_vec[index])) sys.stdout.flush() return time_vec[index]
def test_cantera_reactornet(): """ Testing basic Cantera ReactorNet functionality """ g = get_gas() ctreactor = ct.Reactor(g) ctnet = ct.ReactorNet([ctreactor]) ctnet.advance(0.01)
def simulate_branching_various_conditions_3D( cantera_input_path, HO2_frac, conversion_species=['npropyloo', 'npropyl'], desired_conversion=0.95, starting_alkyl_radical='npropyl', expected_products=None, peroxy_frac=1e-17, temperatures=np.linspace(250, 1250, 25), pressures=np.logspace(3, 7, 15), NO_fracs=np.logspace(-12, -4, 15)): combs = [{ 'temp (K)': f1, 'NO (fraction)': f2, 'pres (Pa)': f3 } for f1 in temperatures for f2 in NO_fracs for f3 in pressures] df = pd.DataFrame(combs) for index in df.index: initialMoleFractions = { "NO": df.loc[index, 'NO (fraction)'], "HO2": HO2_frac, starting_alkyl_radical: peroxy_frac, 'O2': 0.21, "N2": 0.79, } solution = ctt.create_mechanism(cantera_input_path) conditions = df.loc[index, 'temp (K)'], df.loc[ index, 'pres (Pa)'], initialMoleFractions solution.TPX = conditions reactor = ct.IdealGasConstPressureReactor(solution, energy='off') simulator = ct.ReactorNet([reactor]) solution = reactor.kinetics peroxy_conc = sum([ solution.concentrations[solution.species_index(s)] for s in conversion_species ]) outputs = ctt.run_simulation_till_conversion( solution=solution, conditions=conditions, species=conversion_species, conversion=desired_conversion, condition_type='constant-temperature-and-pressure', output_reactions=False, atol=1e-25, ) species = outputs['species'] for name, conc in species.iteritems(): if not expected_products or name in expected_products: df.loc[index, name] = (conc / peroxy_conc).values[-1] df.fillna(value=0, inplace=True) return df
def totaldelaydata1(ITemp, IPressure, Ifraction, IER): Temp = np.zeros(ITemp) a = np.zeros(Ifraction) pressure = np.zeros(IPressure) ER = np.zeros(IER) # write output CSV file for importing into Excel gas = ct.Solution('gri30.xml') #writer.writerow(gas.species_names) for i in range(ITemp): Temp[i] = 1000.0 + 50 * i for m in range(IPressure): pressure[m] = 1 * ct.one_atm + 5.0 * m * ct.one_atm for n in range(Ifraction): a[n] = 0.1 * n for e in range(IER): gas.TP = Temp[i], pressure[m] ER[e] = 0.5 + 0.1 * e fO2 = ((1 - a[n]) * 2.0 + a[n] * 0.5) * (1 / ER[e]) CH4_P = 1 - a[n] H2_P = a[n] O2_P = fO2 N2_P = 3.76 * fO2 gas.X = { 'CH4': 1 - a[n], 'H2': a[n], 'O2': fO2, 'N2': 3.76 * fO2 } r = ct.IdealGasConstPressureReactor(gas) sim = ct.ReactorNet([r]) time = 0.0 states = ct.SolutionArray(gas, extra=['t']) #print('%10s %10s %10s %14s' % ('t [s]','T [K]','P [Pa]','u [J/kg]')) for number in range(10000): time += 1.e-6 sim.advance(time) states.append(r.thermo.state, t=time * 1e3) #print('%10.3e %10.3f %10.3f %14.6e' % (sim.time, r.T,r.thermo.P, r.thermo.u)) X_OH = np.max(states.X[:, gas.species_index('OH')]) X_HO2 = np.max(states.X[:, gas.species_index('HO2')]) # We will use the 'OH' species to compute the ignition delay max_index = np.argmax(states.X[:, gas.species_index('OH')]) Tau1 = states.t[max_index] # We will use the 'HO2' species to compute the ignition delay #max_index = np.argmax(states.X[:, gas.species_index('HO2')]) #Tau2[i] = states.t[max_index] # writer.writerow([pressure, Temp[i], CH4_P, H2_P, # O2_P, N2_P, ER, X_OH[i], X_HO2[i], Tau1[i]]) yield pressure[m], Temp[ i], CH4_P, H2_P, O2_P, N2_P, X_OH, X_HO2, Tau1 gas = ct.Solution('gri30.xml')
def setUpClass(cls): utilities.CanteraTest.setUpClass() cls.gas = ct.Solution('gri30.xml') cls.gas.TPX = 1300.0, ct.one_atm, 'CH4:0.4, O2:1, N2:3.76' r = ct.IdealGasReactor(cls.gas) net = ct.ReactorNet([r]) T = r.T while T < 1900: net.step() T = r.T
def initialize_reactor(self): """Initialize the shock tube. It consists of a Cantera :py:class:`cantera.IdealGasReactor` object defined in self.reactor_model and a Cantera reactor network containing only that reactor. """ self.reactor = self.reactor_model(self.gas) self.simulation = ct.ReactorNet([self.reactor]) self.simulation.atol = 1.0e-13 self.simulation.rtol = 1.0e-4 return
def getAI(self): gas = Global.gas ifuel = gas.species_index(self.fuel) io2 = gas.species_index('O2') in2 = gas.species_index('N2') self.putMultiplier(gas) x = np.zeros(gas.n_species) x[ifuel] = self.phi x[io2] = gas.n_atoms(self.fuel, 'C') + 0.25 * \ gas.n_atoms(self.fuel, 'H') x[in2] = x[io2] * self.n2_o2_ratio gas.TPX = self.Tin, self.P, x # Create reactor network r = ct.Reactor(gas) sim = ct.ReactorNet([r]) # Advance the reactor time = 0.0 time0 = 0.0 time1 = 0.0 curT0 = r.T curT1 = r.T iteration = 0 #sim.atol = 1e-7 #sim.rtol = 1e-4 try: while curT1 < self.Ttarget: time = sim.step() curT0 = curT1 curT1 = r.T time0 = time1 time1 = time iteration += 1 if (time > 4.e2): print('Current time too large, continuing') return 4.e2 if (iteration > 100000): print('Max Iteration reached, continuing') return 0. except: print('Failed! Continuing...') return 4.e2 weight = (self.Ttarget - curT0) / (curT1 - curT0) AItime = (1. - weight) * time0 + weight * time1 return AItime
def initialize_reactor(gas, sensitivity_species): num_reactions = gas.n_reactions r = ct.IdealGasReactor(gas, energy='off') sim = ct.ReactorNet([r]) if sensitivity_species: for i in xrange(num_reactions): r.add_sensitivity_reaction(i) sim.rtol_sensitivity = 1e-4 sim.atol_sensitivity = 1e-6 return r, sim
def __init__(self,mechanism_path,composition,grid,atol=None,rtol=None): self.gas = ct.Solution(mechanism_path) self.gas.X = composition self.T = grid.T self.PG = grid.PG self.N = grid.N self.reactor = ct.IdealGasReactor(contents = self.gas, energy = 'off') self.network=ct.ReactorNet([self.reactor]) if atol != None: self.network.atol = atol if rtol != None: self.network.rtol = rtol
def setUp(self): self.gas = ct.Solution('h2o2.xml') # create a reservoir for the fuel inlet, and set to pure methane. self.gas.TPX = 300.0, ct.one_atm, 'H2:1.0' fuel_in = ct.Reservoir(self.gas) fuel_mw = self.gas.mean_molecular_weight # Oxidizer inlet self.gas.TPX = 300.0, ct.one_atm, 'O2:1.0, AR:3.0' oxidizer_in = ct.Reservoir(self.gas) oxidizer_mw = self.gas.mean_molecular_weight # to ignite the fuel/air mixture, we'll introduce a pulse of radicals. # The steady-state behavior is independent of how we do this, so we'll # just use a stream of pure atomic hydrogen. self.gas.TPX = 300.0, ct.one_atm, 'H:1.0' self.igniter = ct.Reservoir(self.gas) # create the combustor, and fill it in initially with a diluent self.gas.TPX = 300.0, ct.one_atm, 'AR:1.0' self.combustor = ct.IdealGasReactor(self.gas) # create a reservoir for the exhaust self.exhaust = ct.Reservoir(self.gas) # compute fuel and air mass flow rates factor = 0.1 oxidizer_mdot = 4 * factor * oxidizer_mw fuel_mdot = factor * fuel_mw # The igniter will use a time-dependent igniter mass flow rate. def igniter_mdot(t, t0=0.1, fwhm=0.05, amplitude=0.1): return amplitude * math.exp( -(t - t0)**2 * 4 * math.log(2) / fwhm**2) # create and install the mass flow controllers. Controllers # m1 and m2 provide constant mass flow rates, and m3 provides # a short Gaussian pulse only to ignite the mixture m1 = ct.MassFlowController(fuel_in, self.combustor, mdot=fuel_mdot) m2 = ct.MassFlowController(oxidizer_in, self.combustor, mdot=oxidizer_mdot) m3 = ct.MassFlowController(self.igniter, self.combustor, mdot=igniter_mdot) # put a valve on the exhaust line to regulate the pressure self.v = ct.Valve(self.combustor, self.exhaust, K=1.0) # the simulation only contains one reactor self.sim = ct.ReactorNet([self.combustor])