Sort all includes in src/gromacs
[alexxy/gromacs.git] / src / gromacs / fileio / tpxio.c
index f319075b4bf0864c403b9b59ba73b33b15c0396d..4fba747508fc6bb1bec86b89c7fd93924bf11bf7 100644 (file)
@@ -2,8 +2,8 @@
  * This file is part of the GROMACS molecular simulation package.
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * Copyright (c) 2013, by the GROMACS development team, led by
+ * Copyright (c) 2001-2004, The GROMACS development team.
+ * Copyright (c) 2013,2014, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
  * To help us fund GROMACS development, we humbly ask that you cite
  * the research papers on the package. Check out http://www.gromacs.org.
  */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#include "gmxpre.h"
 
 /* This file is completely threadsafe - keep it that way! */
-#ifdef GMX_THREAD_MPI
-#include <thread_mpi.h>
-#endif
-
-
-#include <ctype.h>
-#include "sysstuff.h"
-#include "smalloc.h"
-#include "string2.h"
-#include "gmx_fatal.h"
-#include "macros.h"
-#include "names.h"
-#include "symtab.h"
-#include "futil.h"
-#include "filenm.h"
-#include "gmxfio.h"
-#include "topsort.h"
+
 #include "tpxio.h"
-#include "txtdump.h"
-#include "confio.h"
-#include "atomprop.h"
-#include "copyrite.h"
-#include "vec.h"
-#include "mtop_util.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "gromacs/fileio/confio.h"
+#include "gromacs/fileio/filenm.h"
+#include "gromacs/fileio/gmxfio.h"
+#include "gromacs/legacyheaders/copyrite.h"
+#include "gromacs/legacyheaders/macros.h"
+#include "gromacs/legacyheaders/names.h"
+#include "gromacs/legacyheaders/txtdump.h"
+#include "gromacs/math/vec.h"
+#include "gromacs/topology/atomprop.h"
+#include "gromacs/topology/block.h"
+#include "gromacs/topology/mtop_util.h"
+#include "gromacs/topology/symtab.h"
+#include "gromacs/topology/topology.h"
+#include "gromacs/utility/cstringutil.h"
+#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/futil.h"
+#include "gromacs/utility/smalloc.h"
 
 #define TPX_TAG_RELEASE  "release"
 
-/* This is the tag string which is stored in the tpx file.
- * Change this if you want to change the tpx format in a feature branch.
- * This ensures that there will not be different tpx formats around which
- * can not be distinguished.
+/*! \brief Tag string for the file format written to run input files
+ * written by this version of the code.
+ *
+ * Change this if you want to change the run input format in a feature
+ * branch. This ensures that there will not be different run input
+ * formats around which cannot be distinguished, while not causing
+ * problems rebasing the feature branch onto upstream changes. When
+ * merging with mainstream GROMACS, set this tag string back to
+ * TPX_TAG_RELEASE, and instead add an element to tpxv and set
+ * tpx_version to that.
  */
 static const char *tpx_tag = TPX_TAG_RELEASE;
 
-/* This number should be increased whenever the file format changes! */
-static const int tpx_version = 92;
+/*! \brief Enum of values that describe the contents of a tpr file
+ * whose format matches a version number
+ *
+ * The enum helps the code be more self-documenting and ensure merges
+ * do not silently resolve when two patches make the same bump. When
+ * adding new functionality, add a new element to the end of this
+ * enumeration, change the definition of tpx_version, and write code
+ * below that does the right thing according to the value of
+ * file_version. */
+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_RestrictedBendingAndCombinedAngleTorsionPotentials, /**< potentials for supporting coarse-grained force fields */
+    tpxv_InteractiveMolecularDynamics,                       /**< interactive molecular dynamics (IMD) */
+    tpxv_RemoveObsoleteParameters1                           /**< remove optimize_fft, dihre_fc, nstcheckpoint */
+};
+
+/*! \brief Version number of the file format written to run input
+ * files by this version of the code.
+ *
+ * The tpx_version number should be increased whenever the file format
+ * in the main development branch changes, generally to the highest
+ * value present in tpxv. Backward compatibility for reading old run
+ * input files is maintained by checking this version number against
+ * that of the file and then using the correct code path.
+ *
+ * When developing a feature branch that needs to change the run input
+ * file format, change tpx_tag instead. */
+static const int tpx_version = tpxv_RemoveObsoleteParameters1;
+
 
 /* This number should only be increased when you edit the TOPOLOGY section
  * or the HEADER of the tpx format.
@@ -85,8 +116,11 @@ static const int tpx_version = 92;
  * It first appeared in tpx version 26, when I also moved the inputrecord
  * to the end of the tpx file, so we can just skip it if we only
  * want the topology.
+ *
+ * In particular, it must be increased when adding new elements to
+ * ftupd, so that old code can read new .tpr files.
  */
