Skip to main content

mmff-rs

An extensible molecular-mechanics library in Rust, with a CLI, native Python bindings, and an ASE calculator.

It also provides PBC-aware substituent, ligand and linker editing, pure-Rust conformer search, and molecular-crystal packing. An arbitrary XYZ file can be edited: connectivity comes from covalent radii, and the bond orders are read from the geometry by the same pass the calculation path uses. Use SDF/MOL2/CIF/JSON when exact bond orders or coordination roles must be guaranteed rather than perceived.

Coordinate-only preparation uses a conservative second pass when the initial graph is incomplete: provisional multiple and aromatic orders are retained, and only neutral atoms that remain unresolved may gain slightly longer candidate bonds. The cutoff is never relaxed globally, and the preparation report records when this local recovery was needed.

Seven force fields run against provenance-recorded parameter tables, validated against RDKit or LAMMPS. Custom force fields are declarative. Periodic cells are general 3D triclinic. Coordinate, strain, and mixed derivatives are analytic at arbitrary order, from one Taylor kernel shared by every model.

Install

cargo build --release --bin mmff-rs
cargo install --path . --bin mmff-rs

Run those commands from the released source tree. v0.2.9 is distributed on PyPI and as a versioned source ZIP, not as a crates.io crate: Cargo's registry packaging would remove the root patches for the bundled Rust 1.87 and native link compatibility dependencies. publish = false prevents an incomplete crate from being uploaded accidentally.

Install the published Python wheel from PyPI:

pip install mmff-rs-python

For an editable source checkout:

pip install maturin && maturin develop --release

Quick start

mmff-rs energy molecule.sdf --force-field uff-1992
mmff-rs force-fields
mmff-rs optimize molecule.sdf --force-field mmff94 -o optimized.xyz
mmff-rs fragments
mmff-rs edit replace molecule.xyz --target serial:2 --fragment butyl -o products.sdf
mmff-rs edit resize complex.cif --target 'smarts:[CH2]' --fragment ethylene -o resized.cif
mmff-rs conformers molecule.sdf --mode diverse --count 100 --parallel-strategy auto -o conformers.sdf
mmff-rs pack molecule.sdf --space-group p1 --budget 20000 --parallel-strategy auto -o packings.cif
use mmff_rs::{Calculator, ForceFieldKind, read_structure};

let calculator = Calculator::builtin(ForceFieldKind::Mmff94)?;
let system = read_structure("molecule.sdf")?;
println!("{} Hartree", calculator.energy(&system)?);
# Ok::<(), mmff_rs::MmffError>(())
from ase.build import molecule
from mmff_rs.ase import MMFF

atoms = molecule("H2O")
atoms.calc = MMFF(force_field="mmff94")
print(atoms.get_potential_energy(), "eV")

The Cargo binary, Python console script, module entry point, and compatibility name all use the same Rust-backed unified parser and implementation:

mmff-rs --help
python -m mmff_rs --help
mmff_rs_cli --help

mmff-rs --help groups commands by purpose and includes quick examples; mmff-rs help <COMMAND> shows command-specific usage and units. The complete guide is docs/CLI.md.

mmff-rs models (also mmff-rs force-fields) prints the force fields known to the CLI together with availability and derivative/PBC capabilities.

Complex multi-point and ligand edits use a JSON or TOML EditRecipe. Built-in fragments number 182 (127 one-port, 51 two-port, two three-port, and two four-port); arbitrary fragments use mapped attachment wildcards such as [*:1]CC[*:2] or port-annotated JSON/TOML. JSON and CIF preserve stable IDs, bond roles, periodic images, and vacant coordination sites. CLI projection to XYZ, SDF, and MOL2 needs no --lossy; keep JSON or CIF when metadata must be represented. The categorized list is in docs/FRAGMENT_CATALOG.md.

Ambiguous replacement families are enumerated. For example, --fragment butyl returns n-, sec-, iso-, and tert-butyl products, and tied chemically distinct multi-port attachments are returned as separate candidates. Without -o, structure commands print JSON followed by Cartesian XYZ frames.

When a selector names the first atom of an acyclic substituent, replacement can expand to the smallest complete group with the required number of ports. Tied smallest regions are all returned. This inference never starts from or enters a ring: select a substituent root or a complete SMARTS region explicitly instead. Use --replacement-region-state-limit N to change the positive automatic-search limit (default 4096). Multiple-result commands print a NOTICE: and add candidate_notice to their JSON.

edit replace accepts repeated --target values as one selected region. This is the CLI route for three- and four-port fragments; for example, select all three methyl arms while retaining phosphorus and use --fragment ph-smap to build the three P-C-C-Si bridges of Ph-SMAP. v0.2.9 guarantees and tests one through four ports. edit insert intentionally remains a two-anchor linker operation.

For edit ligand --geometry auto, coordination number is the retained occupied sites plus every attachment port on every added fragment plus --vacant-sites. Thus one bidentate and one monodentate fragment select three-coordinate geometry; four-coordinate geometry remains ambiguous and must be specified explicitly.

ase_to_structure_document(atoms) uses the same Rust distance-and-valence bond inference as XYZ input when neither a bonds argument nor atoms.info["mmff_bonds"] is present. Pass bonds=[], or store an empty mmff_bonds list, to preserve an intentional empty bond graph without inference.

Full API reference with examples: docs/rust-api.md and docs/python-api.md.

Units

Rust, CLI, and native Python use atomic units: Hartree, bohr, electron charge, radians. The ASE adapter alone uses eV, Angstrom, and Kelvin.

Force fields

