Phase B – Model Chemistry Step (selection + storage)#
- Author:
Paul Saxe (with Claude)
- Date:
2026-06-23
- Status:
In progress – design agreed except D1-D4 below
- Campaign:
LAMMPS + MOPAC/xTB QM-MD via MDI
Scope#
Phase B builds the minimum Model Chemistry step needed for the thin line
“select MOPAC PM6-ORG, then drive LAMMPS MD with it via MDI”. The step lets the
user choose a model chemistry and stores it as the workspace variable
_model_chemistry that LAMMPS (Phase C) reads – mirroring how the Forcefield
step provides _forcefield.
In scope:
Strip the package from a subflowchart plug-in (as generated by the cookiecutter) down to a simple step.
The model-chemistry grammar parser/composer (delivered:
model_chemistry_step/grammar.py+tests/test_grammar.py).Discovery of available model chemistries across installed program steps.
A GUI to select one.
run()that parses the selection and sets_model_chemistry.The
_model_chemistryschema (the producer -> consumer contract).
Deferred:
Phase C: the LAMMPS side – read
_model_chemistry, generate the launch script (Phase A’sget_mdi_engine_command+ a free TCP port), run.Cascading Program -> Type -> Method GUI (flat combobox for now).
Full generality: basis/cutoff codes, all program types, and replacing the Forcefield step’s global-variable approach wholesale.
xTB (revisit once the MOPAC thin line works end to end).
Confirmed SEAMM mechanics#
Discovery. Steps are Stevedore plug-ins in the "org.molssi.seamm"
namespace (seamm.PluginManager). Each entry-point object is the step’s
helper class (e.g. MOPACStep). So enumerating model chemistries means
iterating that namespace and calling get_model_chemistry_options() on every
helper that defines it. The owning plug-in’s Stevedore name is captured at the
same time, to serve as the resolution handle later.
Storage. seamm.Node provides set_variable(name, value) /
get_variable(name) / variable_exists(name), backed by
seamm.flowchart_variables. The step does
self.set_variable("_model_chemistry", {...}); LAMMPS does
self.get_variable("_model_chemistry"). Same mechanism as _forcefield.
The _model_chemistry contract#
The step writes this workspace variable:
{
"model_chemistry": "MOPAC:SQM@PM6-ORG", # canonical string
"program": "MOPAC", "type": "SQM", "method": "PM6-ORG",
"basis": None, "cutoff": None, # parsed components
"step": "<stevedore plugin name>", # owning step (resolution handle)
"options": { ... full get_model_chemistry_options() dict ... },
}
LAMMPS (Phase C) then:
reads
_model_chemistry;checks
options["mdi_capable"]andoptions["periodic_mdi"]and errors helpfully if the selection cannot be driven via MDI;resolves the owner:
step = self.flowchart.plugin_manager.manager[mc["step"]].obj;calls
step.get_mdi_engine_command(self.flowchart.executor, self.global_options, method=mc["method"], port=port, charge=..., multiplicity=...)(charge/multiplicity from the configuration object, per SEAMM convention – never from the model-chemistry step).
Carrying the whole options block means LAMMPS needs nothing from the program
step except the launch command. The step name (captured at discovery) avoids
having to map the Program: token back to an entry point.
Open decisions#
D1 – Simplify subflowchart -> simple step. Proposed: yes. Remove the
Substepbase class, the iterate-over-substepsrun(), and the subflowchart GUI scaffolding. Large diff; confirm before restructuring.D2 – The ``_model_chemistry`` schema above. Proposed as written. Confirm the keys, especially carrying the full
optionsblock and usingstep(Stevedore name) as the resolution handle.D3 – Generality vs. filtering. Proposed: keep the step general (lists all discovered model chemistries) and let LAMMPS validate MDI-capability; add an optional filter toggle later.
D4 – GUI. Proposed: flat combobox of
Program:Type@Methodstrings; cascading dropdowns deferred.
Grammar (delivered)#
Program:Type@Method[/Basis[@Cutoff]]. parse_model_chemistry(text) ->
components dict; compose_model_chemistry(components) -> string (inverse).
Delimiters :, @, / are reserved; a Cutoff requires a Basis.
Lives in model_chemistry_step/grammar.py so both the step and consumers
(LAMMPS, program steps) share one definition. Add to __init__.py:
from .grammar import parse_model_chemistry, compose_model_chemistry # noqa: F401
Next steps (pending D1-D4)#
Restructure to a simple step (D1): trim
model_chemistry.py,tk_model_chemistry.py, dropsubstep.py.Real
metadata.pyand amodel_chemistryparameter (dynamic enumeration populated from discovery).Discovery helper +
run()that builds and stores_model_chemistry.GUI combobox populated from discovery.
Tests for discovery + storage (mock a program-step helper exposing
get_model_chemistry_options).
References#
SEAMM plug-in discovery:
seamm/plugin_manager.py(namespaceorg.molssi.seamm).Workspace variables:
seamm/node.py(set_variable/get_variable) andseamm.flowchart_variables.Phase A engine contract:
NOTES_A.rst(get_executor_config,get_mdi_engine_command).