Reaction model
Overview
The ReactionModel contains the information about each elementary step. It supports different types of steps:
Non-activated adsorption
Activated adsorption
Non-activated desorption
Surface reactions or diffusions
Required columns
initial(listofstr): Initial configuration in Zacros format (e.g.,['1 CO* 1', '2 * 1']).final(listofstr): Final configuration in Zacros format (e.g.,['1 C* 1', '2 O* 1']).activ_eng(float): Activation energy in electronvolts (eV).vib_energies_is(listoffloat): Vibrational energies for the initial state in millielectronvolts (meV), excluding the zero-point energy (ZPE).vib_energies_fs(listoffloat): Vibrational energies for the final state in meV, excluding the ZPE.
Additional required columns (when applicable)
When any gas species participates (adsorption/desorption/exchange):
area_site(float): Area of the adsorption site in Ų.
When a gas species is present in the initial state (IS):
molecule_is(str): Gas-phase molecule in the initial state (e.g. adsorption).
When a gas species is present in the final state (FS):
molecule_fs(str): Gas-phase molecule in the final state (e.g. desorption).
Activated steps (activated adsorption, surface reactions):
vib_energies_ts(list[float]): Vibrational energies for the transition state in meV (no ZPE).
For non-activated steps, this may be omitted or set to[].
Deprecation note: The old
moleculecolumn is deprecated. If provided, it is treated asmolecule_isand aDeprecationWarningis issued.
Optional columns
site_types(str): Types of each site in the reaction pattern. Required iflattice_typeis'periodic_cell'.neighboring(str): Connectivity between sites involved (e.g.,'1-2').prox_factor(float): Proximity factor.angles(str): Angle constraints between sites in Zacros format (e.g.,'1-2-3:180').graph_multiplicity(intorfloat): Symmetry factor of the step. The computed pre-exponential factor will be divided by this value. Useful for symmetric steps like diffusion on equivalent sites.fixed_pre_expon(float): Optional fixed forward pre-exponential factor to write as-is (no scaling / no graph multiplicity applied). Units must match Zacros expectations: surface/non-activated desorption ins^-1; adsorption (activated/non-activated) inbar^-1·s^-1.fixed_pe_ratio(float): Optional fixed pre-exponential ratiope_fwd/pe_revto write as-is. Must be provided together withfixed_pre_expon.
Example data table
index |
activ_eng |
area_site |
final |
graph_multiplicity |
initial |
molecule_is |
neighboring |
prox_factor |
site_types |
vib_energies_fs |
vib_energies_is |
vib_energies_ts |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
aO2_HfC |
0.0 |
5.34 |
[‘1 O* 1’, ‘2 O* 1’] |
NaN |
[‘1 * 1’, ‘2 * 1’] |
O2 |
1-2 |
0.0 |
tC tC |
[78.662275, 40.796289, 40.348665, 78.662275, 40.796289, 40.348665] |
[194.605883] |
[] |
aCO_HfC |
0.0 |
5.34 |
[‘1 CO* 1’] |
NaN |
[‘1 * 1’] |
CO |
NaN |
0.0 |
tC |
[240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359] |
[263.427949] |
[] |
aCO2_HfC |
0.0 |
5.34 |
[‘1 CO2* 1’] |
NaN |
[‘1 * 1’] |
CO2 |
NaN |
0.0 |
tC |
[171.188002, 145.668886, 96.963691, 86.25514, 56.201368, 52.375682, 35.933392, 24.342963, 21.024922] |
[293.279791, 163.611086, 78.016609, 77.959489] |
[] |
fCO_HfC |
1.3251912539165005 |
NaN |
[‘1 CO* 1’, ‘2 * 1’] |
NaN |
[‘1 C* 1’, ‘2 O* 1’] |
NaN |
1-2 |
NaN |
tC tC |
[240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359] |
[138.207451, 24.592242, 17.986572, 78.662275, 40.796289, 40.348665] |
[129.799624, 55.940895, 41.760039, 33.292377, 20.816034] |
bCO2_HfC |
1.6930197990402576 |
NaN |
[‘1 CO* 1’, ‘2 O* 1’] |
NaN |
[‘1 CO2* 1’, ‘2 * 1’] |
NaN |
1-2 |
NaN |
tC tC |
[240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359, 78.662275, 40.796289, 40.348665] |
[171.188002, 145.668886, 96.963691, 86.25514, 56.201368, 52.375682, 35.933392, 24.342963, 21.024922] |
[217.940927, 81.361728, 66.833494, 56.917831, 50.342099, 37.430358, 19.074043, 12.356398] |
dCO_HfC |
1.156349999999975 |
NaN |
[‘1 * 1’, ‘2 CO* 1’] |
2.0 |
[‘1 CO* 1’, ‘2 * 1’] |
NaN |
1-2 |
NaN |
tC tC |
[240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359] |
[240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359] |
[218.382388, 53.526855, 47.6122, 28.580404, 6.599679] |
dO_HfC |
1.220541240457237 |
NaN |
[‘1 * 1’, ‘2 O* 1’] |
2.0 |
[‘1 O* 1’, ‘2 * 1’] |
NaN |
1-2 |
NaN |
tC tC |
[78.662275, 40.796289, 40.348665] |
[78.662275, 40.796289, 40.348665] |
[56.617104, 49.715199] |
dC_HfC |
1.4489481277169034 |
NaN |
[‘1 * 1’, ‘2 C* 1’] |
NaN |
[‘1 C* 1’, ‘2 * 1’] |
NaN |
1-2 |
NaN |
tC tC |
[138.207451, 24.592242, 17.986572] |
[138.207451, 24.592242, 17.986572] |
[85.015794, 66.512731] |
Creating a ReactionModel
You can create a ReactionModel instance in several ways:
From a dictionary
From a CSV file
From a Pandas DataFrame
1. From a dictionary
Provide a dictionary where each key is a reaction step name and each value is a dictionary of step properties.
Example
from zacrostools.reaction_model import ReactionModel
# Define the reaction steps data
steps_data = {
'aO2_HfC': {
'activ_eng': 0.0,
'area_site': 5.34,
'final': ['1 O* 1', '2 O* 1'],
'initial': ['1 * 1', '2 * 1'],
'molecule_is': 'O2',
'neighboring': '1-2',
'prox_factor': 0.0,
'site_types': 'tC tC',
'vib_energies_fs': [78.662275, 40.796289, 40.348665, 78.662275, 40.796289, 40.348665],
'vib_energies_is': [194.605883],
'vib_energies_ts': []
},
'aCO_HfC': {
'activ_eng': 0.0,
'area_site': 5.34,
'final': ['1 CO* 1'],
'initial': ['1 * 1'],
'molecule_is': 'CO',
'prox_factor': 0.0,
'site_types': 'tC',
'vib_energies_fs': [240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359],
'vib_energies_is': [263.427949],
'vib_energies_ts': []
},
'aCO2_HfC': {
'activ_eng': 0.0,
'area_site': 5.34,
'final': ['1 CO2* 1'],
'initial': ['1 * 1'],
'molecule_is': 'CO2',
'prox_factor': 0.0,
'site_types': 'tC',
'vib_energies_fs': [171.188002, 145.668886, 96.963691, 86.25514, 56.201368, 52.375682, 35.933392, 24.342963, 21.024922],
'vib_energies_is': [293.279791, 163.611086, 78.016609, 77.959489],
'vib_energies_ts': []
},
'fCO_HfC': {
'activ_eng': 1.3251912539165005,
'final': ['1 CO* 1', '2 * 1'],
'initial': ['1 C* 1', '2 O* 1'],
'neighboring': '1-2',
'site_types': 'tC tC',
'vib_energies_fs': [240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359],
'vib_energies_is': [138.207451, 24.592242, 17.986572, 78.662275, 40.796289, 40.348665],
'vib_energies_ts': [129.799624, 55.940895, 41.760039, 33.292377, 20.816034]
},
'bCO2_HfC': {
'activ_eng': 1.6930197990402576,
'final': ['1 CO* 1', '2 O* 1'],
'initial': ['1 CO2* 1', '2 * 1'],
'neighboring': '1-2',
'site_types': 'tC tC',
'vib_energies_fs': [240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359, 78.662275, 40.796289, 40.348665],
'vib_energies_is': [171.188002, 145.668886, 96.963691, 86.25514, 56.201368, 52.375682, 35.933392, 24.342963, 21.024922],
'vib_energies_ts': [217.940927, 81.361728, 66.833494, 56.917831, 50.342099, 37.430358, 19.074043, 12.356398]
},
'dCO_HfC': {
'activ_eng': 1.156349999999975,
'final': ['1 * 1', '2 CO* 1'],
'initial': ['1 CO* 1', '2 * 1'],
'neighboring': '1-2',
'graph_multiplicity': 2.0,
'site_types': 'tC tC',
'vib_energies_fs': [240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359],
'vib_energies_is': [240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359],
'vib_energies_ts': [218.382388, 53.526855, 47.6122, 28.580404, 6.599679]
},
'dO_HfC': {
'activ_eng': 1.220541240457237,
'final': ['1 * 1', '2 O* 1'],
'initial': ['1 O* 1', '2 * 1'],
'neighboring': '1-2',
'graph_multiplicity': 2.0,
'site_types': 'tC tC',
'vib_energies_fs': [78.662275, 40.796289, 40.348665],
'vib_energies_is': [78.662275, 40.796289, 40.348665],
'vib_energies_ts': [56.617104, 49.715199]
},
'dC_HfC': {
'activ_eng': 1.4489481277169034,
'final': ['1 * 1', '2 C* 1'],
'initial': ['1 C* 1', '2 * 1'],
'neighboring': '1-2',
'site_types': 'tC tC',
'vib_energies_fs': [138.207451, 24.592242, 17.986572],
'vib_energies_is': [138.207451, 24.592242, 17.986572],
'vib_energies_ts': [85.015794, 66.512731]
}
}
# Create the ReactionModel instance
reaction_model = ReactionModel.from_dict(steps_data)
2. From a CSV File
Load reaction steps data from a CSV file. The CSV should have the required columns and use the reaction step names as the index.
Example CSV (mechanism_data.csv)
,index,activ_eng,area_site,final,graph_multiplicity,initial,molecule_is,neighboring,prox_factor,site_types,vib_energies_fs,vib_energies_is,vib_energies_ts
aO2_HfC,0.0,5.34,"['1 O* 1', '2 O* 1']",,"['1 * 1', '2 * 1']",O2,1-2,0.0,"tC tC","[78.662275, 40.796289, 40.348665, 78.662275, 40.796289, 40.348665]",[194.605883],[]
aCO_HfC,0.0,5.34,"['1 CO* 1']",,"['1 * 1']",CO,,0.0,tC,"[240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359]",[263.427949],[]
aCO2_HfC,0.0,5.34,"['1 CO2* 1']",,"['1 * 1']",CO2,,0.0,tC,"[171.188002, 145.668886, 96.963691, 86.25514, 56.201368, 52.375682, 35.933392, 24.342963, 21.024922]","[293.279791, 163.611086, 78.016609, 77.959489]",[]
fCO_HfC,1.3251912539165005,,"['1 CO* 1', '2 * 1']",,"['1 C* 1', '2 O* 1']",,1-2,, "tC tC","[240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359]","[138.207451, 24.592242, 17.986572, 78.662275, 40.796289, 40.348665]","[129.799624, 55.940895, 41.760039, 33.292377, 20.816034]"
bCO2_HfC,1.6930197990402576,,"['1 CO* 1', '2 O* 1']",,"['1 CO2* 1', '2 * 1']",,1-2,, "tC tC","[240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359, 78.662275, 40.796289, 40.348665]","[171.188002, 145.668886, 96.963691, 86.25514, 56.201368, 52.375682, 35.933392, 24.342963, 21.024922]","[217.940927, 81.361728, 66.833494, 56.917831, 50.342099, 37.430358, 19.074043, 12.356398]"
dCO_HfC,1.156349999999975,,"['1 * 1', '2 CO* 1']",2.0,"['1 CO* 1', '2 * 1']",,1-2,, "tC tC","[240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359]","[240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359]","[218.382388, 53.526855, 47.6122, 28.580404, 6.599679]"
dO_HfC,1.220541240457237,,"['1 * 1', '2 O* 1']",2.0,"['1 O* 1', '2 * 1']",,1-2,, "tC tC","[78.662275, 40.796289, 40.348665]","[78.662275, 40.796289, 40.348665]","[56.617104, 49.715199]"
dC_HfC,1.4489481277169034,,"['1 * 1', '2 C* 1']",,"['1 C* 1', '2 * 1']",,1-2,, "tC tC","[138.207451, 24.592242, 17.986572]","[138.207451, 24.592242, 17.986572]","[85.015794, 66.512731]"
Loading from CSV
from zacrostools.reaction_model import ReactionModel
# Create the ReactionModel instance from a CSV file
reaction_model = ReactionModel.from_csv('mechanism_data.csv')
3. From a Pandas DataFrame
If you have a DataFrame containing the reaction steps data, you can create a ReactionModel directly.
Example
import pandas as pd
from zacrostools.reaction_model import ReactionModel
data = {
'activ_eng': [0.0, 0.0, 0.0, 1.3251912539165005, 1.6930197990402576, 1.156349999999975, 1.220541240457237, 1.4489481277169034],
'area_site': [5.34, 5.34, 5.34, None, None, None, None, None],
'final': [
['1 O* 1', '2 O* 1'],
['1 CO* 1'],
['1 CO2* 1'],
['1 CO* 1', '2 * 1'],
['1 CO* 1', '2 O* 1'],
['1 * 1', '2 CO* 1'],
['1 * 1', '2 O* 1'],
['1 * 1', '2 C* 1']
],
'graph_multiplicity': [None, None, None, None, None, 2.0, 2.0, None],
'initial': [
['1 * 1', '2 * 1'],
['1 * 1'],
['1 * 1'],
['1 C* 1', '2 O* 1'],
['1 CO2* 1', '2 * 1'],
['1 CO* 1', '2 * 1'],
['1 O* 1', '2 * 1'],
['1 C* 1', '2 * 1']
],
'molecule_is': ['O2', 'CO', 'CO2', None, None, None, None, None],
'neighboring': ['1-2', None, None, '1-2', '1-2', '1-2', '1-2', '1-2'],
'prox_factor': [0.0, 0.0, 0.0, None, None, None, None, None],
'site_types': ['tC tC', 'tC', 'tC', 'tC tC', 'tC tC', 'tC tC', 'tC tC', 'tC tC'],
'vib_energies_fs': [
[78.662275, 40.796289, 40.348665, 78.662275, 40.796289, 40.348665],
[240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359],
[171.188002, 145.668886, 96.963691, 86.25514, 56.201368, 52.375682, 35.933392, 24.342963, 21.024922],
[240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359],
[240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359, 78.662275, 40.796289, 40.348665],
[240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359],
[78.662275, 40.796289, 40.348665],
[138.207451, 24.592242, 17.986572]
],
'vib_energies_is': [
[194.605883],
[263.427949],
[293.279791, 163.611086, 78.016609, 77.959489],
[138.207451, 24.592242, 17.986572, 78.662275, 40.796289, 40.348665],
[171.188002, 145.668886, 96.963691, 86.25514, 56.201368, 52.375682, 35.933392, 24.342963, 21.024922],
[240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359],
[78.662275, 40.796289, 40.348665],
[138.207451, 24.592242, 17.986572]
],
'vib_energies_ts': [
[],
[],
[],
[129.799624, 55.940895, 41.760039, 33.292377, 20.816034],
[217.940927, 81.361728, 66.833494, 56.917831, 50.342099, 37.430358, 19.074043, 12.356398],
[218.382388, 53.526855, 47.6122, 28.580404, 6.599679],
[56.617104, 49.715199],
[85.015794, 66.512731]
]
}
df = pd.DataFrame(data, index=[
'aO2_HfC',
'aCO_HfC',
'aCO2_HfC',
'fCO_HfC',
'bCO2_HfC',
'dCO_HfC',
'dO_HfC',
'dC_HfC'
])
# Create the ReactionModel instance
reaction_model = ReactionModel.from_df(df)
Adding and removing steps
You can modify an existing model programmatically.
Adding a step
new_step = {
'step_name': 'new_step',
'activ_eng': 2.0,
'final': ['1 * 1'],
'initial': ['1 CO* 1'],
'vib_energies_is': [150, 200],
'vib_energies_fs': [100, 150],
'vib_energies_ts': [125],
'site_types': 'tC'
}
reaction_model.add_step(step_info=new_step)
Removing steps
steps_to_remove = ['aCO_HfC']
reaction_model.remove_steps(steps_to_remove)
Writing the mechanism_input.dat file
The ReactionModel can generate the mechanism_input.dat file required by Zacros.
Method
reaction_model.write_mechanism_input(
output_dir,
temperature,
gas_model,
manual_scaling=None,
stiffness_scalable_steps=None,
stiffness_scalable_symmetric_steps=None,
sig_figs_energies=8,
sig_figs_pe=8
)
output_dir(strorPath): Directory where the file will be written.temperature(float): Temperature in Kelvin for pre-exponential calculations.gas_model(GasModel): Instance ofGasModelcontaining gas-phase species data.manual_scaling(dict, optional): Dictionary of manual scaling factors per step.stiffness_scalable_steps(list, optional): List of steps that are stiffness scalable.stiffness_scalable_symmetric_steps(list, optional): List of steps that are stiffness scalable and symmetric.sig_figs_energies(int, optional): Number of significant figures for activation energies.sig_figs_pe(int, optional): Number of significant figures for pre-exponential factors.
Example
from zacrostools.gas_model import GasModel
# Assume gas_model is already defined
gas_model = GasModel.from_csv('gas_data.csv')
# Write the mechanism_input.dat file
reaction_model.write_mechanism_input(
output_dir='kmc_simulation',
temperature=500,
gas_model=gas_model,
sig_figs_energies=8,
sig_figs_pe=8
)
Accessing reaction data
The reaction steps data is stored internally as a Pandas DataFrame, accessible via the df attribute.
Example
# View the reaction steps data
print(reaction_model.df)
Full example
Below is a complete example demonstrating the creation and modification of a ReactionModel:
from zacrostools.reaction_model import ReactionModel
from zacrostools.gas_model import GasModel
# Assume gas_model is already defined
gas_model = GasModel.from_csv('gas_data.csv')
# Initial reaction steps data
steps_data = {
'aO2_HfC': {
'activ_eng': 0.0,
'area_site': 5.34,
'final': ['1 O* 1', '2 O* 1'],
'initial': ['1 * 1', '2 * 1'],
'molecule_is': 'O2',
'neighboring': '1-2',
'prox_factor': 0.0,
'site_types': 'tC tC',
'vib_energies_fs': [78.662275, 40.796289, 40.348665, 78.662275, 40.796289, 40.348665],
'vib_energies_is': [194.605883],
'vib_energies_ts': []
}
}
# Create the ReactionModel instance
reaction_model = ReactionModel.from_dict(steps_data)
# Add a new step
reaction_model.add_step(step_info={
'step_name': 'aCO_HfC',
'activ_eng': 0.0,
'area_site': 5.34,
'final': ['1 CO* 1'],
'initial': ['1 * 1'],
'molecule_is': 'CO',
'prox_factor': 0.0,
'site_types': 'tC',
'vib_energies_fs': [240.497465, 82.738219, 60.132962, 60.080258, 7.271753, 6.553359],
'vib_energies_is': [263.427949],
'vib_energies_ts': []
})
# Remove an existing step
reaction_model.remove_steps(['aO2_HfC'])
# Write the mechanism input file
reaction_model.write_mechanism_input(
output_dir='kmc_simulation',
temperature=500,
gas_model=gas_model,
sig_figs_energies=8,
sig_figs_pe=8
)
# Access the DataFrame
print(reaction_model.df)
Fixing pre-exponential factors
By default, ReactionModel computes the forward pre-exponential factor (pre_expon) and the pre-exponential ratio (pe_ratio) from statistical mechanics.
However, in some cases you may want to fix these values explicitly (for both forward and reverse directions). This can be done by providing two optional parameters:
fixed_pre_expon(float): User-specified forward pre-exponential factor.fixed_pe_ratio(float): User-specified pre-exponential ratio.
⚠️ Important:
If one of these parameters is provided, the other must also be provided.
Using
fixed_pre_expon/fixed_pe_ratiois incompatible with:Setting
stiffness_scalable_steps="all".Including a fixed step in
stiffness_scalable_steps.Including a fixed step in
stiffness_scalable_symmetric_steps.
If any of these conditions occur, a ReactionModelError is raised.
Example
from zacrostools.reaction_model import ReactionModel
reaction_data = {
'CO_ads': {
'activ_eng': 0.0,
'area_site': 6.54,
'initial': ['1 * 1'],
'final': ['1 CO* 1'],
'molecule_is': 'CO',
'prox_factor': 0.0,
'vib_energies_is': [263],
'vib_energies_fs': [253, 40, 36, 33, 7, 5],
"fixed_pre_expon": 1.0e13, # in s^-1 or bar^-1·s^-1 depending on type
"fixed_pe_ratio": 2.5
}
}
reaction_model = ReactionModel.from_dict(reaction_data)
Next Steps
With the ReactionModel defined, you can proceed to:
Create a
LatticeModelAssemble the
KMCModel
For detailed guidance on these steps, refer to the respective sections in the documentation.