-static const int tpx_generation = 25;
+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.
@@ -138,12 +172,15 @@ static const t_ftupd ftupd[] = {
     { 43, F_TABBONDS          },
     { 43, F_TABBONDSNC        },
     { 70, F_RESTRBONDS        },
+    { tpxv_RestrictedBendingAndCombinedAngleTorsionPotentials, F_RESTRANGLES },
     { 76, F_LINEAR_ANGLES     },
     { 30, F_CROSS_BOND_BONDS  },
     { 30, F_CROSS_BOND_ANGLES },
     { 30, F_UREY_BRADLEY      },
     { 34, F_QUARTIC_ANGLES    },
     { 43, F_TABANGLES         },
+    { tpxv_RestrictedBendingAndCombinedAngleTorsionPotentials, F_RESTRDIHS },
+    { tpxv_RestrictedBendingAndCombinedAngleTorsionPotentials, F_CBTDIHS },
     { 26, F_FOURDIHS          },
     { 26, F_PIDIHS            },
     { 43, F_TABDIHS           },
@@ -158,6 +195,7 @@ static const t_ftupd ftupd[] = {
     { 32, F_BHAM_LR           },
     { 32, F_RF_EXCL           },
     { 32, F_COUL_RECIP        },
+    { 93, F_LJ_RECIP          },
     { 46, F_DPD               },
     { 30, F_POLARIZATION      },
     { 36, F_THOLE_POL         },
@@ -187,59 +225,19 @@ static const t_ftupd ftupd[] = {
 /* Needed for backward compatibility */
 #define MAXNODES 256
 
-static void _do_section(t_fileio *fio, int key, gmx_bool bRead, const char *src,
-                        int line)
-{
-    char     buf[STRLEN];
-    gmx_bool bDbg;
-
-    if (gmx_fio_getftp(fio) == efTPA)
-    {
-        if (!bRead)
-        {
-            gmx_fio_write_string(fio, itemstr[key]);
-            bDbg       = gmx_fio_getdebug(fio);
-            gmx_fio_setdebug(fio, FALSE);
-            gmx_fio_write_string(fio, comment_str[key]);
-            gmx_fio_setdebug(fio, bDbg);
-        }
-        else
-        {
-            if (gmx_fio_getdebug(fio))
-            {
-                fprintf(stderr, "Looking for section %s (%s, %d)",
-                        itemstr[key], src, line);
-            }
-
-            do
-            {
-                gmx_fio_do_string(fio, buf);
-            }
-            while ((gmx_strcasecmp(buf, itemstr[key]) != 0));
-
-            if (gmx_strcasecmp(buf, itemstr[key]) != 0)
-            {
-                gmx_fatal(FARGS, "\nCould not find section heading %s", itemstr[key]);
-            }
-            else if (gmx_fio_getdebug(fio))
-            {
-                fprintf(stderr, " and found it\n");
-            }
-        }
-    }
-}
-
-#define do_section(fio, key, bRead) _do_section(fio, key, bRead, __FILE__, __LINE__)
-
 /**************************************************************
  *
  * Now the higer level routines that do io of the structures and arrays
  *
  **************************************************************/
-static void do_pullgrp(t_fileio *fio, t_pullgrp *pgrp, gmx_bool bRead,
-                       int file_version)
+static void do_pullgrp_tpx_pre95(t_fileio     *fio,
+                                 t_pull_group *pgrp,
+                                 t_pull_coord *pcrd,
+                                 gmx_bool      bRead,
+                                 int           file_version)
 {
-    int      i;
+    int  i;
+    rvec tmp;
 
     gmx_fio_do_int(fio, pgrp->nat);
     if (bRead)
@@ -254,20 +252,55 @@ static void do_pullgrp(t_fileio *fio, t_pullgrp *pgrp, gmx_bool bRead,
     }
     gmx_fio_ndo_real(fio, pgrp->weight, pgrp->nweight);
     gmx_fio_do_int(fio, pgrp->pbcatom);
-    gmx_fio_do_rvec(fio, pgrp->vec);
-    gmx_fio_do_rvec(fio, pgrp->init);
-    gmx_fio_do_real(fio, pgrp->rate);
-    gmx_fio_do_real(fio, pgrp->k);
+    gmx_fio_do_rvec(fio, pcrd->vec);
+    clear_rvec(pcrd->origin);
+    gmx_fio_do_rvec(fio, tmp);
+    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, pgrp->kB);
+        gmx_fio_do_real(fio, pcrd->kB);
     }
     else
     {
-        pgrp->kB = pgrp->k;
+        pcrd->kB = pcrd->k;
     }
 }
 
+static void do_pull_group(t_fileio *fio, t_pull_group *pgrp, gmx_bool bRead)
+{
+    int      i;
+
+    gmx_fio_do_int(fio, pgrp->nat);
+    if (bRead)
+    {
+        snew(pgrp->ind, pgrp->nat);
+    }
+    gmx_fio_ndo_int(fio, pgrp->ind, pgrp->nat);
+    gmx_fio_do_int(fio, pgrp->nweight);
+    if (bRead)
+    {
+        snew(pgrp->weight, pgrp->nweight);
+    }
+    gmx_fio_ndo_real(fio, pgrp->weight, pgrp->nweight);
+    gmx_fio_do_int(fio, pgrp->pbcatom);
+}
+
+static void do_pull_coord(t_fileio *fio, t_pull_coord *pcrd)
+{
+    int      i;
+
+    gmx_fio_do_int(fio, pcrd->group[0]);
+    gmx_fio_do_int(fio, pcrd->group[1]);
+    gmx_fio_do_rvec(fio, pcrd->origin);
+    gmx_fio_do_rvec(fio, pcrd->vec);
+    gmx_fio_do_real(fio, pcrd->init);
+    gmx_fio_do_real(fio, pcrd->rate);
+    gmx_fio_do_real(fio, pcrd->k);
+    gmx_fio_do_real(fio, pcrd->kB);
+}
+
 static void do_expandedvals(t_fileio *fio, t_expanded *expand, t_lambda *fepvals, gmx_bool bRead, int file_version)
 {
     /* i is used in the ndo_double macro*/
@@ -335,6 +368,16 @@ static void do_simtempvals(t_fileio *fio, t_simtemp *simtemp, int n_lambda, gmx_
     }
 }
 
+static void do_imd(t_fileio *fio, t_IMD *imd, gmx_bool bRead)
+{
+    gmx_fio_do_int(fio, imd->nat);
+    if (bRead)
+    {
+        snew(imd->ind, imd->nat);
+    }
+    gmx_fio_ndo_int(fio, imd->ind, imd->nat);
+}
+
 static void do_fepvals(t_fileio *fio, t_lambda *fepvals, gmx_bool bRead, int file_version)
 {
     /* i is defined in the ndo_double macro; use g to iterate. */
@@ -520,11 +563,11 @@ 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->bPrintEnergy);
+        gmx_fio_do_int(fio, fepvals->edHdLPrintEnergy);
     }
     else
     {
-        fepvals->bPrintEnergy = FALSE;
+        fepvals->edHdLPrintEnergy = edHdLPrintEnergyNO;
     }
 
     /* handle lambda_neighbors */
