In [1]:
import cantera_tools as ctt
import numpy as np
from scipy import integrate
import cantera as ct
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
Many RMG models have poorly-named species, due in part to restrictions of CHEMKIN names. Cantera have fewer restrictions, so mechanisms produced with it can have more understandable names. This example converts an RMG CHEMKIN file to a Cantera file which uses SMILES to names species.
This method will place an input_nicely_named.cti and a species_dictionary_nicely_named.txt into the folder specified in the method
In [2]:
ctt.obtain_cti_file_nicely_named('cookbook_files/',original_ck_file='chem.inp')
In [3]:
model_link = 'cookbook_files/model.cti'
desired_reactions = ['CH3OH + O2 <=> CH2OH(29) + HO2(12)',
'C3H8 + O2 <=> C3H7(61) + HO2(12)',
'C3H8 + O2 <=> C3H7(60) + HO2(12)',
'CH3OH + OH(10) <=> CH2OH(29) + H2O(11)',
'C3H8 + OH(10) <=> C3H7(60) + H2O(11)',
'C3H8 + OH(10) <=> C3H7(61) + H2O(11)',
'CH3OH + HO2(12) <=> CH2OH(29) + H2O2(13)',
'C3H8 + HO2(12) <=> C3H7(61) + H2O2(13)',
'C3H8 + HO2(12) <=> C3H7(60) + H2O2(13)',
'C3H7(60) + O2 <=> C3H7O2(78)',
'C3H7(61) + O2 <=> C3H7O2(80)',]
# make the reduced mechanism using the full mechanism `.cti` file.
solution_reduced = ctt.create_mechanism(model_link, kept_reaction_equations=desired_reactions)
# NOTE: this cantera Solution object can now be used like any other
Simulations can be run in the following ways:
run_simulation - you give the method times which you want data saved, and it saves data at each time.run_simulation_till_conversion - this method will run a simulation until the specified conversion is reached for a target species.find_ignition_delay - you give this method the initial conditions and it outputs the ignition delay determined by the maximum of $\frac{dT}{dt}$, as well as simulation data given every so many iterator steps.These methods currently work for constant temperature and pressure or adiabatic constant volume.
It's also possible to adapt these methods to your specific situation. If you think your adaption will be useful for others, consider talking with the author (posting a issue or in person) or just making a pull request.
In [4]:
model_link = 'cookbook_files/model.cti'
# creates the cantera Solution object
solution = ctt.create_mechanism(model_link)
#initial mole fractions
mole_fractions = {'N2':5, 'O2':1, 'C3H8': 0.3}
# set initial conditions of solution in kelvin pascals and mole fractions
conditions = 800, 10**6, mole_fractions
solution.TPX = conditions
# store 100 times between 10^-8s and 1s, with an initial point at t=0
times = np.logspace(-8,0,num=100)
times = np.insert(times,0,0)
# run the simulation
outputs = ctt.run_simulation(solution, times,
condition_type = 'constant-temperature-and-pressure',
output_reactions = True,
output_directional_reactions = True,
output_rop_roc=True)
# you can combine outputs how you would like with pd.concat
result = pd.concat([outputs['conditions'], outputs['species'], outputs['directional_reactions']], axis = 'columns')
# data can be saved to avoid rerunning the simulation for data analysis (in most cases). these can be loaded using pandas.from_pickle() and pandas.from_csv()
result.to_pickle('cookbook_files/{}.pic'.format('run_simulation_example'))
result.to_csv('cookbook_files/{}.csv'.format('run_simulation_example'))
In [5]:
model_link = 'cookbook_files/model.cti'
# creates the cantera Solution object
solution = ctt.create_mechanism(model_link)
# finds initial mole fraction for a fuel-air ratio
mole_fractions = ctt.get_initial_mole_fractions(stoich_ratio = 1,
fuel_mole_ratios=[1],
oxygen_per_fuel_at_stoich_list = [5],
fuels = ['C3H8'])
# set initial conditions of solution in kelvin pascals and mole fractions
conditions = 950, 10**6, mole_fractions
solution.TPX = conditions
# run simulation
output_till_conversion = ctt.run_simulation_till_conversion(solution,
species='C3H8',
conversion=0.5,
condition_type = 'constant-temperature-and-pressure',
output_species = True,
output_reactions = True,
output_directional_reactions = True,
output_rop_roc = True,
skip_data = 25)
In [6]:
model_link = 'cookbook_files/model.cti'
# creates the cantera Solution object
solution = ctt.create_mechanism(model_link)
# finds initial mole fraction for a fuel-air ratio of 1 with 30%/70% methanol/propane blend
# for non-combustion conditions, this can be replaced by a dictionary of values {'CH3OH': 0.3, 'C3H8':0.7}
mole_fractions = ctt.get_initial_mole_fractions(stoich_ratio = 1,
fuel_mole_ratios = [.3,.7],
oxygen_per_fuel_at_stoich_list = [1.5,5],
fuels = ['CH3OH','C3H8'])
# set initial conditions of solution in kelvin pascals and mole fractions
conditions = 750, 10**6, mole_fractions
# run simulation
outputs = ctt.find_ignition_delay(solution, conditions,
output_profile = True,
output_directional_reactions = True,
skip_data = 1000)
# obtain the ignition delays
ignition_delay = outputs['ignition_delay']
Specific state variables (like temperature) can be set across a simulation.
To use this, change the condition_type to the string that describes the
situation (list of acceptable strings is described in the docstring of run_simulation.
Typically you also need to supply a list of the state variable to change which corresponds with the times in the times variable.
In [7]:
model_link = 'cookbook_files/model.cti'
# creates the cantera Solution object
solution = ctt.create_mechanism(model_link)
#initial mole fractions
mole_fractions = {'N2':5, 'O2':1, 'C3H8': 0.3}
# set initial conditions of solution in kelvin pascals and mole fractions
conditions = 800, 10**6, mole_fractions
solution.TPX = conditions
# store 100 times between 10^-8s and 0.01s, with an initial point at t=0
times = np.logspace(-8,-2,num=100)
times = np.insert(times,0,0)
# set a linear ramp temperature from 800 to 1000 at 1e-5s followed by constant temperature
ramp_temperatures = 800 + 2000000 * times[:50]
constant_temperatures = np.ones(51) * 1000
temperatures = np.concatenate((ramp_temperatures,constant_temperatures))
# run the simulation
outputs = ctt.run_simulation(solution, times,
condition_type = 'specified-temperature-constant-volume',
output_reactions = True,
output_directional_reactions = True,
output_rop_roc= False,
temperature_values = temperatures)
In [8]:
# this outputs a dataframe of just species
species = outputs['species']
reactions = outputs['net_reactions']
forward_and_reverse_reactions = outputs['directional_reactions']
net_observables = outputs['conditions']
# obtain reactions with a specific molecule
reactions_with_propane = ctt.find_reactions(df=reactions,
solution=solution,
species = 'C3H8')
In [9]:
species['C3H8'].plot()
Out[9]:
In [10]:
propane_production = ctt.consumption_pathways(df=reactions,
solution=solution,
species = 'C3H8')
In [11]:
f, ax = plt.subplots()
reactions_with_propane.plot.line(ax=ax)
import plot_tools as ptt
ptt.place_legend_outside_plot(axis=ax)
ax.set_ylabel('production rate (kmol/m3s)')
Out[11]:
In [12]:
# this outputs the branching ratio of propane
branching = ctt.branching_ratios(df=reactions,
solution=solution,
compound='C3H8')
In [13]:
f, ax = plt.subplots()
# plot only the top 6 branching ratios
branching.iloc[:,:6].plot.area(ax=ax)
import plot_tools as ptt
ptt.place_legend_outside_plot(axis=ax)
ax.set_ylabel('branching ratio')
Out[13]:
In [14]:
model_link = 'cookbook_files/model.cti'
solution = ctt.create_mechanism(model_link)
mole_fractions = {'N2':5, 'O2':1, 'C3H8': 0.3}
conditions = 800, 10**6, mole_fractions
solution.TPX = conditions
#only specify the times you want a flux diagram at
times = np.logspace(-8,0,num=3)
# run the simulation & create flux diagrams
outputs = ctt.save_flux_diagrams(solution, times,
condition_type = 'constant-temperature-and-pressure',
path='cookbook_files/',
filename='cookbook_fluxes',
filetype = 'svg',
element='C')