Phase B: machine-learned forcefields (2026-10-12)#
What was built#
xnn_step:
get_mdi_engine_command(..., mdi_method="MPI", checkpoint=, device=)returns the engine’s argv for an MPI pair:xnn mdi --ckpt <file> --device <device> <engine options> -mdi "-role ENGINE -name XNN -method MPI", with noconda runand no thread-count prefix. The engine runs in the driver’s (LAMMPS’s) environment, since the pair must share MPI and the MDI library.model_chemistry_option()describes one checkpoint;model_chemistry_for_checkpoint(path)does so for a checkpoint given by path, named after its stem, with the same refusal of dispersion removed twice.model_chemistry_step: two parameters that apply only to an MLFF (a rule shared by the dialog and the builder):
checkpoint: a path, relative to the job’s directory unless absolute, or a$variable. At run time it is described by the step that offers the owner’s MLFFs, and becomes the published model chemistry (xnn:MLFF@<stem>). With a checkpoint the model chosen need not be one of those listed; the builder leaves the check to the run.engine options: split withshlexintooptions["engine_args"].
lammps_step:
mlff_model_chemistry()andpytorch_model().ff_form()isPyTorchfor an MLFF model chemistry, so the existing PyTorch machinery applies unchanged: GPU polling, one pair per GPU, thefix mdi/qminput and the timing record._mlff_launch()writesmdi_launch.sh, which runs asbash mdi_launch.sh, as the QM path does. The script holds the pair (MLFF_PAIR, ormlff-codefrom lammps.ini):mpirun --bind-to none -np 1 {bind} {engine} : -np 1 {bind} lmp -mdi "..." -in input.dat, where{bind}is<root>/bin/mdi_bind.sh.{bind}and{engine}are filled in by Python, not by the executor’sstr.formatloop, because engine options can contain braces (--dispersion "{regime: large}").The device is
cuda:0, the GPU that mdi_bind.sh makes visible fromSEAMM_GPUS. Without a GPU it is xnn.ini’sdevice.A job allocated fewer than two MPI tasks is refused before launching.
The Forcefield step’s
.ptroute andgpu-codeare unchanged.
Validation#
mlff’s 1,554-atom NaCl(aq) box (512 H2O + 9 NaCl), with the ew10_s2 MACE-LES
model, its subtracted D4 added back and --eeq-reuse, was run as 1,000 steps of
NVT at 298.15 K with a 1 fs step. Falcon job 634309 (T4, fal144) ran both routes
one after the other on the same GPU:
old: a Forcefield step with the
.ptand lammps.ini’sgpu-code;new: a Model Chemistry step with
xnn:MLFF@ew10_s2, the checkpoint by path, and--eeq-reuseas an engine option.
Results:
Both exited 0, and
input.datwas identical.pe(0) was -1722.884 eV in both, matching mlff’s reference of -1722.88403 eV (xnn 0.11.1).
Energies and temperatures were identical to the printed precision through 0.4 ps, then diverged slowly, as float32 MD does: at most 0.02 eV at the printed 0.1 ps points by 1 ps.
Loop time for 1,000 steps: 412.0 s (old) and 412.7 s (new), i.e. 2.427 and 2.423 steps/s. The two launches are the same.
Left for later#
GUI narrowing (design 7, phase C): a Model Chemistry feeding LAMMPS lists only what LAMMPS can run.
The converter and the retirement of the Forcefield step’s dialog (phase C).
OpenKIM (
IP@), deferred by Paul.