@@ -564,21 +607,67 @@ static void do_pull(t_fileio *fio, t_pull *pull, gmx_bool bRead, int file_versio
 {
     int g;
 
-    gmx_fio_do_int(fio, pull->ngrp);
+    if (file_version >= 95)
+    {
+        gmx_fio_do_int(fio, pull->ngroup);
+    }
+    gmx_fio_do_int(fio, pull->ncoord);
+    if (file_version < 95)
+    {
+        pull->ngroup = pull->ncoord + 1;
+    }
     gmx_fio_do_int(fio, pull->eGeom);
     gmx_fio_do_ivec(fio, pull->dim);
     gmx_fio_do_real(fio, pull->cyl_r1);
     gmx_fio_do_real(fio, pull->cyl_r0);
     gmx_fio_do_real(fio, pull->constr_tol);
+    if (file_version >= 95)
+    {
+        gmx_fio_do_int(fio, pull->bPrintRef);
+    }
     gmx_fio_do_int(fio, pull->nstxout);
     gmx_fio_do_int(fio, pull->nstfout);
     if (bRead)
     {
-        snew(pull->grp, pull->ngrp+1);
+        snew(pull->group, pull->ngroup);
+        snew(pull->coord, pull->ncoord);
     }
-    for (g = 0; g < pull->ngrp+1; g++)
+    if (file_version < 95)
     {
-        do_pullgrp(fio, &pull->grp[g], bRead, file_version);
+        /* epullgPOS for position pulling, before epullgDIRPBC was removed */
+        if (pull->eGeom == epullgDIRPBC)
+        {
+            gmx_fatal(FARGS, "pull-geometry=position is no longer supported");
+        }
+        if (pull->eGeom > epullgDIRPBC)
+        {
+            pull->eGeom -= 1;
+        }
+
+        for (g = 0; g < pull->ngroup; g++)
+        {
+            /* We read and ignore a pull coordinate for group 0 */
+            do_pullgrp_tpx_pre95(fio, &pull->group[g], &pull->coord[max(g-1, 0)],
+                                 bRead, file_version);
+            if (g > 0)
+            {
+                pull->coord[g-1].group[0] = 0;
+                pull->coord[g-1].group[1] = g;
+            }
+        }
+
+        pull->bPrintRef = (pull->group[0].nat > 0);
+    }
+    else
+    {
+        for (g = 0; g < pull->ngroup; g++)
+        {
+            do_pull_group(fio, &pull->group[g], bRead);
+        }
+        for (g = 0; g < pull->ncoord; g++)
+        {
+            do_pull_coord(fio, &pull->coord[g]);
+        }
     }
 }
 
@@ -630,13 +719,61 @@ static void do_rot(t_fileio *fio, t_rot *rot, gmx_bool bRead)
 }
 
 