Model Identifier Scientific reference Parameter source Oracle
DREIDING 1990 dreiding-1990 10.1021/j100389a010 pysimm fb338141 (MIT) LAMMPS
UFF 1992 uff-1992 10.1021/ja00051a040 RDKit 56506230 (BSD-3) RDKit
GAFF 1.4 gaff-1 10.1002/jcc.20035 Amber via Open Babel 2.3.2 LAMMPS
OPLS-AA/L opls-aa-1996 10.1021/ja9621760 GROMACS v2025.4 (LGPL-2.1) LAMMPS
MMFF94 mmff94 Halgren, J. Comput. Chem. 1996, 17, I-V RDKit 56506230 (BSD-3) RDKit
ReaxFF reaxff-2010 10.1021/jp004368u fetch externally, see below LAMMPS
CLAYFF 2004 clayff-2004 10.1021/jp0363287 independent transcription LAMMPS
Custom custom -- your TOML/JSON pack --

Loading parameters

Three routes, all available from Rust, Python, and the CLI.

Bundled tables. Everything but ReaxFF works with no parameter file at all; the table is embedded and its SHA-256 is reported with every result.

mmff-rs energy molecule.sdf --force-field uff-1992

A ReaxFF ffield file. ReaxFF ships no bundled parameters, so fetch one externally: any file in the standard ffield.reax format works, whether from a LAMMPS checkout's potentials/ directory or from the supplementary material of the paper whose parameterisation you want. A ReaxFF pack is specific to its element set and training data, so that paper is the authority on what it may be applied to.

mmff-rs energy molecule.xyz --force-field reaxff-2010 --parameters ffield.reax.cho
let calculator = mmff_rs::Calculator::reaxff_from_ffield("ffield.reax.cho")?;
MMFFNativeCalculator(force_field="reaxff-2010", parameters="ffield.reax.cho")

A custom or overlaid pack. A TOML/JSON pack declares its own atom types, potential expressions and provenance. Layers merge field by field, so an overlay can patch one charge without restating the rest:

mmff-rs energy molecule.sdf --force-field custom \
  --parameters base.toml --parameter-overlay tweaks.json

Details: rust-api.md sections 2 and 12, python-api.md section 12, and data/README.md for each bundled table's provenance.

What it computes

Energy with a per-category breakdown, analytic gradients, Hessians, virial and stress; L-BFGS and steepest-descent optimization with a streaming trajectory; harmonic frequencies; and, for periodic systems, clamped and relaxed elastic constants, high-order elastic tensors, Gamma-point phonons, Gruneisen parameters, thermal expansion, piezoelectric tensors, and a Birch-Murnaghan equation of state.

Every calculation reports the parameter pack name and SHA-256 digest alongside the result, so a number can always be traced to the data that produced it.

Scope and limitations

Results depend on input bond orders, aromaticity labels, charge policy, atom types, and the selected parameter pack. Support for an element does not mean every chemical environment has been validated.

DREIDING is a generic rule-based force field for structure generation, initial relaxation, and approximate conformational assessment. It has no intrinsic charge model and can be ambiguous for transition-metal coordination. UFF has no charge model either, and rejects supplied partial charges rather than silently discarding them.

Fixed-topology models do not form or break bonds; ReaxFF is the reactive exception. CLAYFF environment types (ob, obos, obts, obss, oh, ohs) must be given explicitly, because coordinates and elements do not uniquely encode substitution sites.

The published parameter tables are not always complete. GAFF 1.4 tabulates no torsion across a cc/cd-to-ca bond, so a benzo-fused heteroaromatic such as tryptophan's indole reports a missing parameter; the Amber workflow fills these by analogy with parmchk2. This library does not guess. Supply the term through a custom parameter layer instead, and the number stays traceable to data you chose.

This release does not promise high-accuracy relative energies or reaction barriers.

References

Every force field and numerical method is implemented from the primary literature; no upstream engine is linked or called. The full citation list is in docs/REFERENCES.md, and the provenance of each imported parameter table -- source commit, licence, and SHA-256 -- is in docs/FORCE_FIELD_PROVENANCE.md.

Documentation

Document Contents
docs/rust-api.md Full Rust and CLI reference with examples
docs/python-api.md Full native-Python and ASE reference with examples
docs/EQUATIONS.md Functional-form mapping per model
docs/ATOM_TYPING.md Perception rules and their limits
docs/PERFORMANCE.md Timings, reproducing commands, parallel policy
docs/CONFORMER_BENCHMARK.md Conformer search against reference minima
docs/FORCE_FIELD_PROVENANCE.md Upstream revisions and digests
docs/REFERENCES.md Primary literature for every model and method
docs/PARAMETER_LICENSING.md Data rights policy
CHANGELOG.md Release history

License

Code is GPL-3.0-or-later.

Bundled parameter data keeps its own license and is not relicensed: MIT (pysimm), BSD-3-Clause (RDKit), LGPL-2.1 (GROMACS), and a public-domain claim (Amber/GAFF). The applicable notices ship under data/licenses/; per-table provenance and digests are in data/README.md.

Release files for mmff-rs-python 0.2.9

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mmff-rs-python 0.2.9
File Size Uploaded
mmff_rs_python-0.2.9.tar.gz 1.5 MB Details

Release files / mmff_rs_python-0.2.9.tar.gz

Download URL mmff_rs_python-0.2.9.tar.gz
Size 1.5 MB
Tags Source
SHA-256 checksum
How to use checksums
f01b9802b7508a01529a4ef58b5dcea8869bd53540b0161d6b00905ff3342ebe
BLAKE2b-256 checksum
How to use checksums
2d41e462597bc222233f77f4f1caca1aa682bf8250fb506b992c440c8e5737e9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.9

Release history Release notifications | RSS feed

This release

0.2.9 This release

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page