QSM-style chain-of-states path optimizer for ASE with tangent-smoothed chain updates, climbing-image saddle search, adaptive redistribution, and SCF-failure resilience.
Project description
ase_qsm
QSM-style chain-of-states path optimizer for ASE.
ase_qsm optimizes discrete chain-of-states paths between two molecular
configurations.
Installation
pip install ase_qsm
From a source checkout:
git clone https://github.com/ss0832/ase_qsm
cd ase_qsm
pip install -e ".[dev]"
pytest
Requires Python 3.10+, NumPy 1.24+, SciPy 1.10+, ASE 3.23+.
Basic example
Prepare endpoint geometries as external structure files, for example
reactant.xyz and product.xyz. The two endpoint files must use the
same atom count and the same atom ordering; use auto_match_atoms=True
only when you intentionally want ase_qsm to reorder atoms before path
construction.
from ase.io import read
from ase.calculators.emt import EMT
from ase_qsm import QSM, finalize_path
reactant = read("reactant.xyz")
product = read("product.xyz")
# Replace EMT() with the calculator appropriate for the endpoint files.
calc = EMT()
# QSM with 11 images and explicit run/report settings.
# The run-level controls mirror the examples/08 suite invocation:
# --steps 32 --output-dir lst_reaction_suite_results --full-hessian-for none
qsm = QSM(
images=[reactant, product],
calculator=calc,
n_images=11,
fmax=0.05,
max_iter=32,
blend_ratio=0.5, # 50/50 FIRE/RFO
hessian_mode="model", # Fischer model Hessian per node
redistribute_interval=1, # redistribute nodes every 1 eligible steps
trajectory="qsm.traj",
)
qsm.run()
report = finalize_path(
qsm,
"results",
refine_ts=False,
full_hessian_for="none",
)
print("TS candidates:", report.ts_candidates)
for k, atoms in enumerate(qsm.images):
print(f"image {k}: E = {atoms.get_potential_energy():.6f} eV")
Additional usage patterns
Endpoint-only input can omit n_images. In that case the constructor
infers the initial image count from the configured pre-climb target
chord and minimum image count. Replace EMT() with the calculator
appropriate for the system.
from ase.io import read
from ase.calculators.emt import EMT
from ase_qsm import QSM
reactant = read("reactant.xyz")
product = read("product.xyz")
qsm = QSM([reactant, product], calculator=EMT(), fmax=0.05)
converged = qsm.run()
print("converged:", converged)
print("images:", len(qsm.images))
For a pre-built image stack, pass all images directly. The constructor
then ignores n_images and interpolation.
from ase.io import read
from ase.calculators.emt import EMT
from ase_qsm import QSM
images = read("initial_path.xyz", index=":")
qsm = QSM(images, calculator=EMT(), fix_endpoints="both")
qsm.run(steps=100)
Use QSMConfig when several controls should be recorded as one object.
The example below enables climbing-image selection and monitor
redistribution, while keeping final reporting limited by skipping
post-run Hessian and TS-refinement work.
from ase.io import read
from ase.calculators.emt import EMT
from ase_qsm import QSM, QSMConfig, finalize_path
reactant = read("reactant.xyz")
product = read("product.xyz")
calc = EMT()
cfg = QSMConfig(
climb=True,
climb_use_rsirfo=True,
max_climbers=3,
redistribute_method="monitor",
adaptive_image_insertion=True,
adaptive_max_images=40,
)
qsm = QSM([reactant, product], calculator=calc, config=cfg)
qsm.run()
report = finalize_path(
qsm,
"qsm_results",
refine_ts=False,
full_hessian_for="none",
)
print(report.ts_candidates)
By default, QSM.run() writes monitoring files under
qsm_path_history/. Set path_history_dir=None and
path_metrics_enabled=False for an in-memory-only run. If
path_history_dir=None but path metrics remain enabled, the metric CSVs
are written in the current working directory as qsm_path_metrics*.csv.
| File | Written by | Purpose |
|---|---|---|
qsm_path_history/path_initial.xyz |
constructor | Initial interpolated or supplied path with per-image metadata. |
qsm_path_history/path_iter_*.xyz |
accepted QSM iterations | One complete path snapshot per saved iteration. |
qsm_path_history/qsm.log |
constructor/run loop | Persistent text log in addition to logfile. |
qsm_path_history/path_metrics.csv |
accepted QSM iterations | Per-image diagnostics such as energy, force, chord, and role labels. |
qsm_path_history/path_metrics_summary.csv |
accepted QSM iterations | One summary row per saved iteration. |
qsm_path_history/path_metrics_wide.csv |
accepted QSM iterations | Wide-format monitoring table for plotting and spreadsheet inspection. |
Three or more input structures are treated as waypoints by default. The constructor uses the waypoint polyline as a guide and resamples it to the requested or inferred total image count. This can increase or decrease the number of supplied structures.
from ase.io import read
from ase.calculators.emt import EMT
from ase_qsm import QSM
waypoints = read("waypoints.xyz", index=":")
qsm = QSM(
waypoints,
calculator=EMT(),
n_images=17, # total images after waypoint resampling
interpolation="lst",
fix_endpoints="both",
)
qsm.run(steps=32)
For a pre-built image stack that should be preserved exactly, opt into
image-stack mode. In this mode the constructor ignores n_images and
interpolation.
from ase.io import read
from ase.calculators.emt import EMT
from ase_qsm import QSM
images = read("initial_path.xyz", index=":")
qsm = QSM(
images,
calculator=EMT(),
initial_path_input_mode="images",
fix_endpoints="both",
)
qsm.run(steps=32)
Reaction-path preset
For ordinary reaction-path searches, use the reaction_path preset rather
than specifying the full set of QSM controls manually. This preset mirrors the
settings used by examples/08_lst_reaction_suite.py and is intended as the
main practical entry point for molecular reaction paths.
from ase.io import read
from ase.calculators.emt import EMT
from ase_qsm import QSM, QSMConfig, finalize_path
reactant = read("reactant.xyz")
product = read("product.xyz")
calc = EMT()
cfg = QSMConfig.reaction_path(
steps=32, # QSM iteration limit used by the reaction-suite example
max_images=40, # optional upper bound for adaptive image insertion
)
qsm = QSM(
[reactant, product],
calculator=calc,
config=cfg,
)
qsm.run()
report = finalize_path(
qsm,
"results",
refine_ts=False,
full_hessian_for="none",
)
print("TS candidates:", report.ts_candidates)
References
-
ASE: Hjorth Larsen et al., The atomic simulation environment—A Python library for working with atoms. Journal of Physics: Condensed Matter 29, 273002 (2017). DOI: 10.1088/1361-648X/aa680e
-
ASE early interface paper: Bahn and Jacobsen, An object-oriented scripting interface to a legacy electronic structure code. Computing in Science & Engineering 4(3), 56–66 (2002). DOI: 10.1109/5992.998641
-
Quadratic String Method: Burger and Yang, Quadratic string method for determining the minimum-energy path based on multiobjective optimization. The Journal of Chemical Physics 124(5), 054109 (2006). DOI: 10.1063/1.2163875
License
GPL-3.0-or-later. See LICENSE and
NOTICE.md for details.
Copyright (C) 2026 ss0832.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ase_qsm-0.2.3.tar.gz.
File metadata
- Download URL: ase_qsm-0.2.3.tar.gz
- Upload date:
- Size: 232.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
532c25fcd046c817c9f8f428be9b6a1feb58944440671110cb702650bc4b7776
|
|
| MD5 |
47c3a1d46d432188205c7e8505402ff9
|
|
| BLAKE2b-256 |
b29a543c4ee9a56071b864e7ba2d14b5c73ee61d84229f66ec8720f94e8383a8
|
File details
Details for the file ase_qsm-0.2.3-py3-none-any.whl.
File metadata
- Download URL: ase_qsm-0.2.3-py3-none-any.whl
- Upload date:
- Size: 236.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fd963d4fc4959f0c0c5c267ed274cad0ba4a2bacacdee90eaf283352c75ab8c7
|
|
| MD5 |
f8cae3092a7fd1e3561d765ed98fcd51
|
|
| BLAKE2b-256 |
19fc98a8e1ae4eb47b86db1e0bb6b261d1702ba2ab4e23ca18b348656f4fc846
|