+static void do_swapcoords(t_fileio *fio, t_swapcoords *swap, gmx_bool bRead)
+{
+    int i, j;
+
+
+    gmx_fio_do_int(fio, swap->nat);
+    gmx_fio_do_int(fio, swap->nat_sol);
+    for (j = 0; j < 2; j++)
+    {
+        gmx_fio_do_int(fio, swap->nat_split[j]);
+        gmx_fio_do_int(fio, swap->massw_split[j]);
+    }
+    gmx_fio_do_int(fio, swap->nstswap);
+    gmx_fio_do_int(fio, swap->nAverage);
+    gmx_fio_do_real(fio, swap->threshold);
+    gmx_fio_do_real(fio, swap->cyl0r);
+    gmx_fio_do_real(fio, swap->cyl0u);
+    gmx_fio_do_real(fio, swap->cyl0l);
+    gmx_fio_do_real(fio, swap->cyl1r);
+    gmx_fio_do_real(fio, swap->cyl1u);
+    gmx_fio_do_real(fio, swap->cyl1l);
+
+    if (bRead)
+    {
+        snew(swap->ind, swap->nat);
+        snew(swap->ind_sol, swap->nat_sol);
+        for (j = 0; j < 2; j++)
+        {
+            snew(swap->ind_split[j], swap->nat_split[j]);
+        }
+    }
+
+    gmx_fio_ndo_int(fio, swap->ind, swap->nat);
+    gmx_fio_ndo_int(fio, swap->ind_sol, swap->nat_sol);
+    for (j = 0; j < 2; j++)
+    {
+        gmx_fio_ndo_int(fio, swap->ind_split[j], swap->nat_split[j]);
+    }
+
+    for (j = 0; j < eCompNR; j++)
+    {
+        gmx_fio_do_int(fio, swap->nanions[j]);
+        gmx_fio_do_int(fio, swap->ncations[j]);
+    }
+
+}
+
+
 static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
                         int file_version, real *fudgeQQ)
 {
     int      i, j, k, *tmp, idum = 0;
     real     rdum, bd_temp;
     rvec     vdum;
-    gmx_bool bSimAnn;
+    gmx_bool bSimAnn, bdum = 0;
     real     zerotemptime, finish_t, init_temp, finish_temp;
 
     if (file_version != tpx_version)
@@ -660,18 +797,19 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
     gmx_fio_do_int(fio, ir->eI);
     if (file_version >= 62)
     {
-        gmx_fio_do_gmx_large_int(fio, ir->nsteps);
+        gmx_fio_do_int64(fio, ir->nsteps);
     }
     else
     {
         gmx_fio_do_int(fio, idum);
         ir->nsteps = idum;
     }
+
     if (file_version > 25)
     {
         if (file_version >= 62)
         {
-            gmx_fio_do_gmx_large_int(fio, ir->init_step);
+            gmx_fio_do_int64(fio, ir->init_step);
         }
         else
         {
@@ -731,6 +869,10 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
     if (file_version >= 81)
     {
         gmx_fio_do_int(fio, ir->cutoff_scheme);
+        if (file_version < 94)
+        {
+            ir->cutoff_scheme = 1 - ir->cutoff_scheme;
+        }
     }
     else
     {
@@ -738,7 +880,7 @@ 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, ir->ndelta);
+    gmx_fio_do_int(fio, idum); /* used to be ndelta; not used anymore */
     if (file_version < 41)
     {
         gmx_fio_do_int(fio, idum);
@@ -767,13 +909,10 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
     }
     ir->nstcomm = abs(ir->nstcomm);
 
-    if (file_version > 25)
-    {
-        gmx_fio_do_int(fio, ir->nstcheckpoint);
-    }
-    else
+    /* ignore nstcheckpoint */
+    if (file_version > 25 && file_version < tpxv_RemoveObsoleteParameters1)
     {
-        ir->nstcheckpoint = 0;
+        gmx_fio_do_int(fio, idum);
     }
 
     gmx_fio_do_int(fio, ir->nstcgsteep);
@@ -792,7 +931,7 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
     gmx_fio_do_int(fio, ir->nstvout);
     gmx_fio_do_int(fio, ir->nstfout);
     gmx_fio_do_int(fio, ir->nstenergy);
-    gmx_fio_do_int(fio, ir->nstxtcout);
+    gmx_fio_do_int(fio, ir->nstxout_compressed);
     if (file_version >= 59)
     {
         gmx_fio_do_double(fio, ir->init_t);
@@ -805,7 +944,7 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
         gmx_fio_do_real(fio, rdum);
         ir->delta_t = rdum;
     }
-    gmx_fio_do_real(fio, ir->xtcprec);
+    gmx_fio_do_real(fio, ir->x_compression_precision);
     if (file_version < 19)
     {
         gmx_fio_do_int(fio, idum);
@@ -817,11 +956,11 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
     }
     if (file_version >= 81)
     {
-        gmx_fio_do_real(fio, ir->verletbuf_drift);
+        gmx_fio_do_real(fio, ir->verletbuf_tol);
     }
     else
     {
-        ir->verletbuf_drift = 0;
+        ir->verletbuf_tol = 0;
     }
     gmx_fio_do_real(fio, ir->rlist);
     if (file_version >= 67)
@@ -967,6 +1106,15 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
     gmx_fio_do_int(fio, ir->pme_order);
     gmx_fio_do_real(fio, ir->ewald_rtol);
 
+    if (file_version >= 93)
+    {
+        gmx_fio_do_real(fio, ir->ewald_rtol_lj);
+    }
+    else
+    {
+        ir->ewald_rtol_lj = ir->ewald_rtol;
+    }
+
     if (file_version >= 24)
     {
         gmx_fio_do_int(fio, ir->ewald_geometry);
@@ -989,8 +1137,16 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
         gmx_fio_do_real(fio, ir->epsilon_surface);
     }
 
-    gmx_fio_do_gmx_bool(fio, ir->bOptFFT);
+    /* ignore bOptFFT */
+    if (file_version < tpxv_RemoveObsoleteParameters1)
+    {
+        gmx_fio_do_gmx_bool(fio, bdum);
+    }
 
+    if (file_version >= 93)
+    {
+        gmx_fio_do_int(fio, ir->ljpme_combination_rule);
+    }
     gmx_fio_do_gmx_bool(fio, ir->bContinuation);
     gmx_fio_do_int(fio, ir->etc);
     /* before version 18, ir->etc was a gmx_bool (ir->btc),
@@ -1189,19 +1345,17 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
         ir->orires_tau  = 0;
         ir->nstorireout = 0;
     }
+
+    /* ignore dihre_fc */
     if (file_version >= 26 && file_version < 79)
     {
-        gmx_fio_do_real(fio, ir->dihre_fc);
+        gmx_fio_do_real(fio, rdum);
         if (file_version < 56)
         {
             gmx_fio_do_real(fio, rdum);
             gmx_fio_do_int(fio, idum);
         }
     }
-    else
-    {
-        ir->dihre_fc = 0;
-    }
 
     gmx_fio_do_real(fio, ir->em_stepsize);
     gmx_fio_do_real(fio, ir->em_tol);
@@ -1253,7 +1407,15 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
         gmx_fio_do_real(fio, bd_temp);
     }
     gmx_fio_do_real(fio, ir->bd_fric);
-    gmx_fio_do_int(fio, ir->ld_seed);
+    if (file_version >= tpxv_Use64BitRandomSeed)
+    {
+        gmx_fio_do_int64(fio, ir->ld_seed);
+    }
+    else
+    {
+        gmx_fio_do_int(fio, idum);
+        ir->ld_seed = idum;
+    }
     if (file_version >= 33)
     {
         for (i = 0; i < DIM; i++)
@@ -1366,6 +1528,25 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
         ir->bRot = FALSE;
     }
 
+    /* Interactive molecular dynamics */
+    if (file_version >= tpxv_InteractiveMolecularDynamics)
+    {
+        gmx_fio_do_int(fio, ir->bIMD);
+        if (TRUE == ir->bIMD)
+        {
+            if (bRead)
+            {
+                snew(ir->imd, 1);
+            }
+            do_imd(fio, ir->imd, bRead);
+        }
+    }
+    else
+    {
+        /* We don't support IMD sessions for old .tpr files */
+        ir->bIMD = FALSE;
+    }
+
     /* grpopts stuff */
     gmx_fio_do_int(fio, ir->opts.ngtc);
     if (file_version >= 69)
@@ -1524,6 +1705,20 @@ static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
         gmx_fio_ndo_real(fio, ir->et[j].phi, ir->et[j].n);
     }
 
+    /* Swap ions */
+    if (file_version >= tpxv_ComputationalElectrophysiology)
+    {
+        gmx_fio_do_int(fio, ir->eSwapCoords);
+        if (ir->eSwapCoords != eswapNO)
+        {
+            if (bRead)
+            {
+                snew(ir->swap, 1);
+            }
+            do_swapcoords(fio, ir->swap, bRead);
+        }
+    }
+
     /* QMMM stuff */
     if (file_version >= 39)
     {
@@ -1600,6 +1795,10 @@ void do_iparams(t_fileio *fio, t_functype ftype, t_iparams *iparams,
                 iparams->pdihs.cpB  = iparams->pdihs.cpA;
             }
             break;
+        case F_RESTRANGLES:
+            gmx_fio_do_real(fio, iparams->harmonic.rA);
+            gmx_fio_do_real(fio, iparams->harmonic.krA);
+            break;
         case F_LINEAR_ANGLES:
             gmx_fio_do_real(fio, iparams->linangle.klinA);
             gmx_fio_do_real(fio, iparams->linangle.aA);
@@ -1610,6 +1809,7 @@ void do_iparams(t_fileio *fio, t_functype ftype, t_iparams *iparams,
             gmx_fio_do_real(fio, iparams->fene.bm);
             gmx_fio_do_real(fio, iparams->fene.kb);
             break;
+
         case F_RESTRBONDS:
             gmx_fio_do_real(fio, iparams->restraint.lowA);
             gmx_fio_do_real(fio, iparams->restraint.up1A);
@@ -1762,6 +1962,10 @@ void do_iparams(t_fileio *fio, t_functype ftype, t_iparams *iparams,
                 gmx_fio_do_int(fio, iparams->pdihs.mult);
             }
             break;
+        case F_RESTRDIHS:
+            gmx_fio_do_real(fio, iparams->pdihs.phiA);
+            gmx_fio_do_real(fio, iparams->pdihs.cpA);
+            break;
         case F_DISRES:
             gmx_fio_do_int(fio, iparams->disres.label);
             gmx_fio_do_int(fio, iparams->disres.type);
@@ -1820,6 +2024,9 @@ void do_iparams(t_fileio *fio, t_functype ftype, t_iparams *iparams,
             gmx_fio_do_real(fio, iparams->fbposres.r);
             gmx_fio_do_real(fio, iparams->fbposres.k);
             break;
+        case F_CBTDIHS:
+            gmx_fio_ndo_real(fio, iparams->cbtdihs.cbtcA, NR_CBTDIHS);
+            break;
         case F_RBDIHS:
             gmx_fio_ndo_real(fio, iparams->rbdihs.rbcA, NR_RBDIHS);
             if (file_version >= 25)
@@ -2131,10 +2338,52 @@ static void do_blocka(t_fileio *fio, t_blocka *block, gmx_bool bRead,
     gmx_fio_ndo_int(fio, block->a, block->nra);
 }
 
+/* This is a primitive routine to make it possible to translate atomic numbers
+ * to element names when reading TPR files, without making the Gromacs library
+ * directory a dependency on mdrun (which is the case if we need elements.dat).
+ */
+static const char *
+atomicnumber_to_element(int atomicnumber)
+{
+    const char * p;
+
+    /* This does not have to be complete, so we only include elements likely
+     * to occur in PDB files.
+     */
+    switch (atomicnumber)
+    {
+        case 1:  p = "H";  break;
+        case 5:  p = "B";  break;
+        case 6:  p = "C";  break;
+        case 7:  p = "N";  break;
+        case 8:  p = "O";  break;
+        case 9:  p = "F";  break;
+        case 11: p = "Na"; break;
+        case 12: p = "Mg"; break;
+        case 15: p = "P";  break;
+        case 16: p = "S";  break;
+        case 17: p = "Cl"; break;
+        case 18: p = "Ar"; break;
+        case 19: p = "K";  break;
+        case 20: p = "Ca"; break;
+        case 25: p = "Mn"; break;
+        case 26: p = "Fe"; break;
+        case 28: p = "Ni"; break;
+        case 29: p = "Cu"; break;
+        case 30: p = "Zn"; break;
+        case 35: p = "Br"; break;
+        case 47: p = "Ag"; break;
+        default: p = "";   break;
+    }
+    return p;
+}
+
+
 static void do_atom(t_fileio *fio, t_atom *atom, int ngrp, gmx_bool bRead,
                     int file_version, gmx_groups_t *groups, int atnr)
 {
-    int i, myngrp;
+    int    i, myngrp;
+    char * p_elem;
 
     gmx_fio_do_real(fio, atom->m);
     gmx_fio_do_real(fio, atom->q);
@@ -2147,6 +2396,15 @@ static void do_atom(t_fileio *fio, t_atom *atom, int ngrp, gmx_bool bRead,
     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.
+             */
+            strncpy(atom->elem, atomicnumber_to_element(atom->atomnumber), 4);
+            /* avoid warnings about potentially unterminated string */
+            atom->elem[3] = '\0';
+        }
     }
     else if (bRead)
     {
@@ -2421,7 +2679,7 @@ static void do_symtab(t_fileio *fio, t_symtab *symtab, gmx_bool bRead)
         for (i = 0; (i < nr); i++)
         {
             gmx_fio_do_string(fio, buf);
-            symbuf->buf[i] = strdup(buf);
+            symbuf->buf[i] = gmx_strdup(buf);
         }
     }
     else
@@ -2732,8 +2990,8 @@ 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, i;
-    t_blocka dumb;
+    int            mt, mb, i;
+    t_blocka       dumb;
 
     if (bRead)
     {
@@ -2898,7 +3156,7 @@ static void do_tpxheader(t_fileio *fio, gmx_bool bRead, t_tpxheader *tpx,
     gmx_fio_checktype(fio);
     gmx_fio_setdebug(fio, bDebugMode());
 
-    /* NEW! XDR tpb file */
+    /* XDR binary topology file */
     precision = sizeof(real);
     if (bRead)
     {
@@ -3003,7 +3261,6 @@ static void do_tpxheader(t_fileio *fio, gmx_bool bRead, t_tpxheader *tpx,
                   gmx_fio_getname(fio), fver, tpx_version);
     }
 
-    do_section(fio, eitemHEADER, bRead);
     gmx_fio_do_int(fio, tpx->natoms);
     if (fver >= 28)
     {
@@ -3098,7 +3355,6 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
 #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);
-    do_section(fio, eitemBOX, bRead);
     if (tpx.bBox)
     {
         gmx_fio_ndo_rvec(fio, state->box, DIM);
@@ -3145,7 +3401,6 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
     if (file_version < 26)
     {
         do_test(fio, tpx.bIr, ir);
-        do_section(fio, eitemIR, bRead);
         if (tpx.bIr)
         {
             if (ir)
@@ -3172,7 +3427,6 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
     }
 
     do_test(fio, tpx.bTop, mtop);
-    do_section(fio, eitemTOP, bRead);
     if (tpx.bTop)
     {
         if (mtop)
@@ -3186,7 +3440,6 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
         }
     }
     do_test(fio, tpx.bX, state->x);
-    do_section(fio, eitemX, bRead);
     if (tpx.bX)
     {
         if (bRead)
@@ -3197,7 +3450,6 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
     }
 
     do_test(fio, tpx.bV, state->v);
-    do_section(fio, eitemV, bRead);
     if (tpx.bV)
     {
         if (bRead)
@@ -3208,7 +3460,6 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
     }
 
     do_test(fio, tpx.bF, f);
-    do_section(fio, eitemF, bRead);
     if (tpx.bF)
     {
         gmx_fio_ndo_rvec(fio, f, state->natoms);
@@ -3226,7 +3477,6 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
     if (file_version >= 26)
     {
         do_test(fio, tpx.bIr, ir);
-        do_section(fio, eitemIR, bRead);
         if (tpx.bIr)
         {
             if (file_version >= 53)
@@ -3410,15 +3660,7 @@ int read_tpx_top(const char *fn,
 
 gmx_bool fn2bTPX(const char *file)
 {
-    switch (fn2ftp(file))
-    {
-        case efTPR:
-        case efTPB:
-        case efTPA:
-            return TRUE;
-        default:
-            return FALSE;
-    }
+    return (efTPR == fn2ftp(file));
 }
 
 static void done_gmx_groups_t(gmx_groups_t *g)