# combustor.py (Source)

 ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83``` ```""" A combustor, modeled as a single well-stirred reactor. We are interested in the steady-state burning solution. This example explores the effect of changing the residence time on completeness of reaction (through the burned gas temperature) and on the total heat release rate. Demonstrates the use of a MassFlowController where the mass flow rate function depends on variables other than time by capturing these variables from the enclosing scope. Also shows the use of a PressureController to create a constant pressure reactor with a fixed volume. """ import numpy as np import matplotlib.pyplot as plt import cantera as ct # Use reaction mechanism GRI-Mech 3.0 gas = ct.Solution('gri30.xml') # Create a Reservoir for the inlet, set to a methane/air mixture at a specified # equivalence ratio equiv_ratio = 0.5 # lean combustion gas.TP = 300.0, ct.one_atm gas.set_equivalence_ratio(equiv_ratio, 'CH4:1.0', 'O2:1.0, N2:3.76') inlet = ct.Reservoir(gas) # Create the combustor, and fill it initially with a mixture consisting of the # equilibrium products of the inlet mixture. This state corresponds to the state # the reactor would reach with infinite residence time, and thus provides a good # initial condition from which to reach a steady-state solution on the reacting # branch. gas.equilibrate('HP') combustor = ct.IdealGasReactor(gas) combustor.volume = 1.0 # Create a reservoir for the exhaust exhaust = ct.Reservoir(gas) # Use a variable mass flow rate to keep the residence time in the reactor # constant (residence_time = mass / mass_flow_rate). The mass flow rate function # can access variables defined in the calling scope, including state variables # of the Reactor object (combustor) itself. def mdot(t): return combustor.mass / residence_time inlet_mfc = ct.MassFlowController(inlet, combustor, mdot=mdot) # A PressureController has a baseline mass flow rate matching the 'master' # MassFlowController, with an additional pressure-dependent term. By explicitly # including the upstream mass flow rate, the pressure is kept constant without # needing to use a large value for 'K', which can introduce undesired stiffness. outlet_mfc = ct.PressureController(combustor, exhaust, master=inlet_mfc, K=0.01) # the simulation only contains one reactor sim = ct.ReactorNet([combustor]) # Run a loop over decreasing residence times, until the reactor is extinguished, # saving the state after each iteration. states = ct.SolutionArray(gas, extra=['tres']) residence_time = 0.1 # starting residence time while combustor.T > 500: sim.set_initial_time(0.0) # reset the integrator sim.advance_to_steady_state() print('tres = {:.2e}; T = {:.1f}'.format(residence_time, combustor.T)) states.append(combustor.thermo.state, tres=residence_time) residence_time *= 0.9 # decrease the residence time for the next iteration # Heat release rate [W/m^3] Q = - np.sum(states.net_production_rates * states.partial_molar_enthalpies, axis=1) # Plot results f, ax1 = plt.subplots(1,1) ax1.plot(states.tres, Q, '.-', color='C0') ax2 = ax1.twinx() ax2.plot(states.tres[:-1], states.T[:-1], '.-', color='C1') ax1.set_xlabel('residence time [s]') ax1.set_ylabel('heat release rate [W/m\$^3\$]', color='C0') ax2.set_ylabel('temperature [K]', color='C1') f.tight_layout() plt.show() ```