Atomistic Potentials¶
Machine-learning interatomic potentials (MLIPs) predict the energy of a set of atoms —
and, by differentiation, the forces and stress — from their positions and chemical
species. opifex builds them from the native E(3)-equivariant kit in
opifex.neural.equivariant, assembled through a small set of protocols so new
architectures and output properties plug in without touching existing code.
Design: backbone → heads¶
An opifex.neural.atomistic.AtomisticModel is composed of three swappable pieces:
- a backbone (the
Backboneprotocol) that turns aMolecularSystemand a neighbour graph into per-atom features; - one or more property heads (the
PropertyHeadprotocol) that map those features to physical outputs; - a neighbour list (the
NeighborListprotocol) that builds the edge graph within a cutoff radius.
Energy is an invariant scalar; forces are the conservative gradient F = −∂E/∂x
and stress is the virial from the strain derivative — both provided by ForcesHead and
StressHead, so any backbone gets correct, energy-conserving forces for free.
Backbones¶
| Backbone | Symmetry | Mechanism | Reference |
|---|---|---|---|
SchNet |
E(3)-invariant | continuous-filter convolutions on radial features | Schütt et al. 2018 (arXiv:1706.08566) |
PaiNN |
E(3)-equivariant (scalar + vector) | gated equivariant message passing | Schütt, Unke & Gastegger 2021 (arXiv:2102.03150) |
NequIP |
E(3)-equivariant (steerable tensors) | Clebsch–Gordan tensor-product convolutions on spherical-harmonic edges | Batzner et al. 2022 (arXiv:2101.03164) |
All three emit per-atom invariant scalar features for the energy head and are
registered under opifex.core.quantum.registry (register_backbone), so they can also
be built by name.
Example¶
import jax.numpy as jnp
import flax.nnx as nnx
from opifex.core.quantum.molecular_system import MolecularSystem
from opifex.core.quantum.protocols import RadiusNeighborList
from opifex.neural.atomistic import AtomisticModel
from opifex.neural.atomistic.backbones import NequIP, NequIPConfig
from opifex.neural.atomistic.heads import EnergyHead, ForcesHead
rngs = nnx.Rngs(0)
backbone = NequIP(
config=NequIPConfig(
hidden_irreps="32x0e + 8x1o",
sh_lmax=2,
num_interactions=2,
num_radial_basis=8,
cutoff=5.0,
),
rngs=rngs,
)
model = AtomisticModel(
backbone=backbone,
heads={"energy": EnergyHead(feature_dim=32, rngs=rngs), "forces": ForcesHead()},
neighbor_list=RadiusNeighborList(cutoff=5.0),
max_edges=64,
)
water = MolecularSystem(
atomic_numbers=jnp.array([8, 1, 1]),
positions=jnp.array([[0.0, 0.0, 0.0], [0.96, 0.0, 0.0], [-0.24, 0.93, 0.0]]),
)
prediction = model(water) # {"energy": (), "forces": (3, 3)}
The energy is invariant and the forces are equivariant under rotation, translation, and
permutation of identical atoms. Train the model with the energy+forces objective in
opifex.neural.atomistic.training (make_atomistic_train_step / fit_atomistic) against
reference energies and forces.
For an end-to-end example — downloading the rMD17 aspirin benchmark, normalizing energies, and training NequIP toward the published rMD17 @1000 energy/force accuracy with visualization — see NequIP on rMD17 (Aspirin).
Property heads¶
Each PropertyHead owns a single property family (opifex.neural.atomistic.heads):
EnergyHead— invariant total energyE = Σ_i ε_i.ForcesHead— conservative forcesF = −∇_r E(autodiff).StressHead— virial / stress via strain-displacement autodiff.ChargeHead— per-atom partial charges with total-charge conservation (Σ_i q_i = Q).DipoleHead— molecular dipoleμ = Σ_i q_i r_i(rotationally equivariant).EvidentialEnergyHead— single-pass uncertainty (below).
Single-pass uncertainty (evidential)¶
EvidentialEnergyHead predicts the Normal-Inverse-Gamma parameters of a Deep Evidential
Regression output (Amini et al. 2020; evidential interatomic potentials,
arXiv:2407.13994), giving per-prediction epistemic and
aleatoric uncertainty in one forward pass — no ensemble or dropout sampling. EvidentialAdapter
(or opifex.uncertainty.nig_to_predictive_distribution) maps its output to the platform
PredictiveDistribution, so it plugs into the existing opifex.uncertainty machinery
(calibration, active learning).
Fine-tuning foundation models¶
opifex.neural.atomistic.foundation provides the transfer-learning mechanism:
remap_element_table remaps a pretrained checkpoint's per-element parameters onto a new element
set, freeze_backbone / trainable_filter keep the backbone fixed while training new heads, and
LoRALinear / apply_lora add low-rank equivariant adapters (W_eff = W + (α/r)·B·A, after
MACE's lora.py) for parameter-efficient fine-tuning.
ASE calculator / MD¶
opifex.deployment.ase_calculator.OpifexCalculator wraps any AtomisticModel as an ASE
Calculator, driving ASE relaxations and molecular dynamics on the jitted forward path
(energies in eV, forces in eV/Å, stress as the Voigt 6-vector). Requires the optional ase
dependency.
Extending¶
- A new architecture — implement the
Backboneprotocol and decorate it with@register_backbone("name"); it composes with the existing heads unchanged. - A new output property (dipole, charges, …) — implement the
PropertyHeadprotocol and add it to the model'sheads. - Periodic systems — supply a periodic
Space(opifex.core.quantum.space); the conservative stress head uses the strain derivative.
The shared equivariant primitives — irreducible representations, Clebsch–Gordan tensor
products, spherical harmonics, gated nonlinearities, and radial bases — live in
opifex.neural.equivariant and are reused across the atomistic and
equivariant-property families.