GROMACS version: 2024.3 (double precision)
GROMACS modification: No
Hello,
My goal is to compute the Hessian for the TIP4P2005 water model, that has LJ interactions (between oxygens), and coulomb interactions (between H and dummy particles). Another feature that’s important here is that the model has rigid constraints.
My current understanding is that GROMACS cannot minimize with rigid constraints (right?), so my strategy has been to export all the GROMACS simulation output files into MDAnalysis, and compute in python all the related quantities and perform my minimization there (the questions below do not have anything to do with MDAnalysis).
My procedure is as follows: I equilibrate the water molecules at high temperature, and then cool it down. After cooling it down I follow with a super damped Langevin dynamics (that allows me to maintain the pressure at its wanted level, while taking away the kinetic energy). I do this with the following command (mdp and top files attached):
gmx_mpi_d grompp -f "damped_quench_p=1000_T=80_s=1.mdp" -c "Tmp_p=1000_T=80_s=1.gro" -p tip4p2005-1000_tmp.top -o "DQuenched_p=1000_T=80_s=1.tpr"
gmx_mpi_d mdrun -s "DQuenched_p=1000_T=80_s=1.tpr" -mp tip4p2005-1000.top -c "DQuenched_p=1000_T=80_s=1.gro" -e "DQuenched_p=1000_T=80_s=1.edr" -o "DQuenched_p=1000_T=80_s=1.trr" -pin on -ntomp 1 -v -deffnm em
This gives me .edr, .gro and .trr files which I then load in python.
I now have two questions. The first part has to do with energy computation (mostly the Coulomb (SR) part), and the second question has to do with the resulting forces and how to extract/interpret those.
Part 1:
My first goal is to reproduce the energy values stored after the dynamics in the .edr file. As I remove most of the kinetic energy, I aim first at recovering the potential energy. The potential energies GROMACS gives are divided into three components - LJ (SR), Coulomb (SR) and Coul. recip.. I always compare the last values stored (e.g., I use edrFile.data_dict[‘Coulomb (SR)’][-1]). I would like to be able to recover these three values from the .gro and .trr files (together with my model parameters of course). To be clear I compare the computed values to those obtained by GROMACS using this: \Delta = \frac{E_\text{edr} - E_\text{computed}}{E_\text{edr}}.
I start with the LJ component as it only operates between the oxygens. I am able to compute it in python with \Delta_{LJ} = 0.000010 - so to a fairly good extent. I would like to achieve a similar value with the Coulomb interactions.
My issue starts with the short-range coulomb interactions, which I obtain to \Delta_{C(SR)} \simeq 0.24 - so something is off. I want to understand what I am missing in my Coulomb energy calculations (we will keep the Ewald/PME contributions aside for now).
Here is what I compute - first, I define the charges for the H’s (Q = 0.5564), and Dummy particles (-2Q), and set the constants \alpha = 2.6035 and F = 138.935458. Then, I run over all pairs that do not belong to the same molecule, and compute the coulomb energy as
E_{C(SR)} = F q_1 q_2 \frac{\text{erfc}(\alpha r)}{r}.
I also tried computing with the cutoff as E_{C(SR)} = F q_1 q_2 \left[\frac{\text{erfc}(\alpha r)}{r} - \frac{\text{erfc}(\alpha r_{cut})}{r_{cut}}\right] but this does not improve the situation. I also add the “self” energy E_{C(SR)} = -F q_1 q_2 \frac{\text{erfc}(\alpha r_{cut})}{r_{cut}} for pairs within the same molecule, but this contribution is neglegible with respect to the first one.
This causes me to believe that I am missing something in the first Coulomb computation, but I am not sure what is missing (is this something to do with the PBCs, an aspect I am missing from the potential calculations, or other) - any help would be much appreciated.
Part 2:
After getting the energy the next stage would be to compute gradients and perform a rigid-body minimization in python. To do this I want to compare the forces in my GROMACS to the ones I compute from taking the energy derivatives.
The .trr file above gives me the forces on all the particles. I observe the forces at the end of the simulation by using MDAnalysis - if u1 is the universe, then I set u1.trajectory[-1] to load the last frame, and get the forces by u1.atoms.forces.
Now I have another run using this last frame as an initial state. Say I try and minimize (whatever GROMACS does in this case) using (quench1.mdp file attached):
gmx_mpi_d grompp -f "quench1_p=1000_T=80_s=1.mdp" -c "DQuenched_p=1000_T=80_s=1.gro" -p tip4p2005-1000_tmp.top -o "Min_p=1000_T=80_s=1.tpr"
gmx_mpi_d mdrun -s "Min_p=1000_T=80_s=1.tpr" -mp tip4p2005-1000.top -c "Min_p=1000_T=80_s=1.gro" -e "Min_p=1000_T=80_s=1.edr" -o "Min_p=1000_T=80_s=1.trr" -pin on -ntomp 1 -v -deffnm em
This also produces a .trr file. I now want to compare the forces from the last frame in the first trr file - denoted here by u1 - , and the first frame in the second .trr file, denoted here as u2.
When I load these to MDAnalysis, the forces from u1 are several orders of magnitude larger than in u2 (both different from the values I compute explicitly with taking an explicit gradient, even when I consider only the oxygens, which “feel” only the LJ part of the forces).
The forces are different in both magnitude and in direction (so it seems like there is no simple ``conversion factor’’ that can explain this discrepancy).
Again - I seem to be overlooking something. Would love to have some input here.
I have attached mdp files and the top file for anyone interested in running these (couldn’t upload the .gro files or the resuling .edr and .trr files).
Many thanks in advance
damped_quench_p=1000_T=80_s=1.mdp|attachment (1.7 KB)
quench1_p=1000_T=80_s=1.mdp|attachment (773 Bytes)
tip4p2005-1000.top (1.3 KB)