Repository navigation
Generate GROMACS mdp run schedules at build time - #67
Conversation
Implementation Plan (revision 2)
Stack:
Decisions settled in planning (with the user)
Nonbonded evidence (primary sources, retrieved during planning)
Package survey (acceptance criterion 4)
mdfactory is MIT-licensed, so the GPL tools are excluded. biobb_gromacs is the only permissive option:
mdfactory therefore keeps the same shape in-house without the dependency. The force-field-aware protocol data has to live in mdfactory in any case. Problem analysis
Target settings (deliverable contract)
simulation_type: bilayer
parametrization: charmm
system: { ... }
simulation_settings: # optional; omitted fields take per-type defaults
temperature: 310.0 # K, part of the hash
production: {length: 500.0, output_interval: 20.0} # ns / ps, not part of the hash
gromacs_overrides:
npt: {pcoupl: C-rescale}Nonbonded block, derived from the family and identical in all four stages:
Intended changes against today's default output:
Derived from the simulation type (unchanged; lnp equals mixedbox):
Constants as today:
Deliverables
Acceptance criteria (mapped to the issue, plus the contract)
Files to create or modify
Testing approachNew tests have no "build" in their names, so CI runs them with
Risks and open questions
Out of scope (follow-ups)
Plan created by mach6 (revision 2) |
Progress UpdatePlan revision 2 is implemented in full. The commit below adds the following:
Decisions made while implementing (beyond the plan text)
Bug found during the e2e runs and fixed: Commit: E2E results and regression report: generated run schedules (issue 62), 2026-11-06Uncommitted working tree on top of 4ea82ba. Jobs: 1. Regression report: generated files versus the static files at 571dedc (default settings)Keys are compared the way GROMACS reads them: case,
The protein schedules (charmm, and amber/sage) differ from the old files only in dropped obsolete keys and 2.
|
| Stage | Small-molecule types (mixedbox, bilayer, lnp) | Protein types |
|---|---|---|
| EM | 1 / 1: atom names from the CGenFF/OpenFF topology differ from system.pdb (pre-existing) |
0 / 1 |
| NVT | 1 / 1: -DPOSRES is not used by the topology |
0 / 1 |
| NPT | 2 / 2: Berendsen, plus -DPOSRES |
2 / 2: Berendsen, plus absolute position restraints with pressure coupling |
| Production | 1 / 2: Berendsen | 0 / 2 |
With C-rescale overriding the barostat (the 310 K example), NPT has 1 warning out of 2. Reports: scratch62/report_{cpu,gpu,lnp}.md.
3. Builds and simulations
| System | Family (scheme) | Env | Build | 4 mdps + record | EM → NVT |
|---|---|---|---|---|---|
| mixedbox water/ethanol | charmm (charmm) | dev, cpu | OK | OK | OK (gmx 2026.3, cpu) |
| mixedbox water/ethanol | openff (sage) | dev, cpu | OK | OK | OK |
mixedbox water/ethanol, water_ethanol_smirnoff_310K.yaml (310 K, 20 ns, C-rescale NPT override) |
openff (sage) | dev, cpu | OK | OK | OK |
| bilayer POPC | charmm (charmm) | dev, cpu | OK | OK | OK |
| bilayer POPC | openff (sage) | dev, cpu | OK | OK | OK |
| lnp ALC-0315 | openff (sage) | dev, gpu | OK | OK | OK (--slurm, gpu, gmx-cuda 2026.3) |
| lnp ALC-0315 | charmm (charmm) | dev, gpu | OK on the second attempt* | OK | OK (--slurm, gpu) |
| proteinbox lysozyme | charmm (charmm) | dev + gmx_mpi 2024.3, gpu | OK (build-time grompp) | OK | OK (gmx 2026.3, cpu) |
| protein_mixedbox lysozyme + ethanol | charmm (charmm) | dev + gmx_mpi 2024.3, gpu | OK (build-time grompp) | OK | OK |
| proteinbox lysozyme | amber (sage) | gmx-cuda 2026.3, gpu | OK (build-time grompp) | OK | OK |
| protein_mixedbox lysozyme + ethanol | amber (sage) | gmx-cuda 2026.3, gpu | OK (build-time grompp) | OK | OK |
* The first charmm LNP attempt failed before any mdp was written: OpenMM reported Energy is NaN in create_sphere during the OpenMM preparation. This is the known random blow-up (issue 58 class). The retry built cleanly.
LNP builds now get the mixedbox schedule and simulate; before this change, simulate skipped them.
4. Temperature series and re-render
- Temperature series. A CSV with
simulation_settings.temperature= 300 and 310 gave two hashes. They equal the hashes of the 300 K example and of the 310 K example, which uses other production settings and an override. Only the state point enters the identity. - Production length. After EM and NVT had run,
apply-settings longer.yaml(production: {length: 200}) updated both directories.npt.mdp,md.mdpand<hash>.yamlwere rewritten:md.mdpnow hasnsteps = 100000000, and the hashes are unchanged.nvt.mdp, which has outputs, was not touched. - Temperature change.
apply-settings hotter.yaml(320 K) was refused for both directories with exit status 1 and wrote nothing. - NVT length.
apply-settings shorter_nvt.yaml(NVT 50 ps) was refused with exit status 1, because NVT already has outputs. The refusal listsnvt.tpr, nvt.cpt, nvt.log, nvt.edr, nvt.gro.
5. Tests
- Unit tests:
pytest -k "not build" mdfactorygives 3406 passed and 1 skipped. - Orchestration and CLI modules:
-k "not build"deselectstest_orchestration_build.pyandtest_orchestration_cli.pyentirely, so they ran separately. 37 passed and 2 failed. The two failures (test_shutdown_parsl_*) also fail at 571dedc when run inside a SLURM job. - Opt-in real-GROMACS tests (
test_amber_gmx_build.py, gmx 2026.3): 7 passed. They run grompp on all four stages within each stage'smaxwarn, passing-rfor restrained stages. The cases are the amber protein schedule on the neutralized peptide, the mixedbox, bilayer and lnp schedules on a 3.2 nm water box with both schemes, and one run with non-default settings and overrides. test_build.py::test_build_mixedbox/test_build_bilayer(CGenFF): these tests now also check the four files and the charmm block. The bilayer ion count (n_ions == 6) is flaky on both 571dedc and this branch, because the water count after the OpenMM compression varies close to the salt-count rounding threshold. In three runs on this branch it was 8, 8 and 6, and it passed on 571dedc.- Wheel: a hatchling wheel built without the
force-includecontains no run-schedule.mdp.
Found during e2e and fixed
<hash>.yaml was written with yaml.safe_dump's default sort_keys=True. That reordered dict fields such as LNP input_fractions, so a reloaded record had a different hash from its directory. The bug predates this change: it affected prepare-build records of LNPs. Records are now written with sort_keys=False, and a regression test covers it.
Progress tracked by mach6
Unverified Review Candidates — Pending AssessmentReview round: 1
CriticalNone. Important1. Integer-valued GROMACS overrides are rendered as 2. 3. One bad build record or a write error aborts the whole
Suggestions4. Test gap: the section-level deep merge across layers is never exercised (test-reviewer 85). No precedence or re-render test has two layers that set different fields of the same section. Replacing the deep merge in 5. Test gap: builder wiring of 6. Test gap: 7. Test gap: owned-key rejection is spot-checked (test-reviewer 82). The tests cover 6 of the 13 settings-owned keys and 4 of the 10 build-owned keys. Nothing ties the owned set to the keys the renderer derives. Dropping 8. Test gap: 9. Test gap: re-render refusal paths beyond state point and outputs (test-reviewer 80). The untested paths are invalid merged settings, a hash mismatch or corrupt record, and a mixed batch where one directory is refused. 10. Test gap: grompp acceptance and the non-protein sequential-YAML build run only outside CI (test-reviewer 80). Grompp acceptance is only checked by the opt-in GROMACS-2026 test. The sequential YAML build is only asserted in the deselected 11. Simplify: 12. Simplify: 13. Simplify: Strengths
Agents run: code-reviewer, error-auditor, test-reviewer, completeness-checker, simplifier Reviewed by mach6 |
Review AssessmentFindings comment: #67 (comment) Round 1 was assessed by the independent assessor. Its results were cross-checked against the code. Classifications
Action Plan
Assessment by mach6 |
Progress UpdateThis fixes finding 1, the only merge blocker from the round-1 assessment. The problem. pandas reads a numeric CSV column with any blank cell as float. An integer override such as Changes:
Checks (cpu partition):
Commit: Progress tracked by mach6 |
Unverified Review Candidates — Pending AssessmentReview round: 2
Round-1 merge blocker (finding 1 of round 1): fixed.
CriticalNone. Important1. CSV override cells such as
2. A misspelled override key is accepted, and grompp's warning for it is absorbed by the stage's
Suggestions3. Test gap: the CSV integer fix is only tested on a whole-number value (test-reviewer 80) 4. Simplify: the row-label uniqueness check is repeated (simplifier 80) 5. Simplify: 6. Simplify: the "str/Path means load the settings file" branch is duplicated (simplifier 80) Strengths
Agents run: code-reviewer, error-auditor, test-reviewer, completeness-checker, simplifier Reviewed by mach6 |
Review AssessmentFindings comment: #67 (comment) Round 2 was assessed by the independent assessor. The parent reproduced the pandas behavior behind finding 1 in the dev environment. The round-1 merge blocker is fixed ( Classifications
Action Plan
Assessment by mach6 |
Progress UpdateThis fixes finding 1, the only merge blocker from the round-2 assessment. The problem. pandas reads the cell text Changes:
Checks (cpu partition):
Finding 2 (useful follow-up), finding 3 (deferred) and the nitpicks in findings 4-6 are not addressed. Commit: Progress tracked by mach6 |
Unverified Review Candidates — Pending AssessmentReview round: 3
Round-2 merge blocker (finding 1 of round 2): fixed. Round-1 merge blocker (finding 1 of round 1): still fixed. Side effects of the global CSV NA change (checked by three agents): CriticalNone. ImportantNone. Suggestions1. Simplify: 2. Simplify: 3. Simplify: Strengths
Agents run: code-reviewer, error-auditor, test-reviewer, completeness-checker, simplifier Reviewed by mach6 |
Review AssessmentRound 3 was assessed by the independent assessor, the developer's advocate and the devil's advocate. The independent assessor also ran Classifications
Previously assessed non-blockers are unchanged by the round-3 delta: The devil's advocate found no missing acceptance evidence for the two fixed blockers or for the criterion that all supply paths resolve identically. It needs no new test. Action PlanNo merge blockers. Nothing to fix before merge. Assessment by mach6 |
542972b to
6631062
Compare
…eline/SimulationSettings examples
Progress UpdateDocumentation and examples for the whole stack (protein types, Amber route, per-component parametrization, SimulationSettings). Docs
Examples
Verification
Found while testing, not fixed
Commit: Progress tracked by mach6 |
Closes #62
Replaces the package-shipped GROMACS
.mdptemplates andrun_schedules.yaml. Runs are now configured through a publicSimulationSettingsPydantic contract that complementsBuildInput:The mdps are rendered from plain dicts at build time, and existing build directories can be re-rendered without a rebuild. The file names and the keys that orchestration reads stay the same.
The nonbonded block follows the force-field family for every system type (CHARMM force-switch 1.0→1.2 nm, Sage potential-switch 0.8→0.9 nm). lnp builds get the mixedbox schedule. Removing the template directory also removes the
force-includethat causes #55.Stacked on #65 (base
feature/issue-61-per-component-parametrization-specs), which is itself stacked on #63 and #59.The implementation plan (revision 2) is posted as a comment below.