Merge branch release-2018 into release-2019
[alexxy/gromacs.git] / src / gromacs / fileio / tpxio.cpp
index b4526ddb818dff0137941c8354cf90ea7a865306..2efb336f97fdba2b37c581a63fe62227f86e3cd5 100644 (file)
@@ -47,6 +47,7 @@
 #include <algorithm>
 #include <vector>
 
+#include "gromacs/compat/make_unique.h"
 #include "gromacs/fileio/filetypes.h"
 #include "gromacs/fileio/gmxfio.h"
 #include "gromacs/fileio/gmxfio-xdr.h"
@@ -102,7 +103,7 @@ static const char *tpx_tag = TPX_TAG_RELEASE;
  */
 enum tpxv {
     tpxv_ComputationalElectrophysiology = 96,                /**< support for ion/water position swaps (computational electrophysiology) */
-    tpxv_Use64BitRandomSeed,                                 /**< change ld_seed from int to gmx_int64_t */
+    tpxv_Use64BitRandomSeed,                                 /**< change ld_seed from int to int64_t */
     tpxv_RestrictedBendingAndCombinedAngleTorsionPotentials, /**< potentials for supporting coarse-grained force fields */
     tpxv_InteractiveMolecularDynamics,                       /**< interactive molecular dynamics (IMD) */
     tpxv_RemoveObsoleteParameters1,                          /**< remove optimize_fft, dihre_fc, nstcheckpoint */
@@ -118,6 +119,10 @@ enum tpxv {
     tpxv_PullExternalPotential,                              /**< Added pull type external potential */
     tpxv_GenericParamsForElectricField,                      /**< Introduced KeyValueTree and moved electric field parameters */
     tpxv_AcceleratedWeightHistogram,                         /**< sampling with accelerated weight histogram method (AWH) */
+    tpxv_RemoveImplicitSolvation,                            /**< removed support for implicit solvation */
+    tpxv_PullPrevStepCOMAsReference,                         /**< Enabled using the COM of the pull group of the last frame as reference for PBC */
+    tpxv_MimicQMMM,                                          /**< Inroduced support for MiMiC QM/MM interface */
+    tpxv_PullAverage,                                        /**< Added possibility to output average pull force and position */
     tpxv_Count                                               /**< the total number of tpxv versions */
 };
 
@@ -153,7 +158,7 @@ static const int tpx_generation = 26;
 /* This number should be the most recent backwards incompatible version
  * I.e., if this number is 9, we cannot read tpx version 9 with this code.
  */
-static const int tpx_incompatible_version = 30; // GMX3.2 has version 31
+static const int tpx_incompatible_version = 57; // GMX4.0 has version 58
 
 
 
@@ -164,44 +169,35 @@ typedef struct {
 } t_ftupd;
 
 /*
+ * TODO The following three lines make little sense, please clarify if
+ * you've had to work out how ftupd works.
+ *
  * The entries should be ordered in:
  * 1. ascending function type number
  * 2. ascending file version number
+ *
+ * Because we support reading of old .tpr file versions (even when
+ * mdrun can no longer run the simulation), we need to be able to read
+ * obsolete t_interaction_function types. Any data read from such
+ * fields is discarded. Their names have _NOLONGERUSED appended to
+ * them to make things clear.
  */
 static const t_ftupd ftupd[] = {
-    { 34, F_FENEBONDS         },
-    { 43, F_TABBONDS          },
-    { 43, F_TABBONDSNC        },
     { 70, F_RESTRBONDS        },
     { tpxv_RestrictedBendingAndCombinedAngleTorsionPotentials, F_RESTRANGLES },
     { 76, F_LINEAR_ANGLES     },
-    { 34, F_QUARTIC_ANGLES    },
-    { 43, F_TABANGLES         },
     { tpxv_RestrictedBendingAndCombinedAngleTorsionPotentials, F_RESTRDIHS },
     { tpxv_RestrictedBendingAndCombinedAngleTorsionPotentials, F_CBTDIHS },
-    { 43, F_TABDIHS           },
     { 65, F_CMAP              },
-    { 60, F_GB12              },
-    { 61, F_GB13              },
-    { 61, F_GB14              },
-    { 72, F_GBPOL             },
-    { 72, F_NPSOLVATION       },
-    { 41, F_LJC14_Q           },
-    { 41, F_LJC_PAIRS_NB      },
-    { 32, F_BHAM_LR_NOLONGERUSED },
-    { 32, F_RF_EXCL           },
-    { 32, F_COUL_RECIP        },
+    { 60, F_GB12_NOLONGERUSED },
+    { 61, F_GB13_NOLONGERUSED },
+    { 61, F_GB14_NOLONGERUSED },
+    { 72, F_GBPOL_NOLONGERUSED },
+    { 72, F_NPSOLVATION_NOLONGERUSED },
     { 93, F_LJ_RECIP          },
-    { 46, F_DPD               },
-    { 36, F_THOLE_POL         },
     { 90, F_FBPOSRES          },
-    { 49, F_VSITE4FDN         },
-    { 50, F_VSITEN            },
-    { 46, F_COM_PULL          },
-    { 46, F_ECONSERVED        },
     { 69, F_VTEMP_NOLONGERUSED},
     { 66, F_PDISPCORR         },
-    { 54, F_DVDL_CONSTR       },
     { 76, F_ANHARM_POL        },
     { 79, F_DVDL_COUL         },
     { 79, F_DVDL_VDW,         },
@@ -222,8 +218,7 @@ static const t_ftupd ftupd[] = {
 static void do_pullgrp_tpx_pre95(t_fileio     *fio,
                                  t_pull_group *pgrp,
                                  t_pull_coord *pcrd,
-                                 gmx_bool      bRead,
-                                 int           file_version)
+                                 gmx_bool      bRead)
 {
     rvec tmp;
 
@@ -246,14 +241,7 @@ static void do_pullgrp_tpx_pre95(t_fileio     *fio,
     pcrd->init = tmp[0];
     gmx_fio_do_real(fio, pcrd->rate);
     gmx_fio_do_real(fio, pcrd->k);
-    if (file_version >= 56)
-    {
-        gmx_fio_do_real(fio, pcrd->kB);
-    }
-    else
-    {
-        pcrd->kB = pcrd->k;
-    }
+    gmx_fio_do_real(fio, pcrd->kB);
 }
 
 static void do_pull_group(t_fileio *fio, t_pull_group *pgrp, gmx_bool bRead)
@@ -402,7 +390,7 @@ static void do_expandedvals(t_fileio *fio, t_expanded *expand, t_lambda *fepvals
         gmx_fio_do_int(fio, expand->lmc_forced_nstart);
         gmx_fio_do_int(fio, expand->lmc_seed);
         gmx_fio_do_real(fio, expand->mc_temp);
-        gmx_fio_do_int(fio, expand->bSymmetrizedTMatrix);
+        gmx_fio_do_gmx_bool(fio, expand->bSymmetrizedTMatrix);
         gmx_fio_do_int(fio, expand->nstTij);
         gmx_fio_do_int(fio, expand->minvarmin);
         gmx_fio_do_int(fio, expand->c_range);
@@ -490,7 +478,7 @@ static void do_fepvals(t_fileio *fio, t_lambda *fepvals, gmx_bool bRead, int fil
                     snew(fepvals->all_lambda[g], fepvals->n_lambda);
                 }
                 gmx_fio_ndo_double(fio, fepvals->all_lambda[g], fepvals->n_lambda);
-                gmx_fio_ndo_int(fio, fepvals->separate_dvdl, efptNR);
+                gmx_fio_ndo_gmx_bool(fio, fepvals->separate_dvdl, efptNR);
             }
             else if (fepvals->init_lambda >= 0)
             {
@@ -551,14 +539,7 @@ static void do_fepvals(t_fileio *fio, t_lambda *fepvals, gmx_bool bRead, int fil
         }
     }
     gmx_fio_do_real(fio, fepvals->sc_alpha);
-    if (file_version >= 38)
-    {
-        gmx_fio_do_int(fio, fepvals->sc_power);
-    }
-    else
-    {
-        fepvals->sc_power = 2;
-    }
+    gmx_fio_do_int(fio, fepvals->sc_power);
     if (file_version >= 79)
     {
         gmx_fio_do_real(fio, fepvals->sc_r_power);
@@ -581,7 +562,7 @@ static void do_fepvals(t_fileio *fio, t_lambda *fepvals, gmx_bool bRead, int fil
     }
     if (file_version >= 79)
     {
-        gmx_fio_do_int(fio, fepvals->bScCoul);
+        gmx_fio_do_gmx_bool(fio, fepvals->bScCoul);
     }
     else
     {
@@ -746,20 +727,20 @@ static void do_pull(t_fileio *fio, pull_params_t *pull, gmx_bool bRead,
     gmx_fio_do_real(fio, pull->constr_tol);
     if (file_version >= 95)
     {
-        gmx_fio_do_int(fio, pull->bPrintCOM);
+        gmx_fio_do_gmx_bool(fio, pull->bPrintCOM);
         /* With file_version < 95 this value is set below */
     }
     if (file_version >= tpxv_ReplacePullPrintCOM12)
     {
-        gmx_fio_do_int(fio, pull->bPrintRefValue);
-        gmx_fio_do_int(fio, pull->bPrintComp);
+        gmx_fio_do_gmx_bool(fio, pull->bPrintRefValue);
+        gmx_fio_do_gmx_bool(fio, pull->bPrintComp);
     }
     else if (file_version >= tpxv_PullCoordTypeGeom)
     {
         int idum;
         gmx_fio_do_int(fio, idum); /* used to be bPrintCOM2 */
-        gmx_fio_do_int(fio, pull->bPrintRefValue);
-        gmx_fio_do_int(fio, pull->bPrintComp);
+        gmx_fio_do_gmx_bool(fio, pull->bPrintRefValue);
+        gmx_fio_do_gmx_bool(fio, pull->bPrintComp);
     }
     else
     {
@@ -768,6 +749,14 @@ static void do_pull(t_fileio *fio, pull_params_t *pull, gmx_bool bRead,
     }
     gmx_fio_do_int(fio, pull->nstxout);
     gmx_fio_do_int(fio, pull->nstfout);
+    if (file_version >= tpxv_PullPrevStepCOMAsReference)
+    {
+        gmx_fio_do_gmx_bool(fio, pull->bSetPbcRefToPrevStepCOM);
+    }
+    else
+    {
+        pull->bSetPbcRefToPrevStepCOM = FALSE;
+    }
     if (bRead)
     {
         snew(pull->group, pull->ngroup);
@@ -789,7 +778,7 @@ static void do_pull(t_fileio *fio, pull_params_t *pull, gmx_bool bRead,
         {
             /* We read and ignore a pull coordinate for group 0 */
             do_pullgrp_tpx_pre95(fio, &pull->group[g], &pull->coord[std::max(g-1, 0)],
-                                 bRead, file_version);
+                                 bRead);
             if (g > 0)
             {
                 pull->coord[g-1].group[0] = 0;
@@ -811,6 +800,17 @@ static void do_pull(t_fileio *fio, pull_params_t *pull, gmx_bool bRead,
                           bRead, file_version, ePullOld, eGeomOld, dimOld);
         }
     }
+    if (file_version >= tpxv_PullAverage)
+    {
+        gmx_bool v;
+
+        v                  = pull->bXOutAverage;
+        gmx_fio_do_gmx_bool(fio, v);
+        pull->bXOutAverage = v;
+        v                  = pull->bFOutAverage;
+        gmx_fio_do_gmx_bool(fio, v);
+        pull->bFOutAverage = v;
+    }
 }
 
 
@@ -829,7 +829,7 @@ static void do_rotgrp(t_fileio *fio, t_rotgrp *rotg, gmx_bool bRead)
         snew(rotg->x_ref, rotg->nat);
     }
     gmx_fio_ndo_rvec(fio, rotg->x_ref, rotg->nat);
-    gmx_fio_do_rvec(fio, rotg->vec);
+    gmx_fio_do_rvec(fio, rotg->inputVec);
     gmx_fio_do_rvec(fio, rotg->pivot);
     gmx_fio_do_real(fio, rotg->rate);
     gmx_fio_do_real(fio, rotg->k);
@@ -914,8 +914,8 @@ static void do_swapcoords_tpx(t_fileio *fio, t_swapcoords *swap, gmx_bool bRead,
         {
             do_swapgroup(fio, &swap->grp[ig], bRead);
         }
-        gmx_fio_do_int(fio, swap->massw_split[eChannel0]);
-        gmx_fio_do_int(fio, swap->massw_split[eChannel1]);
+        gmx_fio_do_gmx_bool(fio, swap->massw_split[eChannel0]);
+        gmx_fio_do_gmx_bool(fio, swap->massw_split[eChannel1]);
         gmx_fio_do_int(fio, swap->nstswap);
         gmx_fio_do_int(fio, swap->nAverage);
         gmx_fio_do_real(fio, swap->threshold);
@@ -943,9 +943,9 @@ static void do_swapcoords_tpx(t_fileio *fio, t_swapcoords *swap, gmx_bool bRead,
         gmx_fio_do_int(fio, swap->grp[3].nat);
         gmx_fio_do_int(fio, swap->grp[eGrpSolvent].nat);
         gmx_fio_do_int(fio, swap->grp[eGrpSplit0].nat);
-        gmx_fio_do_int(fio, swap->massw_split[eChannel0]);
+        gmx_fio_do_gmx_bool(fio, swap->massw_split[eChannel0]);
         gmx_fio_do_int(fio, swap->grp[eGrpSplit1].nat);
-        gmx_fio_do_int(fio, swap->massw_split[eChannel1]);
+        gmx_fio_do_gmx_bool(fio, swap->massw_split[eChannel1]);
         gmx_fio_do_int(fio, swap->nstswap);
         gmx_fio_do_int(fio, swap->nAverage);
         gmx_fio_do_real(fio, swap->threshold);
@@ -1020,11 +1020,11 @@ static void do_legacy_efield(t_fileio *fio, gmx::KeyValueTreeObjectBuilder *root
 
 
 static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
-                        int file_version, real *fudgeQQ)
+                        int file_version)
 {
     int      i, j, k, idum = 0;
-    real     rdum, bd_temp;
-    gmx_bool bdum = 0;
+    real     rdum;
+    gmx_bool bdum = false;
 
     if (file_version != tpx_version)
     {
@@ -1063,14 +1063,7 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
         ir->init_step = idum;
     }
 
-    if (file_version >= 58)
-    {
-        gmx_fio_do_int(fio, ir->simulation_part);
-    }
-    else
-    {
-        ir->simulation_part = 1;
-    }
+    gmx_fio_do_int(fio, ir->simulation_part);
 
     if (file_version >= 67)
     {
@@ -1080,29 +1073,6 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
     {
         ir->nstcalcenergy = 1;
     }
-    if (file_version < 53)
-    {
-        /* The pbc info has been moved out of do_inputrec,
-         * since we always want it, also without reading the inputrec.
-         */
-        gmx_fio_do_int(fio, ir->ePBC);
-        if (file_version >= 45)
-        {
-            gmx_fio_do_int(fio, ir->bPeriodicMols);
-        }
-        else
-        {
-            if (ir->ePBC == 2)
-            {
-                ir->ePBC          = epbcXYZ;
-                ir->bPeriodicMols = TRUE;
-            }
-            else
-            {
-                ir->bPeriodicMols = FALSE;
-            }
-        }
-    }
     if (file_version >= 81)
     {
         gmx_fio_do_int(fio, ir->cutoff_scheme);
@@ -1118,33 +1088,11 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
     gmx_fio_do_int(fio, ir->ns_type);
     gmx_fio_do_int(fio, ir->nstlist);
     gmx_fio_do_int(fio, idum); /* used to be ndelta; not used anymore */
-    if (file_version < 41)
-    {
-        gmx_fio_do_int(fio, idum);
-        gmx_fio_do_int(fio, idum);
-    }
-    if (file_version >= 45)
-    {
-        gmx_fio_do_real(fio, ir->rtpi);
-    }
-    else
-    {
-        ir->rtpi = 0.05;
-    }
+
+    gmx_fio_do_real(fio, ir->rtpi);
+
     gmx_fio_do_int(fio, ir->nstcomm);
-    if (file_version > 34)
-    {
-        gmx_fio_do_int(fio, ir->comm_mode);
-    }
-    else if (ir->nstcomm < 0)
-    {
-        ir->comm_mode = ecmANGULAR;
-    }
-    else
-    {
-        ir->comm_mode = ecmLINEAR;
-    }
-    ir->nstcomm = abs(ir->nstcomm);
+    gmx_fio_do_int(fio, ir->comm_mode);
 
     /* ignore nstcheckpoint */
     if (file_version < tpxv_RemoveObsoleteParameters1)
@@ -1223,10 +1171,6 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
         gmx_fio_do_int(fio, dummy_nstcalclr);
     }
     gmx_fio_do_int(fio, ir->coulombtype);
-    if (file_version < 32 && ir->coulombtype == eelRF)
-    {
-        ir->coulombtype = eelRF_NEC_UNSUPPORTED;
-    }
     if (file_version >= 81)
     {
         gmx_fio_do_int(fio, ir->coulomb_modifier);
@@ -1250,72 +1194,41 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
     gmx_fio_do_real(fio, ir->rvdw);
     gmx_fio_do_int(fio, ir->eDispCorr);
     gmx_fio_do_real(fio, ir->epsilon_r);
-    if (file_version >= 37)
-    {
-        gmx_fio_do_real(fio, ir->epsilon_rf);
-    }
-    else
-    {
-        if (EEL_RF(ir->coulombtype))
-        {
-            ir->epsilon_rf = ir->epsilon_r;
-            ir->epsilon_r  = 1.0;
-        }
-        else
-        {
-            ir->epsilon_rf = 1.0;
-        }
-    }
+    gmx_fio_do_real(fio, ir->epsilon_rf);
     gmx_fio_do_real(fio, ir->tabext);
 
-    gmx_fio_do_int(fio, ir->gb_algorithm);
-    gmx_fio_do_int(fio, ir->nstgbradii);
-    gmx_fio_do_real(fio, ir->rgbradii);
-    gmx_fio_do_real(fio, ir->gb_saltconc);
-    gmx_fio_do_int(fio, ir->implicit_solvent);
-    if (file_version >= 55)
+    // This permits reading a .tpr file that used implicit solvent,
+    // and later permitting mdrun to refuse to run it.
+    if (bRead)
     {
-        gmx_fio_do_real(fio, ir->gb_epsilon_solvent);
-        gmx_fio_do_real(fio, ir->gb_obc_alpha);
-        gmx_fio_do_real(fio, ir->gb_obc_beta);
-        gmx_fio_do_real(fio, ir->gb_obc_gamma);
-        if (file_version >= 60)
+        if (file_version < tpxv_RemoveImplicitSolvation)
         {
-            gmx_fio_do_real(fio, ir->gb_dielectric_offset);
-            gmx_fio_do_int(fio, ir->sa_algorithm);
+            gmx_fio_do_int(fio, idum);
+            gmx_fio_do_int(fio, idum);
+            gmx_fio_do_real(fio, rdum);
+            gmx_fio_do_real(fio, rdum);
+            gmx_fio_do_int(fio, idum);
+            ir->implicit_solvent = (idum > 0);
         }
         else
         {
-            ir->gb_dielectric_offset = 0.009;
-            ir->sa_algorithm         = esaAPPROX;
+            ir->implicit_solvent = false;
         }
-        gmx_fio_do_real(fio, ir->sa_surface_tension);
-
-        /* Override sa_surface_tension if it is not changed in the mpd-file */
-        if (ir->sa_surface_tension < 0)
+        if (file_version < tpxv_RemoveImplicitSolvation)
         {
-            if (ir->gb_algorithm == egbSTILL)
-            {
-                ir->sa_surface_tension = 0.0049 * 100 * CAL2JOULE;
-            }
-            else if (ir->gb_algorithm == egbHCT || ir->gb_algorithm == egbOBC)
+            gmx_fio_do_real(fio, rdum);
+            gmx_fio_do_real(fio, rdum);
+            gmx_fio_do_real(fio, rdum);
+            gmx_fio_do_real(fio, rdum);
+            if (file_version >= 60)
             {
-                ir->sa_surface_tension = 0.0054 * 100 * CAL2JOULE;
+                gmx_fio_do_real(fio, rdum);
+                gmx_fio_do_int(fio, idum);
             }
+            gmx_fio_do_real(fio, rdum);
         }
-
-    }
-    else
-    {
-        /* Better use sensible values than insane (0.0) ones... */
-        ir->gb_epsilon_solvent = 80;
-        ir->gb_obc_alpha       = 1.0;
-        ir->gb_obc_beta        = 0.8;
-        ir->gb_obc_gamma       = 4.85;
-        ir->sa_surface_tension = 2.092;
     }
 
-
     if (file_version >= 81)
     {
         gmx_fio_do_real(fio, ir->fourier_spacing);
@@ -1386,18 +1299,10 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
     gmx_fio_do_rvec(fio, ir->compress[XX]);
     gmx_fio_do_rvec(fio, ir->compress[YY]);
     gmx_fio_do_rvec(fio, ir->compress[ZZ]);
-    if (file_version >= 47)
-    {
-        gmx_fio_do_int(fio, ir->refcoord_scaling);
-        gmx_fio_do_rvec(fio, ir->posres_com);
-        gmx_fio_do_rvec(fio, ir->posres_comB);
-    }
-    else
-    {
-        ir->refcoord_scaling = erscNO;
-        clear_rvec(ir->posres_com);
-        clear_rvec(ir->posres_comB);
-    }
+    gmx_fio_do_int(fio, ir->refcoord_scaling);
+    gmx_fio_do_rvec(fio, ir->posres_com);
+    gmx_fio_do_rvec(fio, ir->posres_comB);
+
     if (file_version < 79)
     {
         gmx_fio_do_int(fio, ir->andersen_seed);
@@ -1407,17 +1312,7 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
         ir->andersen_seed = 0;
     }
 
-    if (file_version < 37)
-    {
-        gmx_fio_do_real(fio, rdum);
-    }
-
     gmx_fio_do_real(fio, ir->shake_tol);
-    if (file_version < 54)
-    {
-        // cppcheck-suppress redundantPointerOp
-        gmx_fio_do_real(fio, *fudgeQQ);
-    }
 
     gmx_fio_do_int(fio, ir->efep);
     do_fepvals(fio, ir->fepvals, bRead, file_version);
@@ -1455,10 +1350,8 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
     {
         do_expandedvals(fio, ir->expandedvals, ir->fepvals, bRead, file_version);
     }
-    if (file_version >= 57)
-    {
-        gmx_fio_do_int(fio, ir->eDisre);
-    }
+
+    gmx_fio_do_int(fio, ir->eDisre);
     gmx_fio_do_int(fio, ir->eDisreWeighting);
     gmx_fio_do_gmx_bool(fio, ir->bDisreMixed);
     gmx_fio_do_real(fio, ir->dr_fc);
@@ -1472,11 +1365,6 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
     if (file_version < 79)
     {
         gmx_fio_do_real(fio, rdum);
-        if (file_version < 56)
-        {
-            gmx_fio_do_real(fio, rdum);
-            gmx_fio_do_int(fio, idum);
-        }
     }
 
     gmx_fio_do_real(fio, ir->em_stepsize);
@@ -1488,10 +1376,6 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
     gmx_fio_do_int(fio, ir->nProjOrder);
     gmx_fio_do_real(fio, ir->LincsWarnAngle);
     gmx_fio_do_int(fio, ir->nLincsIter);
-    if (file_version < 33)
-    {
-        gmx_fio_do_real(fio, bd_temp);
-    }
     gmx_fio_do_real(fio, ir->bd_fric);
     if (file_version >= tpxv_Use64BitRandomSeed)
     {
@@ -1502,19 +1386,10 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
         gmx_fio_do_int(fio, idum);
         ir->ld_seed = idum;
     }
-    if (file_version >= 33)
-    {
-        for (i = 0; i < DIM; i++)
-        {
-            gmx_fio_do_rvec(fio, ir->deform[i]);
-        }
-    }
-    else
+
+    for (i = 0; i < DIM; i++)
     {
-        for (i = 0; i < DIM; i++)
-        {
-            clear_rvec(ir->deform[i]);
-        }
+        gmx_fio_do_rvec(fio, ir->deform[i]);
     }
     gmx_fio_do_real(fio, ir->cos_accel);
 
@@ -1567,7 +1442,6 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
     }
 
     /* pull stuff */
-    if (file_version >= 48)
     {
         int ePullOld = 0;
 
@@ -1591,10 +1465,6 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
             do_pull(fio, ir->pull, bRead, file_version, ePullOld);
         }
     }
-    else
-    {
-        ir->bPull = FALSE;
-    }
 
     if (file_version >= tpxv_AcceleratedWeightHistogram)
     {
@@ -1617,8 +1487,8 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
     /* Enforced rotation */
     if (file_version >= 74)
     {
-        gmx_fio_do_int(fio, ir->bRot);
-        if (ir->bRot == TRUE)
+        gmx_fio_do_gmx_bool(fio, ir->bRot);
+        if (ir->bRot)
         {
             if (bRead)
             {
@@ -1635,8 +1505,8 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
     /* Interactive molecular dynamics */
     if (file_version >= tpxv_InteractiveMolecularDynamics)
     {
-        gmx_fio_do_int(fio, ir->bIMD);
-        if (TRUE == ir->bIMD)
+        gmx_fio_do_gmx_bool(fio, ir->bIMD);
+        if (ir->bIMD)
         {
             if (bRead)
             {
@@ -1683,13 +1553,6 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
         gmx_fio_ndo_real(fio, ir->opts.nrdf, ir->opts.ngtc);
         gmx_fio_ndo_real(fio, ir->opts.ref_t, ir->opts.ngtc);
         gmx_fio_ndo_real(fio, ir->opts.tau_t, ir->opts.ngtc);
-        if (file_version < 33 && ir->eI == eiBD)
-        {
-            for (i = 0; i < ir->opts.ngtc; i++)
-            {
-                ir->opts.tau_t[i] = bd_temp;
-            }
-        }
     }
     if (ir->opts.ngfrz > 0)
     {
@@ -1717,34 +1580,17 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
         gmx_fio_ndo_real(fio, ir->opts.anneal_temp[j], k);
     }
     /* Walls */
-    if (file_version >= 45)
     {
         gmx_fio_do_int(fio, ir->nwall);
         gmx_fio_do_int(fio, ir->wall_type);
-        if (file_version >= 50)
-        {
-            gmx_fio_do_real(fio, ir->wall_r_linpot);
-        }
-        else
-        {
-            ir->wall_r_linpot = -1;
-        }
+        gmx_fio_do_real(fio, ir->wall_r_linpot);
         gmx_fio_do_int(fio, ir->wall_atomtype[0]);
         gmx_fio_do_int(fio, ir->wall_atomtype[1]);
         gmx_fio_do_real(fio, ir->wall_density[0]);
         gmx_fio_do_real(fio, ir->wall_density[1]);
         gmx_fio_do_real(fio, ir->wall_ewald_zfac);
     }
-    else
-    {
-        ir->nwall            = 0;
-        ir->wall_type        = 0;
-        ir->wall_atomtype[0] = -1;
-        ir->wall_atomtype[1] = -1;
-        ir->wall_density[0]  = 0;
-        ir->wall_density[1]  = 0;
-        ir->wall_ewald_zfac  = 3;
-    }
+
     /* Cosine stuff for electric fields */
     if (file_version < tpxv_GenericParamsForElectricField)
     {
@@ -1766,7 +1612,6 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
     }
 
     /* QMMM stuff */
-    if (file_version >= 39)
     {
         gmx_fio_do_gmx_bool(fio, ir->bQMMM);
         gmx_fio_do_int(fio, ir->QMMMscheme);
@@ -1785,7 +1630,7 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
             snew(ir->opts.SAoff,       ir->opts.ngQM);
             snew(ir->opts.SAsteps,     ir->opts.ngQM);
         }
-        if (ir->opts.ngQM > 0)
+        if (ir->opts.ngQM > 0 && ir->bQMMM)
         {
             gmx_fio_ndo_int(fio, ir->opts.QMmethod, ir->opts.ngQM);
             gmx_fio_ndo_int(fio, ir->opts.QMbasis, ir->opts.ngQM);
@@ -1801,8 +1646,8 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
              * changing the tpr format for every QMMM change.
              */
             std::vector<int> dummy(ir->opts.ngQM, 0);
-            gmx_fio_ndo_gmx_bool(fio, dummy.data(), ir->opts.ngQM);
-            gmx_fio_ndo_gmx_bool(fio, dummy.data(), ir->opts.ngQM);
+            gmx_fio_ndo_int(fio, dummy.data(), ir->opts.ngQM);
+            gmx_fio_ndo_int(fio, dummy.data(), ir->opts.ngQM);
         }
         /* end of QMMM stuff */
     }
@@ -2007,20 +1852,9 @@ static void do_iparams(t_fileio *fio, t_functype ftype, t_iparams *iparams,
         case F_ANGRESZ:
             gmx_fio_do_real(fio, iparams->pdihs.phiA);
             gmx_fio_do_real(fio, iparams->pdihs.cpA);
-            if ((ftype == F_ANGRES || ftype == F_ANGRESZ) && file_version < 42)
-            {
-                /* Read the incorrectly stored multiplicity */
-                gmx_fio_do_real(fio, iparams->harmonic.rB);
-                gmx_fio_do_real(fio, iparams->harmonic.krB);
-                iparams->pdihs.phiB = iparams->pdihs.phiA;
-                iparams->pdihs.cpB  = iparams->pdihs.cpA;
-            }
-            else
-            {
-                gmx_fio_do_real(fio, iparams->pdihs.phiB);
-                gmx_fio_do_real(fio, iparams->pdihs.cpB);
-                gmx_fio_do_int(fio, iparams->pdihs.mult);
-            }
+            gmx_fio_do_real(fio, iparams->pdihs.phiB);
+            gmx_fio_do_real(fio, iparams->pdihs.cpB);
+            gmx_fio_do_int(fio, iparams->pdihs.mult);
             break;
         case F_RESTRDIHS:
             gmx_fio_do_real(fio, iparams->pdihs.phiA);
@@ -2119,22 +1953,28 @@ static void do_iparams(t_fileio *fio, t_functype ftype, t_iparams *iparams,
             gmx_fio_do_int(fio, iparams->vsiten.n);
             gmx_fio_do_real(fio, iparams->vsiten.a);
             break;
-        case F_GB12:
-        case F_GB13:
-        case F_GB14:
-            /* We got rid of some parameters in version 68 */
-            if (bRead && file_version < 68)
+        case F_GB12_NOLONGERUSED:
+        case F_GB13_NOLONGERUSED:
+        case F_GB14_NOLONGERUSED:
+            // Implicit solvent parameters can still be read, but never used
+            if (bRead)
             {
-                gmx_fio_do_real(fio, rdum);
-                gmx_fio_do_real(fio, rdum);
-                gmx_fio_do_real(fio, rdum);
-                gmx_fio_do_real(fio, rdum);
+                if (file_version < 68)
+                {
+                    gmx_fio_do_real(fio, rdum);
+                    gmx_fio_do_real(fio, rdum);
+                    gmx_fio_do_real(fio, rdum);
+                    gmx_fio_do_real(fio, rdum);
+                }
+                if (file_version < tpxv_RemoveImplicitSolvation)
+                {
+                    gmx_fio_do_real(fio, rdum);
+                    gmx_fio_do_real(fio, rdum);
+                    gmx_fio_do_real(fio, rdum);
+                    gmx_fio_do_real(fio, rdum);
+                    gmx_fio_do_real(fio, rdum);
+                }
             }
-            gmx_fio_do_real(fio, iparams->gb.sar);
-            gmx_fio_do_real(fio, iparams->gb.st);
-            gmx_fio_do_real(fio, iparams->gb.pi);
-            gmx_fio_do_real(fio, iparams->gb.gbr);
-            gmx_fio_do_real(fio, iparams->gb.bmlt);
             break;
         case F_CMAP:
             gmx_fio_do_int(fio, iparams->cmap.cmapA);
@@ -2146,44 +1986,30 @@ static void do_iparams(t_fileio *fio, t_functype ftype, t_iparams *iparams,
     }
 }
 
-static void do_ilist(t_fileio *fio, t_ilist *ilist, gmx_bool bRead, int file_version)
+static void do_ilist(t_fileio *fio, InteractionList *ilist, gmx_bool bRead)
 {
-    int      i, idum;
-
-    if (file_version < 44)
-    {
-        for (i = 0; i < MAXNODES; i++)
-        {
-            gmx_fio_do_int(fio, idum);
-        }
-    }
-    gmx_fio_do_int(fio, ilist->nr);
+    int nr = ilist->size();
+    gmx_fio_do_int(fio, nr);
     if (bRead)
     {
-        snew(ilist->iatoms, ilist->nr);
+        ilist->iatoms.resize(nr);
     }
-    gmx_fio_ndo_int(fio, ilist->iatoms, ilist->nr);
+    gmx_fio_ndo_int(fio, ilist->iatoms.data(), ilist->size());
 }
 
 static void do_ffparams(t_fileio *fio, gmx_ffparams_t *ffparams,
                         gmx_bool bRead, int file_version)
 {
-    int          idum, i;
-    unsigned int k;
-
     gmx_fio_do_int(fio, ffparams->atnr);
-    if (file_version < 57)
-    {
-        gmx_fio_do_int(fio, idum);
-    }
-    gmx_fio_do_int(fio, ffparams->ntypes);
+    int numTypes = ffparams->numTypes();
+    gmx_fio_do_int(fio, numTypes);
     if (bRead)
     {
-        snew(ffparams->functype, ffparams->ntypes);
-        snew(ffparams->iparams, ffparams->ntypes);
+        ffparams->functype.resize(numTypes);
+        ffparams->iparams.resize(numTypes);
     }
     /* Read/write all the function types */
-    gmx_fio_ndo_int(fio, ffparams->functype, ffparams->ntypes);
+    gmx_fio_ndo_int(fio, ffparams->functype.data(), ffparams->functype.size());
 
     if (file_version >= 66)
     {
@@ -2194,21 +2020,18 @@ static void do_ffparams(t_fileio *fio, gmx_ffparams_t *ffparams,
         ffparams->reppow = 12.0;
     }
 
-    if (file_version >= 57)
-    {
-        gmx_fio_do_real(fio, ffparams->fudgeQQ);
-    }
+    gmx_fio_do_real(fio, ffparams->fudgeQQ);
 
     /* Check whether all these function types are supported by the code.
      * In practice the code is backwards compatible, which means that the
      * numbering may have to be altered from old numbering to new numbering
      */
-    for (i = 0; (i < ffparams->ntypes); i++)
+    for (int i = 0; i < ffparams->numTypes(); i++)
     {
         if (bRead)
         {
             /* Loop over file versions */
-            for (k = 0; (k < NFTUPD); k++)
+            for (int k = 0; k < NFTUPD; k++)
             {
                 /* Compare the read file_version to the update table */
                 if ((file_version < ftupd[k].fvnr) &&
@@ -2224,35 +2047,34 @@ static void do_ffparams(t_fileio *fio, gmx_ffparams_t *ffparams,
     }
 }
 
-static void add_settle_atoms(t_ilist *ilist)
+static void add_settle_atoms(InteractionList *ilist)
 {
     int i;
 
     /* Settle used to only store the first atom: add the other two */
-    srenew(ilist->iatoms, 2*ilist->nr);
-    for (i = ilist->nr/2-1; i >= 0; i--)
+    ilist->iatoms.resize(2*ilist->size());
+    for (i = ilist->size()/4 - 1; i >= 0; i--)
     {
         ilist->iatoms[4*i+0] = ilist->iatoms[2*i+0];
         ilist->iatoms[4*i+1] = ilist->iatoms[2*i+1];
         ilist->iatoms[4*i+2] = ilist->iatoms[2*i+1] + 1;
         ilist->iatoms[4*i+3] = ilist->iatoms[2*i+1] + 2;
     }
-    ilist->nr = 2*ilist->nr;
 }
 
-static void do_ilists(t_fileio *fio, t_ilist *ilist, gmx_bool bRead,
+static void do_ilists(t_fileio *fio, InteractionLists *ilists, gmx_bool bRead,
                       int file_version)
 {
-    int          j;
-    gmx_bool     bClear;
-    unsigned int k;
+    GMX_RELEASE_ASSERT(ilists, "Need a valid ilists object");
+    GMX_RELEASE_ASSERT(ilists->size() == F_NRE, "The code needs to be in sync with InteractionLists");
 
-    for (j = 0; (j < F_NRE); j++)
+    for (int j = 0; j < F_NRE; j++)
     {
-        bClear = FALSE;
+        InteractionList &ilist  = (*ilists)[j];
+        gmx_bool         bClear = FALSE;
         if (bRead)
         {
-            for (k = 0; k < NFTUPD; k++)
+            for (int k = 0; k < NFTUPD; k++)
             {
                 if ((file_version < ftupd[k].fvnr) && (j == ftupd[k].ftype))
                 {
@@ -2262,49 +2084,22 @@ static void do_ilists(t_fileio *fio, t_ilist *ilist, gmx_bool bRead,
         }
         if (bClear)
         {
-            ilist[j].nr     = 0;
-            ilist[j].iatoms = nullptr;
+            ilist.iatoms.clear();
         }
         else
         {
-            do_ilist(fio, &ilist[j], bRead, file_version);
-            if (file_version < 78 && j == F_SETTLE && ilist[j].nr > 0)
+            do_ilist(fio, &ilist, bRead);
+            if (file_version < 78 && j == F_SETTLE && ilist.size() > 0)
             {
-                add_settle_atoms(&ilist[j]);
+                add_settle_atoms(&ilist);
             }
         }
     }
 }
 
-static void do_idef(t_fileio *fio, gmx_ffparams_t *ffparams, gmx_moltype_t *molt,
-                    gmx_bool bRead, int file_version)
+static void do_block(t_fileio *fio, t_block *block, gmx_bool bRead)
 {
-    do_ffparams(fio, ffparams, bRead, file_version);
-
-    if (file_version >= 54)
-    {
-        gmx_fio_do_real(fio, ffparams->fudgeQQ);
-    }
-
-    do_ilists(fio, molt->ilist, bRead, file_version);
-}
-
-static void do_block(t_fileio *fio, t_block *block, gmx_bool bRead, int file_version)
-{
-    int      i, idum, dum_nra, *dum_a;
-
-    if (file_version < 44)
-    {
-        for (i = 0; i < MAXNODES; i++)
-        {
-            gmx_fio_do_int(fio, idum);
-        }
-    }
     gmx_fio_do_int(fio, block->nr);
-    if (file_version < 51)
-    {
-        gmx_fio_do_int(fio, dum_nra);
-    }
     if (bRead)
     {
         if ((block->nalloc_index > 0) && (nullptr != block->index))
@@ -2315,27 +2110,10 @@ static void do_block(t_fileio *fio, t_block *block, gmx_bool bRead, int file_ver
         snew(block->index, block->nalloc_index);
     }
     gmx_fio_ndo_int(fio, block->index, block->nr+1);
-
-    if (file_version < 51 && dum_nra > 0)
-    {
-        snew(dum_a, dum_nra);
-        gmx_fio_ndo_int(fio, dum_a, dum_nra);
-        sfree(dum_a);
-    }
 }
 
-static void do_blocka(t_fileio *fio, t_blocka *block, gmx_bool bRead,
-                      int file_version)
+static void do_blocka(t_fileio *fio, t_blocka *block, gmx_bool bRead)
 {
-    int      i, idum;
-
-    if (file_version < 44)
-    {
-        for (i = 0; i < MAXNODES; i++)
-        {
-            gmx_fio_do_int(fio, idum);
-        }
-    }
     gmx_fio_do_int(fio, block->nr);
     gmx_fio_do_int(fio, block->nra);
     if (bRead)
@@ -2390,11 +2168,8 @@ atomicnumber_to_element(int atomicnumber)
 }
 
 
-static void do_atom(t_fileio *fio, t_atom *atom, int ngrp, gmx_bool bRead,
-                    int file_version, gmx_groups_t *groups, int atnr)
+static void do_atom(t_fileio *fio, t_atom *atom, gmx_bool bRead)
 {
-    int    i, myngrp;
-
     gmx_fio_do_real(fio, atom->m);
     gmx_fio_do_real(fio, atom->q);
     gmx_fio_do_real(fio, atom->mB);
@@ -2403,78 +2178,28 @@ static void do_atom(t_fileio *fio, t_atom *atom, int ngrp, gmx_bool bRead,
     gmx_fio_do_ushort(fio, atom->typeB);
     gmx_fio_do_int(fio, atom->ptype);
     gmx_fio_do_int(fio, atom->resind);
-    if (file_version >= 52)
-    {
-        gmx_fio_do_int(fio, atom->atomnumber);
-        if (bRead)
-        {
-            /* Set element string from atomic number if present.
-             * This routine returns an empty string if the name is not found.
-             */
-            std::strncpy(atom->elem, atomicnumber_to_element(atom->atomnumber), 4);
-            /* avoid warnings about potentially unterminated string */
-            atom->elem[3] = '\0';
-        }
-    }
-    else if (bRead)
-    {
-        atom->atomnumber = 0;
-    }
-    if (file_version < 39)
-    {
-        myngrp = 9;
-    }
-    else
-    {
-        myngrp = ngrp;
-    }
-
-    if (file_version < 57)
+    gmx_fio_do_int(fio, atom->atomnumber);
+    if (bRead)
     {
-        unsigned char uchar[egcNR];
-        gmx_fio_ndo_uchar(fio, uchar, myngrp);
-        for (i = myngrp; (i < ngrp); i++)
-        {
-            uchar[i] = 0;
-        }
-        /* Copy the old data format to the groups struct */
-        for (i = 0; i < ngrp; i++)
-        {
-            groups->grpnr[i][atnr] = uchar[i];
-        }
+        /* Set element string from atomic number if present.
+         * This routine returns an empty string if the name is not found.
+         */
+        std::strncpy(atom->elem, atomicnumber_to_element(atom->atomnumber), 4);
+        /* avoid warnings about potentially unterminated string */
+        atom->elem[3] = '\0';
     }
 }
 
-static void do_grps(t_fileio *fio, int ngrp, t_grps grps[], gmx_bool bRead,
-                    int file_version)
+static void do_grps(t_fileio *fio, int ngrp, t_grps grps[], gmx_bool bRead)
 {
-    int      j, myngrp;
-
-    if (file_version < 39)
-    {
-        myngrp = 9;
-    }
-    else
-    {
-        myngrp = ngrp;
-    }
-
-    for (j = 0; (j < ngrp); j++)
+    for (int j = 0; j < ngrp; j++)
     {
-        if (j < myngrp)
-        {
-            gmx_fio_do_int(fio, grps[j].nr);
-            if (bRead)
-            {
-                snew(grps[j].nm_ind, grps[j].nr);
-            }
-            gmx_fio_ndo_int(fio, grps[j].nm_ind, grps[j].nr);
-        }
-        else
+        gmx_fio_do_int(fio, grps[j].nr);
+        if (bRead)
         {
-            grps[j].nr = 1;
             snew(grps[j].nm_ind, grps[j].nr);
         }
+        gmx_fio_ndo_int(fio, grps[j].nm_ind, grps[j].nr);
     }
 }
 
@@ -2527,22 +2252,12 @@ static void do_resinfo(t_fileio *fio, int n, t_resinfo *ri, gmx_bool bRead,
 }
 
 static void do_atoms(t_fileio *fio, t_atoms *atoms, gmx_bool bRead, t_symtab *symtab,
-                     int file_version,
-                     gmx_groups_t *groups)
+                     int file_version)
 {
     int i;
 
     gmx_fio_do_int(fio, atoms->nr);
     gmx_fio_do_int(fio, atoms->nres);
-    if (file_version < 57)
-    {
-        gmx_fio_do_int(fio, groups->ngrpname);
-        for (i = 0; i < egcNR; i++)
-        {
-            groups->ngrpnr[i] = atoms->nr;
-            snew(groups->grpnr[i], groups->ngrpnr[i]);
-        }
-    }
     if (bRead)
     {
         /* Since we have always written all t_atom properties in the tpr file
@@ -2560,10 +2275,6 @@ static void do_atoms(t_fileio *fio, t_atoms *atoms, gmx_bool bRead, t_symtab *sy
         snew(atoms->atomtype, atoms->nr);
         snew(atoms->atomtypeB, atoms->nr);
         snew(atoms->resinfo, atoms->nres);
-        if (file_version < 57)
-        {
-            snew(groups->grpname, groups->ngrpname);
-        }
         atoms->pdbinfo = nullptr;
     }
     else
@@ -2572,29 +2283,21 @@ static void do_atoms(t_fileio *fio, t_atoms *atoms, gmx_bool bRead, t_symtab *sy
     }
     for (i = 0; (i < atoms->nr); i++)
     {
-        do_atom(fio, &atoms->atom[i], egcNR, bRead, file_version, groups, i);
+        do_atom(fio, &atoms->atom[i], bRead);
     }
     do_strstr(fio, atoms->nr, atoms->atomname, bRead, symtab);
     do_strstr(fio, atoms->nr, atoms->atomtype, bRead, symtab);
     do_strstr(fio, atoms->nr, atoms->atomtypeB, bRead, symtab);
 
     do_resinfo(fio, atoms->nres, atoms->resinfo, bRead, symtab, file_version);
-
-    if (file_version < 57)
-    {
-        do_strstr(fio, groups->ngrpname, groups->grpname, bRead, symtab);
-
-        do_grps(fio, egcNR, groups->grps, bRead, file_version);
-    }
 }
 
 static void do_groups(t_fileio *fio, gmx_groups_t *groups,
-                      gmx_bool bRead, t_symtab *symtab,
-                      int file_version)
+                      gmx_bool bRead, t_symtab *symtab)
 {
     int      g;
 
-    do_grps(fio, egcNR, groups->grps, bRead, file_version);
+    do_grps(fio, egcNR, groups->grps, bRead);
     gmx_fio_do_int(fio, groups->ngrpname);
     if (bRead)
     {
@@ -2631,24 +2334,22 @@ static void do_atomtypes(t_fileio *fio, t_atomtypes *atomtypes, gmx_bool bRead,
     j = atomtypes->nr;
     if (bRead)
     {
-        snew(atomtypes->radius, j);
-        snew(atomtypes->vol, j);
-        snew(atomtypes->surftens, j);
         snew(atomtypes->atomnumber, j);
-        snew(atomtypes->gb_radius, j);
-        snew(atomtypes->S_hct, j);
     }
-    gmx_fio_ndo_real(fio, atomtypes->radius, j);
-    gmx_fio_ndo_real(fio, atomtypes->vol, j);
-    gmx_fio_ndo_real(fio, atomtypes->surftens, j);
-    if (file_version >= 40)
+    if (bRead && file_version < tpxv_RemoveImplicitSolvation)
     {
-        gmx_fio_ndo_int(fio, atomtypes->atomnumber, j);
+        std::vector<real> dummy(atomtypes->nr, 0);
+        gmx_fio_ndo_real(fio, dummy.data(), dummy.size());
+        gmx_fio_ndo_real(fio, dummy.data(), dummy.size());
+        gmx_fio_ndo_real(fio, dummy.data(), dummy.size());
     }
-    if (file_version >= 60)
+    gmx_fio_ndo_int(fio, atomtypes->atomnumber, j);
+
+    if (bRead && file_version >= 60 && file_version < tpxv_RemoveImplicitSolvation)
     {
-        gmx_fio_ndo_real(fio, atomtypes->gb_radius, j);
-        gmx_fio_ndo_real(fio, atomtypes->S_hct, j);
+        std::vector<real> dummy(atomtypes->nr, 0);
+        gmx_fio_ndo_real(fio, dummy.data(), dummy.size());
+        gmx_fio_ndo_real(fio, dummy.data(), dummy.size());
     }
 }
 
@@ -2693,28 +2394,27 @@ static void do_symtab(t_fileio *fio, t_symtab *symtab, gmx_bool bRead)
 
 static void do_cmap(t_fileio *fio, gmx_cmap_t *cmap_grid, gmx_bool bRead)
 {
-    int i, j, ngrid, gs, nelem;
 
-    gmx_fio_do_int(fio, cmap_grid->ngrid);
+    int ngrid = cmap_grid->cmapdata.size();
+    gmx_fio_do_int(fio, ngrid);
     gmx_fio_do_int(fio, cmap_grid->grid_spacing);
 
-    ngrid = cmap_grid->ngrid;
-    gs    = cmap_grid->grid_spacing;
-    nelem = gs * gs;
+    int gs    = cmap_grid->grid_spacing;
+    int nelem = gs * gs;
 
     if (bRead)
     {
-        snew(cmap_grid->cmapdata, ngrid);
+        cmap_grid->cmapdata.resize(ngrid);
 
-        for (i = 0; i < cmap_grid->ngrid; i++)
+        for (int i = 0; i < ngrid; i++)
         {
-            snew(cmap_grid->cmapdata[i].cmap, 4*nelem);
+            cmap_grid->cmapdata[i].cmap.resize(4*nelem);
         }
     }
 
-    for (i = 0; i < cmap_grid->ngrid; i++)
+    for (int i = 0; i < ngrid; i++)
     {
-        for (j = 0; j < nelem; j++)
+        for (int j = 0; j < nelem; j++)
         {
             gmx_fio_do_real(fio, cmap_grid->cmapdata[i].cmap[j*4]);
             gmx_fio_do_real(fio, cmap_grid->cmapdata[i].cmap[j*4+1]);
@@ -2726,193 +2426,75 @@ static void do_cmap(t_fileio *fio, gmx_cmap_t *cmap_grid, gmx_bool bRead)
 
 
 static void do_moltype(t_fileio *fio, gmx_moltype_t *molt, gmx_bool bRead,
-                       t_symtab *symtab, int file_version,
-                       gmx_groups_t *groups)
+                       t_symtab *symtab, int file_version)
 {
-    if (file_version >= 57)
-    {
-        do_symstr(fio, &(molt->name), bRead, symtab);
-    }
+    do_symstr(fio, &(molt->name), bRead, symtab);
 
-    do_atoms(fio, &molt->atoms, bRead, symtab, file_version, groups);
+    do_atoms(fio, &molt->atoms, bRead, symtab, file_version);
 
-    if (file_version >= 57)
-    {
-        do_ilists(fio, molt->ilist, bRead, file_version);
+    do_ilists(fio, &molt->ilist, bRead, file_version);
 
-        do_block(fio, &molt->cgs, bRead, file_version);
-    }
+    do_block(fio, &molt->cgs, bRead);
 
     /* This used to be in the atoms struct */
-    do_blocka(fio, &molt->excls, bRead, file_version);
+    do_blocka(fio, &molt->excls, bRead);
 }
 
-static void do_molblock(t_fileio *fio, gmx_molblock_t *molb, gmx_bool bRead)
+static void do_molblock(t_fileio *fio, gmx_molblock_t *molb,
+                        int numAtomsPerMolecule,
+                        gmx_bool bRead)
 {
     gmx_fio_do_int(fio, molb->type);
     gmx_fio_do_int(fio, molb->nmol);
-    gmx_fio_do_int(fio, molb->natoms_mol);
+    /* To maintain forward topology reading compatibility, we store #atoms.
+     * TODO: Change this to conditional reading of a dummy int when we
+     *       increase tpx_generation.
+     */
+    gmx_fio_do_int(fio, numAtomsPerMolecule);
     /* Position restraint coordinates */
-    gmx_fio_do_int(fio, molb->nposres_xA);
-    if (molb->nposres_xA > 0)
+    int numPosres_xA = molb->posres_xA.size();
+    gmx_fio_do_int(fio, numPosres_xA);
+    if (numPosres_xA > 0)
     {
         if (bRead)
         {
-            snew(molb->posres_xA, molb->nposres_xA);
+            molb->posres_xA.resize(numPosres_xA);
         }
-        gmx_fio_ndo_rvec(fio, molb->posres_xA, molb->nposres_xA);
+        gmx_fio_ndo_rvec(fio, as_rvec_array(molb->posres_xA.data()), numPosres_xA);
     }
-    gmx_fio_do_int(fio, molb->nposres_xB);
-    if (molb->nposres_xB > 0)
+    int numPosres_xB = molb->posres_xB.size();
+    gmx_fio_do_int(fio, numPosres_xB);
+    if (numPosres_xB > 0)
     {
         if (bRead)
         {
-            snew(molb->posres_xB, molb->nposres_xB);
+            molb->posres_xB.resize(numPosres_xB);
         }
-        gmx_fio_ndo_rvec(fio, molb->posres_xB, molb->nposres_xB);
+        gmx_fio_ndo_rvec(fio, as_rvec_array(molb->posres_xB.data()), numPosres_xB);
     }
 
 }
 
-static t_block mtop_mols(gmx_mtop_t *mtop)
-{
-    int     mb, m, a, mol;
-    t_block mols;
-
-    mols.nr = 0;
-    for (mb = 0; mb < mtop->nmolblock; mb++)
-    {
-        mols.nr += mtop->molblock[mb].nmol;
-    }
-    mols.nalloc_index = mols.nr + 1;
-    snew(mols.index, mols.nalloc_index);
-
-    a             = 0;
-    m             = 0;
-    mols.index[m] = a;
-    for (mb = 0; mb < mtop->nmolblock; mb++)
-    {
-        for (mol = 0; mol < mtop->molblock[mb].nmol; mol++)
-        {
-            a += mtop->molblock[mb].natoms_mol;
-            m++;
-            mols.index[m] = a;
-        }
-    }
-
-    return mols;
-}
-
-static void add_posres_molblock(gmx_mtop_t *mtop)
-{
-    t_ilist        *il, *ilfb;
-    int             am, i, mol, a;
-    gmx_bool        bFE;
-    gmx_molblock_t *molb;
-    t_iparams      *ip;
-
-    /* posres reference positions are stored in ip->posres (if present) and
-       in ip->fbposres (if present). If normal and flat-bottomed posres are present,
-       posres.pos0A are identical to fbposres.pos0. */
-    il   = &mtop->moltype[0].ilist[F_POSRES];
-    ilfb = &mtop->moltype[0].ilist[F_FBPOSRES];
-    if (il->nr == 0 && ilfb->nr == 0)
-    {
-        return;
-    }
-    am  = 0;
-    bFE = FALSE;
-    for (i = 0; i < il->nr; i += 2)
-    {
-        ip = &mtop->ffparams.iparams[il->iatoms[i]];
-        am = std::max(am, il->iatoms[i+1]);
-        if (ip->posres.pos0B[XX] != ip->posres.pos0A[XX] ||
-            ip->posres.pos0B[YY] != ip->posres.pos0A[YY] ||
-            ip->posres.pos0B[ZZ] != ip->posres.pos0A[ZZ])
-        {
-            bFE = TRUE;
-        }
-    }
-    /* This loop is required if we have only flat-bottomed posres:
-       - set am
-       - bFE == FALSE (no B-state for flat-bottomed posres) */
-    if (il->nr == 0)
-    {
-        for (i = 0; i < ilfb->nr; i += 2)
-        {
-            am = std::max(am, ilfb->iatoms[i+1]);
-        }
-    }
-    /* Make the posres coordinate block end at a molecule end */
-    mol = 0;
-    while (am >= mtop->mols.index[mol+1])
-    {
-        mol++;
-    }
-    molb             = &mtop->molblock[0];
-    molb->nposres_xA = mtop->mols.index[mol+1];
-    snew(molb->posres_xA, molb->nposres_xA);
-    if (bFE)
-    {
-        molb->nposres_xB = molb->nposres_xA;
-        snew(molb->posres_xB, molb->nposres_xB);
-    }
-    else
-    {
-        molb->nposres_xB = 0;
-    }
-    for (i = 0; i < il->nr; i += 2)
-    {
-        ip                     = &mtop->ffparams.iparams[il->iatoms[i]];
-        a                      = il->iatoms[i+1];
-        molb->posres_xA[a][XX] = ip->posres.pos0A[XX];
-        molb->posres_xA[a][YY] = ip->posres.pos0A[YY];
-        molb->posres_xA[a][ZZ] = ip->posres.pos0A[ZZ];
-        if (bFE)
-        {
-            molb->posres_xB[a][XX] = ip->posres.pos0B[XX];
-            molb->posres_xB[a][YY] = ip->posres.pos0B[YY];
-            molb->posres_xB[a][ZZ] = ip->posres.pos0B[ZZ];
-        }
-    }
-    if (il->nr == 0)
-    {
-        /* If only flat-bottomed posres are present, take reference pos from them.
-           Here: bFE == FALSE      */
-        for (i = 0; i < ilfb->nr; i += 2)
-        {
-            ip                     = &mtop->ffparams.iparams[ilfb->iatoms[i]];
-            a                      = ilfb->iatoms[i+1];
-            molb->posres_xA[a][XX] = ip->fbposres.pos0[XX];
-            molb->posres_xA[a][YY] = ip->fbposres.pos0[YY];
-            molb->posres_xA[a][ZZ] = ip->fbposres.pos0[ZZ];
-        }
-    }
-}
-
 static void set_disres_npair(gmx_mtop_t *mtop)
 {
-    t_iparams            *ip;
-    gmx_mtop_ilistloop_t  iloop;
-    t_ilist              *ilist, *il;
-    int                   nmol, i, npair;
-    t_iatom              *a;
+    gmx_mtop_ilistloop_t     iloop;
+    int                      nmol;
 
-    ip = mtop->ffparams.iparams;
+    gmx::ArrayRef<t_iparams> ip = mtop->ffparams.iparams;
 
     iloop     = gmx_mtop_ilistloop_init(mtop);
-    while (gmx_mtop_ilistloop_next(iloop, &ilist, &nmol))
+    while (const InteractionLists *ilist = gmx_mtop_ilistloop_next(iloop, &nmol))
     {
-        il = &ilist[F_DISRES];
+        const InteractionList &il = (*ilist)[F_DISRES];
 
-        if (il->nr > 0)
+        if (il.size() > 0)
         {
-            a     = il->iatoms;
-            npair = 0;
-            for (i = 0; i < il->nr; i += 3)
+            gmx::ArrayRef<const int> a     = il.iatoms;
+            int                      npair = 0;
+            for (int i = 0; i < il.size(); i += 3)
             {
                 npair++;
-                if (i+3 == il->nr || ip[a[i]].disres.label != ip[a[i+3]].disres.label)
+                if (i+3 == il.size() || ip[a[i]].disres.label != ip[a[i+3]].disres.label)
                 {
                     ip[a[i]].disres.npair = npair;
                     npair                 = 0;
@@ -2925,69 +2507,35 @@ static void set_disres_npair(gmx_mtop_t *mtop)
 static void do_mtop(t_fileio *fio, gmx_mtop_t *mtop, gmx_bool bRead,
                     int file_version)
 {
-    int            mt, mb;
-    t_blocka       dumb;
-
-    if (bRead)
-    {
-        init_mtop(mtop);
-    }
     do_symtab(fio, &(mtop->symtab), bRead);
 
     do_symstr(fio, &(mtop->name), bRead, &(mtop->symtab));
 
-    if (file_version >= 57)
-    {
-        do_ffparams(fio, &mtop->ffparams, bRead, file_version);
+    do_ffparams(fio, &mtop->ffparams, bRead, file_version);
 
-        gmx_fio_do_int(fio, mtop->nmoltype);
-    }
-    else
-    {
-        mtop->nmoltype = 1;
-    }
+    int nmoltype = mtop->moltype.size();
+    gmx_fio_do_int(fio, nmoltype);
     if (bRead)
     {
-        snew(mtop->moltype, mtop->nmoltype);
-        if (file_version < 57)
-        {
-            mtop->moltype[0].name = mtop->name;
-        }
+        mtop->moltype.resize(nmoltype);
     }
-    for (mt = 0; mt < mtop->nmoltype; mt++)
+    for (gmx_moltype_t &moltype : mtop->moltype)
     {
-        do_moltype(fio, &mtop->moltype[mt], bRead, &mtop->symtab, file_version,
-                   &mtop->groups);
+        do_moltype(fio, &moltype, bRead, &mtop->symtab, file_version);
     }
 
-    if (file_version >= 57)
-    {
-        gmx_fio_do_int(fio, mtop->nmolblock);
-    }
-    else
-    {
-        mtop->nmolblock = 1;
-    }
+    int nmolblock = mtop->molblock.size();
+    gmx_fio_do_int(fio, nmolblock);
     if (bRead)
     {
-        snew(mtop->molblock, mtop->nmolblock);
-    }
-    if (file_version >= 57)
-    {
-        for (mb = 0; mb < mtop->nmolblock; mb++)
-        {
-            do_molblock(fio, &mtop->molblock[mb], bRead);
-        }
-        gmx_fio_do_int(fio, mtop->natoms);
+        mtop->molblock.resize(nmolblock);
     }
-    else
+    for (gmx_molblock_t &molblock : mtop->molblock)
     {
-        mtop->molblock[0].type       = 0;
-        mtop->molblock[0].nmol       = 1;
-        mtop->molblock[0].natoms_mol = mtop->moltype[0].atoms.nr;
-        mtop->molblock[0].nposres_xA = 0;
-        mtop->molblock[0].nposres_xB = 0;
+        int numAtomsPerMolecule = (bRead ? 0 : mtop->moltype[molblock.type].atoms.nr);
+        do_molblock(fio, &molblock, numAtomsPerMolecule, bRead);
     }
+    gmx_fio_do_int(fio, mtop->natoms);
 
     if (file_version >= tpxv_IntermolecularBondeds)
     {
@@ -2996,9 +2544,9 @@ static void do_mtop(t_fileio *fio, gmx_mtop_t *mtop, gmx_bool bRead,
         {
             if (bRead)
             {
-                snew(mtop->intermolecular_ilist, F_NRE);
+                mtop->intermolecular_ilist = gmx::compat::make_unique<InteractionLists>();
             }
-            do_ilists(fio, mtop->intermolecular_ilist, bRead, file_version);
+            do_ilists(fio, mtop->intermolecular_ilist.get(), bRead, file_version);
         }
     }
     else
@@ -3008,57 +2556,19 @@ static void do_mtop(t_fileio *fio, gmx_mtop_t *mtop, gmx_bool bRead,
 
     do_atomtypes (fio, &(mtop->atomtypes), bRead, file_version);
 
-    if (file_version < 57)
-    {
-        do_idef (fio, &mtop->ffparams, &mtop->moltype[0], bRead, file_version);
-        mtop->natoms = mtop->moltype[0].atoms.nr;
-    }
-
     if (file_version >= 65)
     {
         do_cmap(fio, &mtop->ffparams.cmap_grid, bRead);
     }
     else
     {
-        mtop->ffparams.cmap_grid.ngrid        = 0;
         mtop->ffparams.cmap_grid.grid_spacing = 0;
-        mtop->ffparams.cmap_grid.cmapdata     = nullptr;
-    }
-
-    if (file_version >= 57)
-    {
-        do_groups(fio, &mtop->groups, bRead, &(mtop->symtab), file_version);
+        mtop->ffparams.cmap_grid.cmapdata.clear();
     }
 
-    if (file_version < 57)
-    {
-        do_block(fio, &mtop->moltype[0].cgs, bRead, file_version);
-        do_block(fio, &mtop->mols, bRead, file_version);
-        /* Add the posres coordinates to the molblock */
-        add_posres_molblock(mtop);
-    }
-    if (bRead)
-    {
-        if (file_version >= 57)
-        {
-            done_block(&mtop->mols);
-            mtop->mols = mtop_mols(mtop);
-        }
-    }
+    do_groups(fio, &mtop->groups, bRead, &(mtop->symtab));
 
-    if (file_version < 51)
-    {
-        /* Here used to be the shake blocks */
-        do_blocka(fio, &dumb, bRead, file_version);
-        if (dumb.nr > 0)
-        {
-            sfree(dumb.index);
-        }
-        if (dumb.nra > 0)
-        {
-            sfree(dumb.a);
-        }
-    }
+    mtop->haveMoleculeIndices = true;
 
     if (bRead)
     {
@@ -3093,7 +2603,7 @@ static void do_tpxheader(t_fileio *fio, gmx_bool bRead, t_tpxheader *tpx,
     if (bRead)
     {
         gmx_fio_do_string(fio, buf);
-        if (std::strncmp(buf, "VERSION", 7))
+        if (std::strncmp(buf, "VERSION", 7) != 0)
         {
             gmx_fatal(FARGS, "Can not read file %s,\n"
                       "             this file is from a GROMACS version which is older than 2.0\n"
@@ -3105,7 +2615,7 @@ static void do_tpxheader(t_fileio *fio, gmx_bool bRead, t_tpxheader *tpx,
         if ((precision != sizeof(float)) && !bDouble)
         {
             gmx_fatal(FARGS, "Unknown precision in file %s: real is %d bytes "
-                      "instead of %d or %d",
+                      "instead of %zu or %zu",
                       gmx_fio_getname(fio), precision, sizeof(float), sizeof(double));
         }
         gmx_fio_setprecision(fio, bDouble);
@@ -3199,12 +2709,12 @@ static void do_tpxheader(t_fileio *fio, gmx_bool bRead, t_tpxheader *tpx,
         gmx_fio_do_int(fio, tpx->fep_state);
     }
     gmx_fio_do_real(fio, tpx->lambda);
-    gmx_fio_do_int(fio, tpx->bIr);
-    gmx_fio_do_int(fio, tpx->bTop);
-    gmx_fio_do_int(fio, tpx->bX);
-    gmx_fio_do_int(fio, tpx->bV);
-    gmx_fio_do_int(fio, tpx->bF);
-    gmx_fio_do_int(fio, tpx->bBox);
+    gmx_fio_do_gmx_bool(fio, tpx->bIr);
+    gmx_fio_do_gmx_bool(fio, tpx->bTop);
+    gmx_fio_do_gmx_bool(fio, tpx->bX);
+    gmx_fio_do_gmx_bool(fio, tpx->bV);
+    gmx_fio_do_gmx_bool(fio, tpx->bF);
+    gmx_fio_do_gmx_bool(fio, tpx->bBox);
 
     if ((fileGeneration > tpx_generation))
     {
@@ -3218,7 +2728,6 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
                   gmx_mtop_t *mtop)
 {
     t_tpxheader     tpx;
-    gmx_mtop_t      dum_top;
     gmx_bool        TopOnlyOK;
     int             ePBC;
     gmx_bool        bPeriodicMols;
@@ -3232,10 +2741,10 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
         tpx.ngtc      = state->ngtc;
         tpx.fep_state = state->fep_state;
         tpx.lambda    = state->lambda[efptFEP];
-        tpx.bIr       = (ir       != nullptr);
-        tpx.bTop      = (mtop     != nullptr);
-        tpx.bX        = (state->flags & (1 << estX));
-        tpx.bV        = (state->flags & (1 << estV));
+        tpx.bIr       = ir       != nullptr;
+        tpx.bTop      = mtop     != nullptr;
+        tpx.bX        = (state->flags & (1 << estX)) != 0;
+        tpx.bV        = (state->flags & (1 << estV)) != 0;
         tpx.bF        = FALSE;
         tpx.bBox      = TRUE;
     }
@@ -3273,11 +2782,11 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
 
     if (x == nullptr)
     {
-        x = as_rvec_array(state->x.data());
-        v = as_rvec_array(state->v.data());
+        x = state->x.rvec_array();
+        v = state->v.rvec_array();
     }
 
-#define do_test(fio, b, p) if (bRead && (p != NULL) && !b) gmx_fatal(FARGS, "No %s in %s",#p, gmx_fio_getname(fio))
+#define do_test(fio, b, p) if (bRead && ((p) != NULL) && !(b)) gmx_fatal(FARGS, "No %s in %s",#p, gmx_fio_getname(fio))
 
     do_test(fio, tpx.bBox, state->box);
     if (tpx.bBox)
@@ -3322,8 +2831,8 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
         }
         else
         {
+            gmx_mtop_t dum_top;
             do_mtop(fio, &dum_top, bRead, fileVersion);
-            done_mtop(&dum_top);
         }
     }
     do_test(fio, tpx.bX, x);
@@ -3381,7 +2890,7 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
         }
         if (fileGeneration <= tpx_generation && ir)
         {
-            do_inputrec(fio, ir, bRead, fileVersion, mtop ? &mtop->ffparams.fudgeQQ : nullptr);
+            do_inputrec(fio, ir, bRead, fileVersion);
             if (fileVersion < 51)
             {
                 set_box_rel(ir, state);
@@ -3413,7 +2922,7 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
             {
                 if (fileVersion < 57)
                 {
-                    if (mtop->moltype[0].ilist[F_DISRES].nr > 0)
+                    if (mtop->moltype[0].ilist[F_DISRES].size() > 0)
                     {
                         ir->eDisre = edrSimple;
                     }