Dictionary-Style Configuration#
eOn reads its parameters from a config.ini file in INI format. While writing
these files by hand works well for one-off runs, programmatic workflows benefit
from generating the configuration from Python dictionaries. The
write_eon_config() function in
rgpycrumbs handles this conversion.
All configuration options are documented in eon.schema, which is the
single source of truth for parameter names, types, defaults, and allowed values.
The user guide pages (e.g. General Simulation Parameters, Nudged Elastic Band)
render these Pydantic models directly.
Installation#
rgpycrumbs is available on PyPI:
pip install rgpycrumbs
# or
uv add rgpycrumbs
Basic Usage#
A dictionary maps INI section names to their key-value pairs. The section names
match the headers in config.ini (and the headings in the user guide). For
example, an AKMC run on a Pt heptamer:
from pathlib import Path
from rgpycrumbs.eon.helpers import write_eon_config
settings = {
"Main": {
"job": "akmc",
"temperature": 300,
},
"Potential": {
"potential": "morse_pt",
},
"Optimizer": {
"converged_force": 0.001,
"max_iterations": 1000,
},
"AKMC": {
"confidence": 0.95,
},
"Process Search": {
"minimize_first": True,
},
"Communicator": {
"type": "local",
"number_of_CPUs": 2,
"num_jobs": 2,
},
"Saddle Search": {
"displace_least_coordinated_weight": 1.0,
"displace_radius": 3.3,
"displace_magnitude": 0.1,
"min_mode_method": "dimer",
"max_energy": 10.0,
},
}
write_eon_config(Path("."), settings)
This writes a config.ini in the current directory. You can then run
python -m eon.server (or eonclient directly) as usual.
Tip
Pass a directory path and write_eon_config creates config.ini inside it.
Pass a full file path to control the output name.
Why Dictionaries?#
Compared to editing INI files by hand, the dictionary approach provides:
Reproducibility: the script is the configuration, checked into version control alongside the structure files.
Parameterization: loop over temperatures, spring constants, or image counts without duplicating INI files.
Validation reference: option names and types are defined in
eon.schema. Typos that would silently fall back to defaults in an INI file become obvious when compared against the schema documentation.Notebook integration: generate and run eOn configurations within Jupyter notebooks. The atomistic cookbook has a worked NEB example using this approach.
Examples by Job Type#
Each example directory under examples/ now contains both a config.ini and
a Python equivalent (run_*.py). The scripts are self-contained and can be
executed with:
cd examples/akmc-pt
python run_akmc_pt.py # generates config.ini
python -m eon.server # runs the simulation
AKMC#
:::::{tab-set}
::::{tab-item} Dictionary (Python)
"""AKMC simulation of Pt heptamer with dictionary-style configuration.
Equivalent to the config.ini in this directory. Uses the dimer method
for saddle searches with displacement biased towards the least
coordinated atom.
"""
from pathlib import Path
from rgpycrumbs.eon.helpers import write_eon_config
settings = {
"Main": {
"job": "akmc",
"temperature": 300,
},
"Potential": {
"potential": "morse_pt",
},
"Optimizer": {
"converged_force": 0.001,
"max_iterations": 1000,
},
"AKMC": {
"confidence": 0.95,
},
"Process Search": {
"minimize_first": True,
},
"Communicator": {
"type": "local",
"number_of_CPUs": 2,
"num_jobs": 2,
},
"Saddle Search": {
"displace_least_coordinated_weight": 1.0,
"displace_radius": 3.3,
"displace_magnitude": 0.1,
"min_mode_method": "dimer",
"max_energy": 10.0,
},
}
if __name__ == "__main__":
write_eon_config(Path("."), settings)
::::
::::{tab-item} INI
[Main]
job = akmc
temperature = 300
[Potential]
potential = morse_pt
[Optimizer]
converged_force = 0.001
max_iterations = 1000
[AKMC]
confidence = 0.95
[Process Search]
minimize_first = true
[Communicator]
type = local
number_of_CPUs = 2
num_jobs=2
[Saddle Search]
displace_least_coordinated_weight=1.0
displace_radius = 3.3
displace_magnitude= 0.1
min_mode_method = dimer
max_energy = 10.0
::::
:::::
NEB#
:::::{tab-set}
::::{tab-item} Dictionary (Python)
"""Nudged elastic band calculation with dictionary-style configuration.
Equivalent to the config.ini in this directory. Runs an NEB calculation
on Al with 7 intermediate images and LBFGS optimization.
"""
from pathlib import Path
from rgpycrumbs.eon.helpers import write_eon_config
settings = {
"Main": {
"job": "nudged_elastic_band",
},
"Potential": {
"potential": "eam_al",
},
"Nudged Elastic Band": {
"images": 7,
"spring": 5.0,
},
"Optimizer": {
"max_iterations": 1000,
"opt_method": "lbfgs",
"max_move": 0.1,
"converged_force": 0.001,
},
}
if __name__ == "__main__":
write_eon_config(Path("."), settings)
::::
::::{tab-item} INI
[Main]
job = nudged_elastic_band
[Potential]
potential = eam_al
[Nudged Elastic Band]
images = 7
spring = 5.0
[Optimizer]
max_iterations = 1000
opt_method = lbfgs
max_move = 0.1
converged_force = 0.001
::::
:::::
For advanced NEB options (climbing image, energy-weighted springs, IDPP
initialization, off-path CI with MMF), see
examples/neb-al/run_neb_advanced.py.
Basin Hopping#
:::::{tab-set}
::::{tab-item} Dictionary (Python)
"""Basin hopping global optimization with dictionary-style configuration.
Equivalent to the config.ini in this directory. Searches for the global
minimum of a Lennard-Jones cluster at 2000 K using Gaussian-distributed
displacements.
"""
from pathlib import Path
from rgpycrumbs.eon.helpers import write_eon_config
settings = {
"Main": {
"job": "basin_hopping",
"temperature": 2000,
},
"Communicator": {
"type": "local",
},
"Potential": {
"potential": "lj",
},
"Basin Hopping": {
"steps": 100,
"displacement": 0.25,
"significant_structure": True,
"displacement_distribution": "gaussian",
},
"Optimizer": {
"opt_method": "cg",
"converged_force": 0.01,
"max_iterations": 10000,
},
}
if __name__ == "__main__":
write_eon_config(Path("."), settings)
::::
::::{tab-item} INI
[Main]
job=basin_hopping
temperature=2000
[Communicator]
type = local
client_path=../../client/eonclient
[Potential]
potential=lj
[Basin Hopping]
steps=100
displacement=0.25
significant_structure=true
displacement_distribution=gaussian
[Optimizer]
opt_method=cg
converged_force=0.01
max_iterations=10000
::::
:::::
Parallel Replica Dynamics#
:::::{tab-set}
::::{tab-item} Dictionary (Python)
"""Parallel replica dynamics with dictionary-style configuration.
Equivalent to the config.ini in this directory. Runs parallel replica
dynamics on an Al(100) surface with an Andersen thermostat at 500 K.
"""
from pathlib import Path
from rgpycrumbs.eon.helpers import write_eon_config
settings = {
"Main": {
"job": "parallel_replica",
"temperature": 500,
"random_seed": 1042,
},
"Potential": {
"potential": "eam_al",
},
"Communicator": {
"type": "local",
"number_of_cpus": 1,
"num_jobs": 2,
},
"Dynamics": {
"time_step": 1.0,
"time": 5000.0,
"thermostat": "andersen",
"andersen_alpha": 0.2,
"andersen_collision_period": 10.0,
},
"Parallel Replica": {
"dephase_time": 1000.0,
"state_check_interval": 3000.0,
"state_save_interval": 1000.0,
"post_transition_time": 200.0,
"stop_after_transition": False,
},
"Optimizer": {
"opt_method": "cg",
"converged_force": 0.005,
},
}
if __name__ == "__main__":
write_eon_config(Path("."), settings)
::::
::::{tab-item} INI
[Main]
job = parallel_replica
temperature = 500
random_seed = 1042
[Potential]
potential = eam_al
[Communicator]
type = local
number_of_cpus = 1
num_jobs = 2
[Dynamics]
time_step = 1.0
time = 5000.0
thermostat = andersen
andersen_alpha = 0.2
andersen_collision_period = 10.0
[Parallel Replica]
dephase_time = 1000.0
state_check_interval = 3000.0
state_save_interval = 1000.0
post_transition_time = 200.0
stop_after_transition = false
[Optimizer]
opt_method = cg
converged_force = 0.005
::::
:::::
AKMC with Displacement Script#
The Cu vacancy example shows how dictionary config works alongside a
displacement script (ptmdisp.py). The script path is just another string
parameter:
"Saddle Search": {
"displace_atom_kmc_state_script": "ptmdisp.py",
"displace_all_listed": True,
# ...
},
See examples/akmc-cu-vacancy/run_akmc_cu.py for the full configuration and
Targeted Displacement for Saddle Searches for details on writing displacement scripts.
Parameter Sweeps#
The dictionary approach makes parameter sweeps straightforward:
from pathlib import Path
from rgpycrumbs.eon.helpers import write_eon_config
base = {
"Main": {"job": "nudged_elastic_band"},
"Potential": {"potential": "eam_al"},
"Optimizer": {
"opt_method": "lbfgs",
"max_move": 0.1,
"converged_force": 0.001,
"max_iterations": 1000,
},
}
for n_images in [5, 7, 11, 15]:
run_dir = Path(f"neb_{n_images}img")
run_dir.mkdir(exist_ok=True)
settings = {
**base,
"Nudged Elastic Band": {
"images": n_images,
"spring": 5.0,
},
}
write_eon_config(run_dir, settings)
Schema Reference#
The authoritative documentation for every configuration option lives in the
Pydantic models in eon.schema. The user guide pages render these models
automatically:
General Simulation Parameters – general simulation parameters
Adaptive Kinetic Monte Carlo – adaptive kinetic Monte Carlo
Nudged Elastic Band – nudged elastic band
Saddle Search – saddle search methods
Optimizer – optimization algorithms
Potential – interatomic potentials
Dynamics – molecular dynamics
Parallel Replica – parallel replica dynamics
Basin Hopping – basin hopping
Communicator – job communicators