Development Plan: QM/MD via MDI in SEAMM — MOPAC First#
- Author:
Paul Saxe (plan drafted with Claude)
- Date:
2026-06-11
- Status:
Proposed
Overview#
This document describes a plan to enable QM-driven molecular dynamics in SEAMM, using LAMMPS as the MD driver and a quantum-chemistry code (initially MOPAC, later xTB and others) as the energy/force engine via the MolSSI Driver Interface (MDI).
Key insight from the MOPAC source tree: MOPAC already contains a
native MDI engine implementation, built when MOPAC is compiled with
the CMake option -DMDI=ON (see
https://openmopac.net/about/software/#mdi). This means no Python wrapper
is needed for MOPAC — the MOPAC executable itself acts as the MDI engine
once it is started with the appropriate -mdi flag. This is fundamentally
different from the MACE case, where a Python engine script was required
because mace-torch has no built-in MDI support.
Architecture#
Runtime picture#
LAMMPS (driver) <──MPI/MDI──> MOPAC (engine)
fix mdi/qm native MDI loop
No pair_style PM7 / PM6-ORG / AM1 / …
Verlet / Nosé-Hoover reads .mop for Hamiltonian settings
NVT, NPT receives coords+cell, returns E, F, σ
Both processes share one MPI_COMM_WORLD via the mpirun colon syntax.
MDI_Init splits it into sub-communicators.
Launch command#
mpirun --mca mpi_yield_when_idle 1 \
-np 1 mopac mopac.mop \
-mdi "-role ENGINE -name MOPAC -method MPI" \
: -np 1 lmp \
-mdi "-role DRIVER -name LAMMPS -method MPI" \
-in input.dat
MOPAC reads mopac.mop for its Hamiltonian and keyword settings, then
enters its MDI event loop. LAMMPS drives the MD, sending >COORDS (and
>CELL for periodic systems) each step and requesting <ENERGY,
<FORCES, and (when virial yes) <STRESS.
MOPAC MDI command support (from the MDI Mechanic test report)#
The openmopac/MDI_MOPAC_test repository reports MOPAC’s MDI command
support at the @DEFAULT node:
Supported (green):
<ENERGY, <FORCES, <STRESS, >COORDS, >CELL,
<CHARGES, <COORDS, <CELL, <DIMENSIONS, <CELL_DISPL,
<ELEC_MULT, <ELEMENTS, <MASSES, <NAME, <NATOMS,
<TOTCHARGE, <@
Not yet supported (gray):
EXIT, >TOTCHARGE, >ELEC_MULT, >CELL_DISPL, >CHARGES,
>MASSES, >STRESS, >FORCES, >ENERGY, <KE,
<PE, <VELOCITIES, @INIT_MD, @INIT_MC, @INIT_OPTG
All commands required by fix mdi/qm (<ENERGY, <FORCES,
<STRESS, >COORDS, >CELL) are supported.
Note
EXIT is listed as gray (not registered by MOPAC). In practice MOPAC
likely detects the MPI communicator closure or an EOF condition when LAMMPS
exits and terminates cleanly. This must be verified empirically in
Phase A. If LAMMPS fails to terminate MOPAC, a wrapper or a SIGTERM
mechanism may be needed.
Build requirement#
Standard MOPAC distributions do not include MDI support. The conda-forge
mopac package does not currently ship MDI-enabled builds. To use MOPAC
as an MDI engine you must build from source:
cmake -DMDI=ON …
make install
This is a deployment concern that affects SEAMM packaging. Options:
Maintain a separate
mopac-mdiconda package (or a feature variant).Require users to build MOPAC from source and point SEAMM to that binary.
Petition the MOPAC conda-forge maintainers to enable MDI in the package.
Recommendation: start with option 2 for development, pursue option 1 or 3 for production.
SEAMM integration design#
Design goals#
The user configures the QM engine using the normal SEAMM GUI for that code (MOPAC parameters, Hamiltonian selector, convergence options, etc.).
The LAMMPS step generates all required inputs automatically: the
.mopfile, the LAMMPS input, and thempirunlaunch command.The design is code-agnostic so that xTB, ORCA, or any future MDI-capable code can be dropped in with minimal changes.
New component: QM Engine substep in the LAMMPS subflowchart#
The LAMMPS step’s existing subflowchart (which currently holds Initialization, Velocities, NVT/NPT substeps) gains a new first slot: the QM Engine substep. When this substep is present, the LAMMPS step switches to MDI mode.
LAMMPS step subflowchart (MDI QM/MD mode)
──────────────────────────────────────────
[QM Engine] ──► [Initialization] ──► [Velocities] ──► [NVT/NPT]
QM Engine substep (mini-flowchart)
───────────────────────────────────
[MOPAC step] ← configured with normal MOPAC GUI
The QM Engine substep is a new plug-in step — call it qm_engine_step
(package qm_engine_step, or embedded in lammps_step to avoid a new
package for now). It holds a one-step mini-flowchart that can contain any
MDI-capable QM step. Its role is purely configurational: it is never
executed directly — instead it is interrogated by the LAMMPS step to extract
the information needed to build the MDI launch.
QM Engine substep responsibilities#
Hold the mini-flowchart (contains a MOPAC step, xTB step, etc.).
Expose a method
get_mdi_engine(configuration)that returns anMDIEngineSpecobject (see below).
MDIEngineSpec — the engine abstraction#
A lightweight dataclass (not a full SEAMM plug-in) that captures everything the LAMMPS step needs:
@dataclasses.dataclass
class MDIEngineSpec:
engine_name: str # e.g. "MOPAC" (the MDI engine name)
executable: str # e.g. "/path/to/mopac"
input_file: str # e.g. "mopac.mop"
input_content: str # full content of the input file
extra_args: list[str] # any extra CLI args before -mdi flag
elements: list[str] # ordered element list for fix mdi/qm
needs_virial: bool # True if NPT (stress required)
Each QM step (MOPAC, xTB, …) implements a new method:
def get_mdi_engine_spec(
self,
configuration,
needs_virial: bool = False
) -> MDIEngineSpec:
...
This is the only interface the LAMMPS step needs. Adding xTB or any other code requires only implementing this method in that step’s class.
MOPAC step changes#
New method get_mdi_engine_spec#
The MOPAC step adds get_mdi_engine_spec() that:
Reads the current parameter values (Hamiltonian, convergence, MOZYME flag, etc.) exactly as
get_input()does today.Constructs the
.mopfile content for MDI mode:Uses the chosen Hamiltonian (
PM7,PM6-ORG,AM1, etc.).Adds
MDIkeyword to activate the MDI engine loop.Does not add
1SCF,FORCE,AUX,NOREOR—the MDI engine loop handles execution differently from a batch run.Adds
LET(suppress convergence-failure fatal error).For periodic systems (periodicity == 3): adds
STRESS.Includes a placeholder single-atom geometry (required by MOPAC’s input parser even in MDI mode; the real geometry arrives via MDI).
Returns the
MDIEngineSpec.
The MOPAC step is not executed in MDI mode. Its run() method is
bypassed; only get_mdi_engine_spec() is called by the LAMMPS step.
LAMMPS step changes#
The LAMMPS step needs the following additions:
Detection of QM Engine substep#
When building the LAMMPS input, the step iterates its subflowchart. If it
finds a QM Engine substep, it:
Extracts the
MDIEngineSpecfrom the contained QM step.Writes the
.mop(or other QM input) file.Omits
pair_styleandpair_coefffrom the LAMMPS input.Emits
comm_modify cutoff 2.0near the top of the input (mandatory; no pair_style means zero default pairwise cutoff).Derives the ordered
elementslist from the configuration atom types.Emits
fix mdi_fix all mdi/qm [virial yes] elements ….Constructs the full
mpirunlaunch command.
atom_style full
comm_modify cutoff 2.0 # mandatory: no pair_style → no cutoff
fix prop all property/atom mol charge ...
read_data structure.dat
# NVT (no barostat):
fix mdi_fix all mdi/qm elements H C O N ...
# NPT (barostat needs virial):
fix mdi_fix all mdi/qm virial yes elements H C O N ...
lammps.ini and the code key#
The lammps_step already substitutes the code key from lammps.ini
when launching. For QM/MD, the MDI launch command takes the form:
mpirun --mca mpi_yield_when_idle 1 \
-np 1 {QM_EXE} {QM_INPUT} \
-mdi "-role ENGINE -name {ENGINE_NAME} -method MPI" \
: -np 1 lmp \
-mdi "-role DRIVER -name LAMMPS -method MPI"
The QM-specific parts ({QM_EXE}, {QM_INPUT}, {ENGINE_NAME}) are
provided by the MDIEngineSpec and substituted at runtime. The -in
input.dat suffix is appended automatically by SEAMM as usual.
A new mdi-code key in lammps.ini could store the template with
placeholders. Alternatively, the code is constructed entirely in Python
from the MDIEngineSpec data, and lammps.ini is not modified. The
latter is cleaner and is preferred.
MOPAC .mop file for MDI mode#
Minimum viable input file#
PM7 MDI LET
MOPAC MDI engine — generated by SEAMM lammps_step
(geometry replaced each step by MDI driver)
C 0.0 1 0.0 1 0.0 1
0
The critical points:
MDIActivates MOPAC’s internal MDI engine loop. Without this keyword, MOPAC runs as a normal batch calculation and never connects to LAMMPS.
- Hamiltonian keyword (
PM7,PM6-ORG,GFN2, etc.) Selected by the user in the MOPAC step GUI, exactly as today.
LETPrevents SCF convergence failures from killing the MD run.
- Placeholder geometry
MOPAC requires at least one atom in the input, even in MDI mode. A single carbon at the origin is sufficient; it is immediately overwritten by the
>COORDScommand from LAMMPS.
Periodic systems#
For systems with PBC (periodicity == 3), add STRESS to request the
stress tensor, and include three Tv lines:
PM7 MDI LET STRESS
MOPAC MDI engine — periodic system
(geometry replaced each step by MDI driver)
C 0.0 1 0.0 1 0.0 1
Tv 10.0 0 0.0 0 0.0 0
Tv 0.0 0 10.0 0 0.0 0
Tv 0.0 0 0.0 0 10.0 0
0
Warning
It is currently unclear whether MOPAC’s MDI loop reads the Tv lines
from the .mop file or relies entirely on the >CELL MDI command.
This must be tested empirically. If >CELL is sufficient, the Tv
lines can be omitted from the template.
Additional MOPAC keywords exposed in the GUI#
The following MOPAC step parameters map naturally to MDI/MD use:
CHARGE=nTotal charge of the system. Sourced from the configuration object, not from the GUI (consistent with SEAMM convention).
MULT=nSpin multiplicity. Also sourced from the configuration object.
MOZYMELinear-scaling SCF. Highly recommended for systems > ~200 atoms. The MOPAC step GUI already exposes this.
CHARGE_MODELCM5,MULL, etc. Exposed but not critical for MD forces.- Convergence keyword
MOPAC’s default convergence is adequate for most MD applications. Expose
PRECISEandRELSCF=nin the GUI.
Phased development plan#
Phase A — Proof of concept: MOPAC NVT on a molecule#
Goal: confirm that a MOPAC-MDI build can be driven by LAMMPS
fix mdi/qm for a non-periodic NVT simulation.
Deliverables
Build MOPAC from source with
-DMDI=ON. Confirm theMDIkeyword is accepted.Manually craft a
.mopfile and LAMMPS input for formic acid (HCOOH) NVT, PM7 Hamiltonian.Verify:
Forces agree with finite-difference numerical gradient at the starting geometry.
NVT simulation runs without crashes for ≥ 1000 steps.
EXITcommand behaviour: does MOPAC terminate cleanly when LAMMPS finishes?
Document the exact
.mopfile format, required keywords, and launch command.Note any discrepancies with the MDI Mechanic test report.
Risks
MOPAC
EXITnot registered (gray badge) may prevent clean shutdown. Workaround: run LAMMPS withfix mdi/qmand rely on MPI teardown.-DMDI=ONmay not be available in conda. Manual build required.
Phase B — SEAMM integration skeleton#
Goal: add the minimum code to lammps_step and mopac_step to
run the Phase A case from a SEAMM flowchart.
Deliverables
MDIEngineSpecdataclass in a newlammps_step/mdi.pymodule.MopacStep.get_mdi_engine_spec()method.QM Enginesubstep skeleton (can be a simple wrapper with one-step mini-flowchart, embedded inlammps_stepinitially).LAMMPS step changes:
Detect
QM Enginesubstep presence.Call
get_mdi_engine_spec().Write
.mopfile.Omit
pair_style.Emit
comm_modify cutoff 2.0andfix mdi/qm.Build and execute the
mpirunlaunch command.
End-to-end test: formic acid NVT from a SEAMM flowchart.
Phase C — Periodic NVT (stress)#
Goal: extend to periodic systems with stress tensor.
Deliverables
Extend
get_mdi_engine_spec()to emitSTRESSkeyword andTvlines (or confirm they are not needed).Verify that MOPAC
<STRESSreturns the correct sign convention (tensile positive) and that SEAMM passes it directly to LAMMPS (which expects the same viafix_mdi_qm).Test: periodic water box (64 molecules), PM7, NVT.
Verify stress appears in LAMMPS thermo output (non-zero virial).
Phase D — Periodic NPT#
Goal: NPT simulation with MOPAC as the QM engine.
Deliverables
virial yesemitted when the subflowchart contains a barostat step.Test: water box NPT, verify pressure converges to target.
Performance benchmark: step time vs. number of atoms (100–500 atoms).
Document
comm_modifyandvirial yesas mandatory for NPT.
Phase E — xTB support#
Goal: support Grimme’s xtb as an alternative QM engine.
xTB has a native MDI implementation in recent versions (check the xTB
documentation at https://xtb-docs.readthedocs.io for --mdi flag
support). If native MDI is available, the pattern is identical to MOPAC:
mpirun --mca mpi_yield_when_idle 1 \
-np 1 xtb xtb.inp --mdi "-role ENGINE -name XTB -method MPI" \
: -np 1 lmp -mdi "-role DRIVER -name LAMMPS -method MPI" -in input.dat
Deliverables
Verify xTB MDI support status (native vs. subprocess-wrapper needed).
Implement
XtbStep.get_mdi_engine_spec().Test: water box NVT, GFN2-xTB.
Confirm the
QM Enginesubstep GUI accepts xTB step with no changes.
Phase F — Packaging and deployment#
Goal: make MOPAC MDI builds available through SEAMM.
Deliverables
Conda recipe for
mopac-mdi(MOPAC built with-DMDI=ON).SEAMM installer integration: detect whether installed MOPAC has MDI support; warn if not.
lammps.inidocumentation: add MDI section with example launch commands.User-facing documentation (RST).
Known issues and open questions#
- EXIT command (MOPAC)
MOPAC does not register the
EXITMDI command. LAMMPS sends it at the end of the run. Need to verify empirically whether MOPAC handles it gracefully, ignores it, or crashes. Possible mitigations:Rely on MPI communicator teardown (LAMMPS exits → MPI_Finalize → MOPAC detects broken communicator and exits).
Patch MOPAC to register and handle EXIT. The openmopac/MDI_MOPAC_test repo has an open pull request from MolSSI-MDI; check its status.
- Energy quantity: HOF vs. total energy
MOPAC reports Heat of Formation (kcal/mol), not a total electronic energy. For MD only energy differences and gradients matter, so HOF is correct for forces. The absolute energy in LAMMPS thermo will be an HOF in Hartree — this is unusual and must be clearly documented.
TOTAL_ENERGY(eV, available in the AUX file) is a better quantity for absolute comparisons, but it is unclear whether MOPAC’s MDI engine returnsTOTAL_ENERGYorHEAT_OF_FORMATIONvia<ENERGY. This must be confirmed by inspection or from the MOPAC source.- MOPAC NOREOR in MDI mode
In batch mode, MOPAC can reorient molecules into a standard orientation (NOREOR suppresses this). Whether the MDI engine loop applies any reorientation is unknown. If it does, forces will be returned in the wrong frame. Verify empirically; if necessary, add
NOREORto the generated.mopfile.- Charge and multiplicity
These should come from the configuration object (SEAMM convention), not from the GUI. The MOPAC
.mopfile should includeCHARGE=nandMULT=nonly when they differ from the defaults (0 and 1). The MDI<TOTCHARGEand<ELEC_MULTcommands (supported by MOPAC) allow the driver to query these values, but not to set them.- MOZYME for large systems
MOPAC’s MOZYME (localized MO) method enables near-linear scaling and is important for systems > 200 atoms. It may have compatibility constraints with the MDI loop. Verify in Phase A/B.
- QM Engine substep package location
For Phase B, embed the
QM Enginesubstep insidelammps_stepto avoid creating a new package. Evaluate whether it merits a separateqm_engine_steppackage as adoption grows.- Parallel MOPAC
MOPAC supports OpenMP parallelism. The MDI launch can run MOPAC on multiple threads by setting
OMP_NUM_THREADSbefore thempiruninvocation. Expose asmopac-threadsoption in the QM Engine substep.
Comparison with MACE MDI (for reference)#
Aspect |
MACE (lammps-mdi) |
MOPAC (this plan) |
|---|---|---|
Engine implementation |
Python wrapper script |
Native in MOPAC binary |
MDI support required? |
Custom (mace_mdi.py) |
Build with |
Per-step overhead |
~0 (in-process GPU) |
~0 (in-process, CPU) |
Subprocess needed? |
No |
No |
Stress sign convention |
Negate (MACE tensile+) |
Verify (MOPAC ?) |
SEAMM integration |
lammps.ini code= key |
QM Engine substep + auto-generated .mop |
|
Yes — same |
Yes — same |
|
Yes — same |
Yes — same |
Energy quantity |
eV (DFT total energy) |
kcal/mol (HOF) — verify |
References#
MOPAC MDI documentation: https://openmopac.net/about/software/#mdi
MOPAC MDI test repository: openmopac/MDI_MOPAC_test
MDI specification: https://molssi-mdi.github.io/MDI_Library/
LAMMPS
fix mdi/qm: https://docs.lammps.org/fix_mdi_qm.htmlLAMMPS MDI HOWTO: https://docs.lammps.org/Howto_mdi.html
MACE MDI development summary:
mace_mdi_development_summary.md(project knowledge)