grompp crashes with deform-init-flow = yes for energy minimization, normal-mode analysis and test-particle insertion
Summary
With deform set and deform-init-flow = yes, gmx grompp crashes with a segmentation fault for every integrator without velocities (steep, cg, l-bfgs, nm, tpi, tpic).
deformInitFlow() adds the flow profile to state->v
(https://gitlab.com/gromacs/gromacs/-/blob/dd255a67520b520ed49eb4bc5779cf4b7ca28891/src/gromacs/gmxpreprocess/grompp.cpp#L2075-2098),
and it is called whenever deform-init-flow = yes
(https://gitlab.com/gromacs/gromacs/-/blob/dd255a67520b520ed49eb4bc5779cf4b7ca28891/src/gromacs/gmxpreprocess/grompp.cpp#L2738-2742).
But the state only has velocities for dynamical integrators
(https://gitlab.com/gromacs/gromacs/-/blob/dd255a67520b520ed49eb4bc5779cf4b7ca28891/src/gromacs/gmxpreprocess/grompp.cpp#L803-816).
For the other integrators state.v is empty, and deformInitFlow() writes past its end.
grompp even recommends the option: with deform and deform-init-flow = no, the same steep input gives the note "Unless the velocities in the initial configuration already obey the flow profile, the flow profile should be initialized by setting deform-init-flow=yes when using the deform option"
(https://gitlab.com/gromacs/gromacs/-/blob/dd255a67520b520ed49eb4bc5779cf4b7ca28891/src/gromacs/gmxpreprocess/readir.cpp#L1794-1810).
With gen-vel = yes in the mdp file (which these integrators otherwise ignore) and deform-init-flow = no, grompp stops with the error "When the box is deformed and velocities are generated, the flow profile should be initialized by setting deform-init-flow=yes", so there is no setting of deform-init-flow that works. As far as I can see, box deformation is only applied by the dynamical integrators, so for these integrators the option has no effect anyway.
GROMACS version
Tested: 2026.0 (conda-forge) and main at dd255a67 (2027.0-dev-20261009-dd255a67). By code inspection, all 2024 and 2025 releases and release-2026 have the same unguarded call. It came with 28697ebf "Improve the deform option" (!3141 (merged), #4607 (closed)), first released in 2024.0.
Steps to reproduce
spc-and-methanol.gro and spc-and-methanol.top from src/testutils/simulationdatabase, with
integrator = steep
nsteps = 10
cutoff-scheme = Verlet
coulombtype = Reaction-Field
rcoulomb = 0.9
rvdw = 0.9
deform = 0 0 0 0 0.01 0
deform-init-flow = yesgmx grompp -f em.mdp -c spc-and-methanol.gro -p spc-and-methanol.top -o em.tprThe same happens with integrator = cg, l-bfgs and nm, and with tpi and tpic (which also need tc-grps, tau-t and ref-t). With integrator = md, the same input works.
What is the current bug behavior?
grompp crashes with a segmentation fault (exit status 139) after printing the degrees of freedom. There is no error message, and no .tpr is written.
What did you expect the correct behavior to be?
grompp writes the .tpr. For integrators without velocities, deform-init-flow is ignored, with a note.
Possible fixes
- Only call
deformInitFlow()when the state has velocities (state.hasEntry(StateEntry::V)). - In readir, for integrators without velocities, print a note that
deform-init-flowis ignored. Also skip the note (and the error forgen-vel = yes) that asks fordeform-init-flow = yes.
Related ordering issues in grompp
While looking at this, I found two more ordering issues. In both, grompp uses the state from -c before cont_status() replaces it with the frame from -t
(https://gitlab.com/gromacs/gromacs/-/blob/dd255a67520b520ed49eb4bc5779cf4b7ca28891/src/gromacs/gmxpreprocess/grompp.cpp#L2770-2788).
-
-ttogether withdeform-init-flow = yes: the flow profile is computed from the-ccoordinates and box. When velocities are then read from-t, they overwrite the flow profile. When they are not read (gen-vel = yes), the flow profile no longer matches the coordinates. Example on main withdeform = 0 0 0 0 0.301 0(so v_x = 0.1 z in a 3.01 nm box),-cwith zero velocities, and-ta .trr frame of the same configuration shifted by 1 nm in z with zero velocities:- without
-t: v_x = 0.1209, 0.1082, ... for z = 1.209, 1.082, ... (correct) - with
-t,gen-vel = no: all velocities in the .tpr are zero - with
-t,gen-vel = yes,gen-temp = 0: z = 2.209, 2.082, ... but v_x = 0.1209, 0.1082, ... The same happens in the usual setup where-cand-thold the same frame, for example when adeformrun is started from an equilibration withoutdeform(-c npt.gro -t npt.cpt): withgen-vel = no, the velocities in the .tpr are exactly those from-t, without the flow profile and without a note, although the documentation says that the profile is added to the initial velocities. This exists sincedeform-init-flowwas added.
- without
-
NVE (
integrator = md,tcoupl = no) with-tandgen-vel = no: the temperature for the Verlet buffer is computed bycalc_temp()from the-cvelocities (https://gitlab.com/gromacs/gromacs/-/blob/dd255a67520b520ed49eb4bc5779cf4b7ca28891/src/gromacs/gmxpreprocess/grompp.cpp#L2662), but the run starts with the-tvelocities. mdrun keeps this buffer for NVE. For spc-and-methanol, with-tframes whose velocities are 2x and 0.5x those in the .gro, grompp prints "will use the initial temperature of 1046.791 K" and sets rlist = 0.935 nm in all three cases (without-tand with each of the two frames). Giving the same velocities with-cgives 4187 K / rlist 1.017 nm and 262 K / 0.904 nm. With-cand-tfrom the same frame the velocities are the same, so this matters when they differ, for example when the-cfile has no velocities: grompp then uses the fixed 10% buffer for T = 0 (rlist 0.99 nm here), even when the-tframe is hot. The atom density for the buffer also comes from the-ccoordinates and box. This order exists since the automatic NVE buffer was added in 5.0.
A fix for both: read the -t frame before the buffer is determined. Then compute the buffer temperature from the final velocities, and add the flow profile last, from the final coordinates and box. Reading -t right after new_status() would probably be simplest. Velocities from a previous deform run already contain the flow profile, so a note for -t velocities combined with deform-init-flow = yes could help.
On main, velocities of frozen atoms are also not cleared after deformInitFlow() or after reading -t. That is already reported in a comment on #5714 and addressed in !6344 (merged), so I left it out here.
I can open an MR with the fix.