Cloning t_forcerec in v2024

GROMACS version: 2024-dev-20250310-fb7d05abbd-dirty-unknown
Starting commit: Enable multisim for modular simulator (84a5f710) · Commits · GROMACS / GROMACS · GitLab

I’m implementing the path MD algorithm in GROMACS (see <A href="https://gitlab.com/gromacs/gromacs/-/issues/4571">Gromacs issue #4571 </A> - HackMD). The algorithm computes the product of the Hessian of potential and a position-like vector via central differences. For this, I need to call do_force twice (sequentially) additionally in every step. The parameters here are basically x + e and x - e where x is the positions vector and e is a perturbation.

I see that t_forcerec is a mutable parameter to do_force, so I decided to clone it, to be sure. For this, I’m basically calling the same init. functions in runner.cpp. These are (apart from some constructors) init_forcerec and init_nb_verlet. I see that the latter creates an ExclusionChecker that adds a subscriber to ObservablesReducerBuilder. Since I have no idea what these structures do exactly (apart from what Perplexity could tell me), I was wondering what dependencies and “handshakes” I’m omitting to acknowledge.

On a side note, is it possible to call do_force twice for the central differences computation using the same t_forcerec knowing that the perturbation is “small”? Here, it would be interesting to know how to handle the domain decomposition (re-partitioning, neighbour search) aspect as well.

I would be very grateful for any ideas, guidance, tips etc that you could give me regarding the matter of “cloning the t_forcerec” or generally the problem at hand.

Looking forward to hearing from you, thanks in advance,
Nitin Malapally

You should not clone t_forcerec, that only lead to complications.

t_forcerec is a legacy data structure that we are slowly refactoring. By now t_forcerec is nearly const in between domain decomposition repartitionings. The only things that might change per step are the shift forces, PME data, PP-PME communication buffers and force providers. None of these should be a problem when you would call do_force before the normal do_force call.

Have a look a shellfc.cpp, which calls do_force multiple times at every MD step to minimize shell sites.

Thanks for your reply. OK, so you’re saying I can simply use the same t_forcerec instance without further changes. What about neighbour searching? Could it be that the perturbation requires NS for accurate computations?

No, it will not require extra search. I assume your deltas are very small compared to the particle displacements within nstlist steps.

Usually they are. Would this work for a more robust implementation (just before calling do_force for the central differences calls)?

if (maxPerturbation >= 0.5_real * inputRec->rlist)
{
    runScheduleWork.stepWork.doNeighborSearch = true;
    adaptedFlags = GMX_FORCE_ALLFORCES | GMX_FORCE_NS;
}

On a separate note, do we need special considerations for force-offloading to GPUs? I see that a “StateGPU” is associated with the forceRec

You can’t simply call extra search. But this shouldn’t be necessary as your delta/epsilon should be really small.

You will not be able to use “GPU-resident” mode, so update on GPU. There is nothing special to do for force offloading.

Thanks, you’ve been very helpful! :)