29b0208b0310f1e13e127d5f6b468dd535ccdf82
[alexxy/gromacs.git] / src / gromacs / fileio / tpxio.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team.
6  * Copyright (c) 2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
7  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8  * and including many others, as listed in the AUTHORS file in the
9  * top-level source directory and at http://www.gromacs.org.
10  *
11  * GROMACS is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation; either version 2.1
14  * of the License, or (at your option) any later version.
15  *
16  * GROMACS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with GROMACS; if not, see
23  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25  *
26  * If you want to redistribute modifications to GROMACS, please
27  * consider that scientific software is very special. Version
28  * control is crucial - bugs must be traceable. We will be happy to
29  * consider code for inclusion in the official distribution, but
30  * derived work must not be called official GROMACS. Details are found
31  * in the README & COPYING files - if they are missing, get the
32  * official version at http://www.gromacs.org.
33  *
34  * To help us fund GROMACS development, we humbly ask that you cite
35  * the research papers on the package. Check out http://www.gromacs.org.
36  */
37 #include "gmxpre.h"
38
39 /* This file is completely threadsafe - keep it that way! */
40
41 #include "tpxio.h"
42
43 #include <cstdio>
44 #include <cstdlib>
45 #include <cstring>
46
47 #include <algorithm>
48 #include <vector>
49
50 #include "gromacs/compat/make_unique.h"
51 #include "gromacs/fileio/filetypes.h"
52 #include "gromacs/fileio/gmxfio.h"
53 #include "gromacs/fileio/gmxfio-xdr.h"
54 #include "gromacs/math/units.h"
55 #include "gromacs/math/vec.h"
56 #include "gromacs/mdtypes/awh-history.h"
57 #include "gromacs/mdtypes/awh-params.h"
58 #include "gromacs/mdtypes/inputrec.h"
59 #include "gromacs/mdtypes/md_enums.h"
60 #include "gromacs/mdtypes/pull-params.h"
61 #include "gromacs/mdtypes/state.h"
62 #include "gromacs/pbcutil/boxutilities.h"
63 #include "gromacs/pbcutil/pbc.h"
64 #include "gromacs/topology/block.h"
65 #include "gromacs/topology/ifunc.h"
66 #include "gromacs/topology/mtop_util.h"
67 #include "gromacs/topology/symtab.h"
68 #include "gromacs/topology/topology.h"
69 #include "gromacs/utility/arraysize.h"
70 #include "gromacs/utility/baseversion.h"
71 #include "gromacs/utility/cstringutil.h"
72 #include "gromacs/utility/fatalerror.h"
73 #include "gromacs/utility/futil.h"
74 #include "gromacs/utility/gmxassert.h"
75 #include "gromacs/utility/keyvaluetreebuilder.h"
76 #include "gromacs/utility/keyvaluetreeserializer.h"
77 #include "gromacs/utility/smalloc.h"
78 #include "gromacs/utility/snprintf.h"
79 #include "gromacs/utility/txtdump.h"
80
81 #define TPX_TAG_RELEASE  "release"
82
83 /*! \brief Tag string for the file format written to run input files
84  * written by this version of the code.
85  *
86  * Change this if you want to change the run input format in a feature
87  * branch. This ensures that there will not be different run input
88  * formats around which cannot be distinguished, while not causing
89  * problems rebasing the feature branch onto upstream changes. When
90  * merging with mainstream GROMACS, set this tag string back to
91  * TPX_TAG_RELEASE, and instead add an element to tpxv.
92  */
93 static const char *tpx_tag = TPX_TAG_RELEASE;
94
95 /*! \brief Enum of values that describe the contents of a tpr file
96  * whose format matches a version number
97  *
98  * The enum helps the code be more self-documenting and ensure merges
99  * do not silently resolve when two patches make the same bump. When
100  * adding new functionality, add a new element just above tpxv_Count
101  * in this enumeration, and write code below that does the right thing
102  * according to the value of file_version.
103  */
104 enum tpxv {
105     tpxv_ComputationalElectrophysiology = 96,                /**< support for ion/water position swaps (computational electrophysiology) */
106     tpxv_Use64BitRandomSeed,                                 /**< change ld_seed from int to int64_t */
107     tpxv_RestrictedBendingAndCombinedAngleTorsionPotentials, /**< potentials for supporting coarse-grained force fields */
108     tpxv_InteractiveMolecularDynamics,                       /**< interactive molecular dynamics (IMD) */
109     tpxv_RemoveObsoleteParameters1,                          /**< remove optimize_fft, dihre_fc, nstcheckpoint */
110     tpxv_PullCoordTypeGeom,                                  /**< add pull type and geometry per group and flat-bottom */
111     tpxv_PullGeomDirRel,                                     /**< add pull geometry direction-relative */
112     tpxv_IntermolecularBondeds,                              /**< permit inter-molecular bonded interactions in the topology */
113     tpxv_CompElWithSwapLayerOffset,                          /**< added parameters for improved CompEl setups */
114     tpxv_CompElPolyatomicIonsAndMultipleIonTypes,            /**< CompEl now can handle polyatomic ions and more than two types of ions */
115     tpxv_RemoveAdress,                                       /**< removed support for AdResS */
116     tpxv_PullCoordNGroup,                                    /**< add ngroup to pull coord */
117     tpxv_RemoveTwinRange,                                    /**< removed support for twin-range interactions */
118     tpxv_ReplacePullPrintCOM12,                              /**< Replaced print-com-1, 2 with pull-print-com */
119     tpxv_PullExternalPotential,                              /**< Added pull type external potential */
120     tpxv_GenericParamsForElectricField,                      /**< Introduced KeyValueTree and moved electric field parameters */
121     tpxv_AcceleratedWeightHistogram,                         /**< sampling with accelerated weight histogram method (AWH) */
122     tpxv_RemoveImplicitSolvation,                            /**< removed support for implicit solvation */
123     tpxv_PullPrevStepCOMAsReference,                         /**< Enabled using the COM of the pull group of the last frame as reference for PBC */
124     tpxv_Count                                               /**< the total number of tpxv versions */
125 };
126
127 /*! \brief Version number of the file format written to run input
128  * files by this version of the code.
129  *
130  * The tpx_version increases whenever the file format in the main
131  * development branch changes, due to an extension of the tpxv enum above.
132  * Backward compatibility for reading old run input files is maintained
133  * by checking this version number against that of the file and then using
134  * the correct code path.
135  *
136  * When developing a feature branch that needs to change the run input
137  * file format, change tpx_tag instead. */
138 static const int tpx_version = tpxv_Count - 1;
139
140
141 /* This number should only be increased when you edit the TOPOLOGY section
142  * or the HEADER of the tpx format.
143  * This way we can maintain forward compatibility too for all analysis tools
144  * and/or external programs that only need to know the atom/residue names,
145  * charges, and bond connectivity.
146  *
147  * It first appeared in tpx version 26, when I also moved the inputrecord
148  * to the end of the tpx file, so we can just skip it if we only
149  * want the topology.
150  *
151  * In particular, it must be increased when adding new elements to
152  * ftupd, so that old code can read new .tpr files.
153  */
154 static const int tpx_generation = 26;
155
156 /* This number should be the most recent backwards incompatible version
157  * I.e., if this number is 9, we cannot read tpx version 9 with this code.
158  */
159 static const int tpx_incompatible_version = 57; // GMX4.0 has version 58
160
161
162
163 /* Struct used to maintain tpx compatibility when function types are added */
164 typedef struct {
165     int fvnr;  /* file version number in which the function type first appeared */
166     int ftype; /* function type */
167 } t_ftupd;
168
169 /*
170  * TODO The following three lines make little sense, please clarify if
171  * you've had to work out how ftupd works.
172  *
173  * The entries should be ordered in:
174  * 1. ascending function type number
175  * 2. ascending file version number
176  *
177  * Because we support reading of old .tpr file versions (even when
178  * mdrun can no longer run the simulation), we need to be able to read
179  * obsolete t_interaction_function types. Any data read from such
180  * fields is discarded. Their names have _NOLONGERUSED appended to
181  * them to make things clear.
182  */
183 static const t_ftupd ftupd[] = {
184     { 70, F_RESTRBONDS        },
185     { tpxv_RestrictedBendingAndCombinedAngleTorsionPotentials, F_RESTRANGLES },
186     { 76, F_LINEAR_ANGLES     },
187     { tpxv_RestrictedBendingAndCombinedAngleTorsionPotentials, F_RESTRDIHS },
188     { tpxv_RestrictedBendingAndCombinedAngleTorsionPotentials, F_CBTDIHS },
189     { 65, F_CMAP              },
190     { 60, F_GB12_NOLONGERUSED },
191     { 61, F_GB13_NOLONGERUSED },
192     { 61, F_GB14_NOLONGERUSED },
193     { 72, F_GBPOL_NOLONGERUSED },
194     { 72, F_NPSOLVATION_NOLONGERUSED },
195     { 93, F_LJ_RECIP          },
196     { 90, F_FBPOSRES          },
197     { 69, F_VTEMP_NOLONGERUSED},
198     { 66, F_PDISPCORR         },
199     { 76, F_ANHARM_POL        },
200     { 79, F_DVDL_COUL         },
201     { 79, F_DVDL_VDW,         },
202     { 79, F_DVDL_BONDED,      },
203     { 79, F_DVDL_RESTRAINT    },
204     { 79, F_DVDL_TEMPERATURE  },
205 };
206 #define NFTUPD asize(ftupd)
207
208 /* Needed for backward compatibility */
209 #define MAXNODES 256
210
211 /**************************************************************
212  *
213  * Now the higer level routines that do io of the structures and arrays
214  *
215  **************************************************************/
216 static void do_pullgrp_tpx_pre95(t_fileio     *fio,
217                                  t_pull_group *pgrp,
218                                  t_pull_coord *pcrd,
219                                  gmx_bool      bRead)
220 {
221     rvec tmp;
222
223     gmx_fio_do_int(fio, pgrp->nat);
224     if (bRead)
225     {
226         snew(pgrp->ind, pgrp->nat);
227     }
228     gmx_fio_ndo_int(fio, pgrp->ind, pgrp->nat);
229     gmx_fio_do_int(fio, pgrp->nweight);
230     if (bRead)
231     {
232         snew(pgrp->weight, pgrp->nweight);
233     }
234     gmx_fio_ndo_real(fio, pgrp->weight, pgrp->nweight);
235     gmx_fio_do_int(fio, pgrp->pbcatom);
236     gmx_fio_do_rvec(fio, pcrd->vec);
237     clear_rvec(pcrd->origin);
238     gmx_fio_do_rvec(fio, tmp);
239     pcrd->init = tmp[0];
240     gmx_fio_do_real(fio, pcrd->rate);
241     gmx_fio_do_real(fio, pcrd->k);
242     gmx_fio_do_real(fio, pcrd->kB);
243 }
244
245 static void do_pull_group(t_fileio *fio, t_pull_group *pgrp, gmx_bool bRead)
246 {
247     gmx_fio_do_int(fio, pgrp->nat);
248     if (bRead)
249     {
250         snew(pgrp->ind, pgrp->nat);
251     }
252     gmx_fio_ndo_int(fio, pgrp->ind, pgrp->nat);
253     gmx_fio_do_int(fio, pgrp->nweight);
254     if (bRead)
255     {
256         snew(pgrp->weight, pgrp->nweight);
257     }
258     gmx_fio_ndo_real(fio, pgrp->weight, pgrp->nweight);
259     gmx_fio_do_int(fio, pgrp->pbcatom);
260 }
261
262 static void do_pull_coord(t_fileio *fio, t_pull_coord *pcrd,
263                           gmx_bool bRead, int file_version,
264                           int ePullOld, int eGeomOld, ivec dimOld)
265 {
266     if (file_version >= tpxv_PullCoordNGroup)
267     {
268         gmx_fio_do_int(fio,  pcrd->eType);
269         if (file_version >= tpxv_PullExternalPotential)
270         {
271             if (pcrd->eType == epullEXTERNAL)
272             {
273                 if (bRead)
274                 {
275                     char buf[STRLEN];
276
277                     gmx_fio_do_string(fio, buf);
278                     pcrd->externalPotentialProvider = gmx_strdup(buf);
279                 }
280                 else
281                 {
282                     gmx_fio_do_string(fio, pcrd->externalPotentialProvider);
283                 }
284             }
285             else
286             {
287                 pcrd->externalPotentialProvider = nullptr;
288             }
289         }
290         else
291         {
292             if (bRead)
293             {
294                 pcrd->externalPotentialProvider = nullptr;
295             }
296         }
297         /* Note that we try to support adding new geometries without
298          * changing the tpx version. This requires checks when printing the
299          * geometry string and a check and fatal_error in init_pull.
300          */
301         gmx_fio_do_int(fio,  pcrd->eGeom);
302         gmx_fio_do_int(fio,  pcrd->ngroup);
303         if (pcrd->ngroup <= c_pullCoordNgroupMax)
304         {
305             gmx_fio_ndo_int(fio, pcrd->group, pcrd->ngroup);
306         }
307         else
308         {
309             /* More groups in file than supported, this must be a new geometry
310              * that is not supported by our current code. Since we will not
311              * use the groups for this coord (checks in the pull and WHAM code
312              * ensure this), we can ignore the groups and set ngroup=0.
313              */
314             int *dum;
315             snew(dum, pcrd->ngroup);
316             gmx_fio_ndo_int(fio, dum, pcrd->ngroup);
317             sfree(dum);
318
319             pcrd->ngroup = 0;
320         }
321         gmx_fio_do_ivec(fio, pcrd->dim);
322     }
323     else
324     {
325         pcrd->ngroup = 2;
326         gmx_fio_do_int(fio, pcrd->group[0]);
327         gmx_fio_do_int(fio, pcrd->group[1]);
328         if (file_version >= tpxv_PullCoordTypeGeom)
329         {
330             pcrd->ngroup = (pcrd->eGeom == epullgDIRRELATIVE ? 4 : 2);
331             gmx_fio_do_int(fio,  pcrd->eType);
332             gmx_fio_do_int(fio,  pcrd->eGeom);
333             if (pcrd->ngroup == 4)
334             {
335                 gmx_fio_do_int(fio, pcrd->group[2]);
336                 gmx_fio_do_int(fio, pcrd->group[3]);
337             }
338             gmx_fio_do_ivec(fio, pcrd->dim);
339         }
340         else
341         {
342             pcrd->eType = ePullOld;
343             pcrd->eGeom = eGeomOld;
344             copy_ivec(dimOld, pcrd->dim);
345         }
346     }
347     gmx_fio_do_rvec(fio, pcrd->origin);
348     gmx_fio_do_rvec(fio, pcrd->vec);
349     if (file_version >= tpxv_PullCoordTypeGeom)
350     {
351         gmx_fio_do_gmx_bool(fio, pcrd->bStart);
352     }
353     else
354     {
355         /* This parameter is only printed, but not actually used by mdrun */
356         pcrd->bStart = FALSE;
357     }
358     gmx_fio_do_real(fio, pcrd->init);
359     gmx_fio_do_real(fio, pcrd->rate);
360     gmx_fio_do_real(fio, pcrd->k);
361     gmx_fio_do_real(fio, pcrd->kB);
362 }
363
364 static void do_expandedvals(t_fileio *fio, t_expanded *expand, t_lambda *fepvals, gmx_bool bRead, int file_version)
365 {
366     int      n_lambda = fepvals->n_lambda;
367
368     /* reset the lambda calculation window */
369     fepvals->lambda_start_n = 0;
370     fepvals->lambda_stop_n  = n_lambda;
371     if (file_version >= 79)
372     {
373         if (n_lambda > 0)
374         {
375             if (bRead)
376             {
377                 snew(expand->init_lambda_weights, n_lambda);
378             }
379             gmx_fio_ndo_real(fio, expand->init_lambda_weights, n_lambda);
380             gmx_fio_do_gmx_bool(fio, expand->bInit_weights);
381         }
382
383         gmx_fio_do_int(fio, expand->nstexpanded);
384         gmx_fio_do_int(fio, expand->elmcmove);
385         gmx_fio_do_int(fio, expand->elamstats);
386         gmx_fio_do_int(fio, expand->lmc_repeats);
387         gmx_fio_do_int(fio, expand->gibbsdeltalam);
388         gmx_fio_do_int(fio, expand->lmc_forced_nstart);
389         gmx_fio_do_int(fio, expand->lmc_seed);
390         gmx_fio_do_real(fio, expand->mc_temp);
391         gmx_fio_do_gmx_bool(fio, expand->bSymmetrizedTMatrix);
392         gmx_fio_do_int(fio, expand->nstTij);
393         gmx_fio_do_int(fio, expand->minvarmin);
394         gmx_fio_do_int(fio, expand->c_range);
395         gmx_fio_do_real(fio, expand->wl_scale);
396         gmx_fio_do_real(fio, expand->wl_ratio);
397         gmx_fio_do_real(fio, expand->init_wl_delta);
398         gmx_fio_do_gmx_bool(fio, expand->bWLoneovert);
399         gmx_fio_do_int(fio, expand->elmceq);
400         gmx_fio_do_int(fio, expand->equil_steps);
401         gmx_fio_do_int(fio, expand->equil_samples);
402         gmx_fio_do_int(fio, expand->equil_n_at_lam);
403         gmx_fio_do_real(fio, expand->equil_wl_delta);
404         gmx_fio_do_real(fio, expand->equil_ratio);
405     }
406 }
407
408 static void do_simtempvals(t_fileio *fio, t_simtemp *simtemp, int n_lambda, gmx_bool bRead,
409                            int file_version)
410 {
411     if (file_version >= 79)
412     {
413         gmx_fio_do_int(fio, simtemp->eSimTempScale);
414         gmx_fio_do_real(fio, simtemp->simtemp_high);
415         gmx_fio_do_real(fio, simtemp->simtemp_low);
416         if (n_lambda > 0)
417         {
418             if (bRead)
419             {
420                 snew(simtemp->temperatures, n_lambda);
421             }
422             gmx_fio_ndo_real(fio, simtemp->temperatures, n_lambda);
423         }
424     }
425 }
426
427 static void do_imd(t_fileio *fio, t_IMD *imd, gmx_bool bRead)
428 {
429     gmx_fio_do_int(fio, imd->nat);
430     if (bRead)
431     {
432         snew(imd->ind, imd->nat);
433     }
434     gmx_fio_ndo_int(fio, imd->ind, imd->nat);
435 }
436
437 static void do_fepvals(t_fileio *fio, t_lambda *fepvals, gmx_bool bRead, int file_version)
438 {
439     /* i is defined in the ndo_double macro; use g to iterate. */
440     int      g;
441     real     rdum;
442
443     /* free energy values */
444
445     if (file_version >= 79)
446     {
447         gmx_fio_do_int(fio, fepvals->init_fep_state);
448         gmx_fio_do_double(fio, fepvals->init_lambda);
449         gmx_fio_do_double(fio, fepvals->delta_lambda);
450     }
451     else if (file_version >= 59)
452     {
453         gmx_fio_do_double(fio, fepvals->init_lambda);
454         gmx_fio_do_double(fio, fepvals->delta_lambda);
455     }
456     else
457     {
458         gmx_fio_do_real(fio, rdum);
459         fepvals->init_lambda = rdum;
460         gmx_fio_do_real(fio, rdum);
461         fepvals->delta_lambda = rdum;
462     }
463     if (file_version >= 79)
464     {
465         gmx_fio_do_int(fio, fepvals->n_lambda);
466         if (bRead)
467         {
468             snew(fepvals->all_lambda, efptNR);
469         }
470         for (g = 0; g < efptNR; g++)
471         {
472             if (fepvals->n_lambda > 0)
473             {
474                 if (bRead)
475                 {
476                     snew(fepvals->all_lambda[g], fepvals->n_lambda);
477                 }
478                 gmx_fio_ndo_double(fio, fepvals->all_lambda[g], fepvals->n_lambda);
479                 gmx_fio_ndo_gmx_bool(fio, fepvals->separate_dvdl, efptNR);
480             }
481             else if (fepvals->init_lambda >= 0)
482             {
483                 fepvals->separate_dvdl[efptFEP] = TRUE;
484             }
485         }
486     }
487     else if (file_version >= 64)
488     {
489         gmx_fio_do_int(fio, fepvals->n_lambda);
490         if (bRead)
491         {
492             int g;
493
494             snew(fepvals->all_lambda, efptNR);
495             /* still allocate the all_lambda array's contents. */
496             for (g = 0; g < efptNR; g++)
497             {
498                 if (fepvals->n_lambda > 0)
499                 {
500                     snew(fepvals->all_lambda[g], fepvals->n_lambda);
501                 }
502             }
503         }
504         gmx_fio_ndo_double(fio, fepvals->all_lambda[efptFEP],
505                            fepvals->n_lambda);
506         if (fepvals->init_lambda >= 0)
507         {
508             int g, h;
509
510             fepvals->separate_dvdl[efptFEP] = TRUE;
511
512             if (bRead)
513             {
514                 /* copy the contents of the efptFEP lambda component to all
515                    the other components */
516                 for (g = 0; g < efptNR; g++)
517                 {
518                     for (h = 0; h < fepvals->n_lambda; h++)
519                     {
520                         if (g != efptFEP)
521                         {
522                             fepvals->all_lambda[g][h] =
523                                 fepvals->all_lambda[efptFEP][h];
524                         }
525                     }
526                 }
527             }
528         }
529     }
530     else
531     {
532         fepvals->n_lambda     = 0;
533         fepvals->all_lambda   = nullptr;
534         if (fepvals->init_lambda >= 0)
535         {
536             fepvals->separate_dvdl[efptFEP] = TRUE;
537         }
538     }
539     gmx_fio_do_real(fio, fepvals->sc_alpha);
540     gmx_fio_do_int(fio, fepvals->sc_power);
541     if (file_version >= 79)
542     {
543         gmx_fio_do_real(fio, fepvals->sc_r_power);
544     }
545     else
546     {
547         fepvals->sc_r_power = 6.0;
548     }
549     gmx_fio_do_real(fio, fepvals->sc_sigma);
550     if (bRead)
551     {
552         if (file_version >= 71)
553         {
554             fepvals->sc_sigma_min = fepvals->sc_sigma;
555         }
556         else
557         {
558             fepvals->sc_sigma_min = 0;
559         }
560     }
561     if (file_version >= 79)
562     {
563         gmx_fio_do_gmx_bool(fio, fepvals->bScCoul);
564     }
565     else
566     {
567         fepvals->bScCoul = TRUE;
568     }
569     if (file_version >= 64)
570     {
571         gmx_fio_do_int(fio, fepvals->nstdhdl);
572     }
573     else
574     {
575         fepvals->nstdhdl = 1;
576     }
577
578     if (file_version >= 73)
579     {
580         gmx_fio_do_int(fio, fepvals->separate_dhdl_file);
581         gmx_fio_do_int(fio, fepvals->dhdl_derivatives);
582     }
583     else
584     {
585         fepvals->separate_dhdl_file = esepdhdlfileYES;
586         fepvals->dhdl_derivatives   = edhdlderivativesYES;
587     }
588     if (file_version >= 71)
589     {
590         gmx_fio_do_int(fio, fepvals->dh_hist_size);
591         gmx_fio_do_double(fio, fepvals->dh_hist_spacing);
592     }
593     else
594     {
595         fepvals->dh_hist_size    = 0;
596         fepvals->dh_hist_spacing = 0.1;
597     }
598     if (file_version >= 79)
599     {
600         gmx_fio_do_int(fio, fepvals->edHdLPrintEnergy);
601     }
602     else
603     {
604         fepvals->edHdLPrintEnergy = edHdLPrintEnergyNO;
605     }
606
607     /* handle lambda_neighbors */
608     if ((file_version >= 83 && file_version < 90) || file_version >= 92)
609     {
610         gmx_fio_do_int(fio, fepvals->lambda_neighbors);
611         if ( (fepvals->lambda_neighbors >= 0) && (fepvals->init_fep_state >= 0) &&
612              (fepvals->init_lambda < 0) )
613         {
614             fepvals->lambda_start_n = (fepvals->init_fep_state -
615                                        fepvals->lambda_neighbors);
616             fepvals->lambda_stop_n = (fepvals->init_fep_state +
617                                       fepvals->lambda_neighbors + 1);
618             if (fepvals->lambda_start_n < 0)
619             {
620                 fepvals->lambda_start_n = 0;;
621             }
622             if (fepvals->lambda_stop_n >= fepvals->n_lambda)
623             {
624                 fepvals->lambda_stop_n = fepvals->n_lambda;
625             }
626         }
627         else
628         {
629             fepvals->lambda_start_n = 0;
630             fepvals->lambda_stop_n  = fepvals->n_lambda;
631         }
632     }
633     else
634     {
635         fepvals->lambda_start_n = 0;
636         fepvals->lambda_stop_n  = fepvals->n_lambda;
637     }
638 }
639
640 static void do_awhBias(t_fileio *fio, gmx::AwhBiasParams *awhBiasParams, gmx_bool bRead,
641                        int gmx_unused file_version)
642 {
643     gmx_fio_do_int(fio, awhBiasParams->eTarget);
644     gmx_fio_do_double(fio, awhBiasParams->targetBetaScaling);
645     gmx_fio_do_double(fio, awhBiasParams->targetCutoff);
646     gmx_fio_do_int(fio, awhBiasParams->eGrowth);
647     gmx_fio_do_int(fio, awhBiasParams->bUserData);
648     gmx_fio_do_double(fio, awhBiasParams->errorInitial);
649     gmx_fio_do_int(fio, awhBiasParams->ndim);
650     gmx_fio_do_int(fio, awhBiasParams->shareGroup);
651     gmx_fio_do_gmx_bool(fio, awhBiasParams->equilibrateHistogram);
652
653     if (bRead)
654     {
655         snew(awhBiasParams->dimParams, awhBiasParams->ndim);
656     }
657
658     for (int d = 0; d < awhBiasParams->ndim; d++)
659     {
660         gmx::AwhDimParams *dimParams = &awhBiasParams->dimParams[d];
661
662         gmx_fio_do_int(fio, dimParams->eCoordProvider);
663         gmx_fio_do_int(fio, dimParams->coordIndex);
664         gmx_fio_do_double(fio, dimParams->origin);
665         gmx_fio_do_double(fio, dimParams->end);
666         gmx_fio_do_double(fio, dimParams->period);
667         gmx_fio_do_double(fio, dimParams->forceConstant);
668         gmx_fio_do_double(fio, dimParams->diffusion);
669         gmx_fio_do_double(fio, dimParams->coordValueInit);
670         gmx_fio_do_double(fio, dimParams->coverDiameter);
671     }
672 }
673
674 static void do_awh(t_fileio *fio, gmx::AwhParams *awhParams, gmx_bool bRead,
675                    int gmx_unused file_version)
676 {
677     gmx_fio_do_int(fio, awhParams->numBias);
678     gmx_fio_do_int(fio, awhParams->nstOut);
679     gmx_fio_do_int64(fio, awhParams->seed);
680     gmx_fio_do_int(fio, awhParams->nstSampleCoord);
681     gmx_fio_do_int(fio, awhParams->numSamplesUpdateFreeEnergy);
682     gmx_fio_do_int(fio, awhParams->ePotential);
683     gmx_fio_do_gmx_bool(fio, awhParams->shareBiasMultisim);
684
685     if (awhParams->numBias > 0)
686     {
687         if (bRead)
688         {
689             snew(awhParams->awhBiasParams, awhParams->numBias);
690         }
691
692         for (int k = 0; k < awhParams->numBias; k++)
693         {
694             do_awhBias(fio, &awhParams->awhBiasParams[k], bRead, file_version);
695         }
696     }
697 }
698
699 static void do_pull(t_fileio *fio, pull_params_t *pull, gmx_bool bRead,
700                     int file_version, int ePullOld)
701 {
702     int  eGeomOld = -1;
703     ivec dimOld;
704     int  g;
705
706     if (file_version >= 95)
707     {
708         gmx_fio_do_int(fio, pull->ngroup);
709     }
710     gmx_fio_do_int(fio, pull->ncoord);
711     if (file_version < 95)
712     {
713         pull->ngroup = pull->ncoord + 1;
714     }
715     if (file_version < tpxv_PullCoordTypeGeom)
716     {
717         real dum;
718
719         gmx_fio_do_int(fio, eGeomOld);
720         gmx_fio_do_ivec(fio, dimOld);
721         /* The inner cylinder radius, now removed */
722         gmx_fio_do_real(fio, dum);
723     }
724     gmx_fio_do_real(fio, pull->cylinder_r);
725     gmx_fio_do_real(fio, pull->constr_tol);
726     if (file_version >= 95)
727     {
728         gmx_fio_do_gmx_bool(fio, pull->bPrintCOM);
729         /* With file_version < 95 this value is set below */
730     }
731     if (file_version >= tpxv_ReplacePullPrintCOM12)
732     {
733         gmx_fio_do_gmx_bool(fio, pull->bPrintRefValue);
734         gmx_fio_do_gmx_bool(fio, pull->bPrintComp);
735     }
736     else if (file_version >= tpxv_PullCoordTypeGeom)
737     {
738         int idum;
739         gmx_fio_do_int(fio, idum); /* used to be bPrintCOM2 */
740         gmx_fio_do_gmx_bool(fio, pull->bPrintRefValue);
741         gmx_fio_do_gmx_bool(fio, pull->bPrintComp);
742     }
743     else
744     {
745         pull->bPrintRefValue = FALSE;
746         pull->bPrintComp     = TRUE;
747     }
748     gmx_fio_do_int(fio, pull->nstxout);
749     gmx_fio_do_int(fio, pull->nstfout);
750     if (file_version >= tpxv_PullPrevStepCOMAsReference)
751     {
752         gmx_fio_do_gmx_bool(fio, pull->bSetPbcRefToPrevStepCOM);
753     }
754     else
755     {
756         pull->bSetPbcRefToPrevStepCOM = FALSE;
757     }
758     if (bRead)
759     {
760         snew(pull->group, pull->ngroup);
761         snew(pull->coord, pull->ncoord);
762     }
763     if (file_version < 95)
764     {
765         /* epullgPOS for position pulling, before epullgDIRPBC was removed */
766         if (eGeomOld == epullgDIRPBC)
767         {
768             gmx_fatal(FARGS, "pull-geometry=position is no longer supported");
769         }
770         if (eGeomOld > epullgDIRPBC)
771         {
772             eGeomOld -= 1;
773         }
774
775         for (g = 0; g < pull->ngroup; g++)
776         {
777             /* We read and ignore a pull coordinate for group 0 */
778             do_pullgrp_tpx_pre95(fio, &pull->group[g], &pull->coord[std::max(g-1, 0)],
779                                  bRead);
780             if (g > 0)
781             {
782                 pull->coord[g-1].group[0] = 0;
783                 pull->coord[g-1].group[1] = g;
784             }
785         }
786
787         pull->bPrintCOM = (pull->group[0].nat > 0);
788     }
789     else
790     {
791         for (g = 0; g < pull->ngroup; g++)
792         {
793             do_pull_group(fio, &pull->group[g], bRead);
794         }
795         for (g = 0; g < pull->ncoord; g++)
796         {
797             do_pull_coord(fio, &pull->coord[g],
798                           bRead, file_version, ePullOld, eGeomOld, dimOld);
799         }
800     }
801 }
802
803
804 static void do_rotgrp(t_fileio *fio, t_rotgrp *rotg, gmx_bool bRead)
805 {
806     gmx_fio_do_int(fio, rotg->eType);
807     gmx_fio_do_int(fio, rotg->bMassW);
808     gmx_fio_do_int(fio, rotg->nat);
809     if (bRead)
810     {
811         snew(rotg->ind, rotg->nat);
812     }
813     gmx_fio_ndo_int(fio, rotg->ind, rotg->nat);
814     if (bRead)
815     {
816         snew(rotg->x_ref, rotg->nat);
817     }
818     gmx_fio_ndo_rvec(fio, rotg->x_ref, rotg->nat);
819     gmx_fio_do_rvec(fio, rotg->inputVec);
820     gmx_fio_do_rvec(fio, rotg->pivot);
821     gmx_fio_do_real(fio, rotg->rate);
822     gmx_fio_do_real(fio, rotg->k);
823     gmx_fio_do_real(fio, rotg->slab_dist);
824     gmx_fio_do_real(fio, rotg->min_gaussian);
825     gmx_fio_do_real(fio, rotg->eps);
826     gmx_fio_do_int(fio, rotg->eFittype);
827     gmx_fio_do_int(fio, rotg->PotAngle_nstep);
828     gmx_fio_do_real(fio, rotg->PotAngle_step);
829 }
830
831 static void do_rot(t_fileio *fio, t_rot *rot, gmx_bool bRead)
832 {
833     int g;
834
835     gmx_fio_do_int(fio, rot->ngrp);
836     gmx_fio_do_int(fio, rot->nstrout);
837     gmx_fio_do_int(fio, rot->nstsout);
838     if (bRead)
839     {
840         snew(rot->grp, rot->ngrp);
841     }
842     for (g = 0; g < rot->ngrp; g++)
843     {
844         do_rotgrp(fio, &rot->grp[g], bRead);
845     }
846 }
847
848
849 static void do_swapgroup(t_fileio *fio, t_swapGroup *g, gmx_bool bRead)
850 {
851
852     /* Name of the group or molecule */
853     if (bRead)
854     {
855         char buf[STRLEN];
856
857         gmx_fio_do_string(fio, buf);
858         g->molname = gmx_strdup(buf);
859     }
860     else
861     {
862         gmx_fio_do_string(fio, g->molname);
863     }
864
865     /* Number of atoms in the group */
866     gmx_fio_do_int(fio, g->nat);
867
868     /* The group's atom indices */
869     if (bRead)
870     {
871         snew(g->ind, g->nat);
872     }
873     gmx_fio_ndo_int(fio, g->ind, g->nat);
874
875     /* Requested counts for compartments A and B */
876     gmx_fio_ndo_int(fio, g->nmolReq, eCompNR);
877 }
878
879 static void do_swapcoords_tpx(t_fileio *fio, t_swapcoords *swap, gmx_bool bRead, int file_version)
880 {
881     /* Enums for better readability of the code */
882     enum {
883         eCompA = 0, eCompB
884     };
885     enum {
886         eChannel0 = 0, eChannel1
887     };
888
889
890     if (file_version >= tpxv_CompElPolyatomicIonsAndMultipleIonTypes)
891     {
892         /* The total number of swap groups is the sum of the fixed groups
893          * (split0, split1, solvent), and the user-defined groups (2+ types of ions)
894          */
895         gmx_fio_do_int(fio, swap->ngrp);
896         if (bRead)
897         {
898             snew(swap->grp, swap->ngrp);
899         }
900         for (int ig = 0; ig < swap->ngrp; ig++)
901         {
902             do_swapgroup(fio, &swap->grp[ig], bRead);
903         }
904         gmx_fio_do_gmx_bool(fio, swap->massw_split[eChannel0]);
905         gmx_fio_do_gmx_bool(fio, swap->massw_split[eChannel1]);
906         gmx_fio_do_int(fio, swap->nstswap);
907         gmx_fio_do_int(fio, swap->nAverage);
908         gmx_fio_do_real(fio, swap->threshold);
909         gmx_fio_do_real(fio, swap->cyl0r);
910         gmx_fio_do_real(fio, swap->cyl0u);
911         gmx_fio_do_real(fio, swap->cyl0l);
912         gmx_fio_do_real(fio, swap->cyl1r);
913         gmx_fio_do_real(fio, swap->cyl1u);
914         gmx_fio_do_real(fio, swap->cyl1l);
915     }
916     else
917     {
918         /*** Support reading older CompEl .tpr files ***/
919
920         /* In the original CompEl .tpr files, we always have 5 groups: */
921         swap->ngrp = 5;
922         snew(swap->grp, swap->ngrp);
923
924         swap->grp[eGrpSplit0 ].molname = gmx_strdup("split0" );  // group 0: split0
925         swap->grp[eGrpSplit1 ].molname = gmx_strdup("split1" );  // group 1: split1
926         swap->grp[eGrpSolvent].molname = gmx_strdup("solvent");  // group 2: solvent
927         swap->grp[3          ].molname = gmx_strdup("anions" );  // group 3: anions
928         swap->grp[4          ].molname = gmx_strdup("cations");  // group 4: cations
929
930         gmx_fio_do_int(fio, swap->grp[3].nat);
931         gmx_fio_do_int(fio, swap->grp[eGrpSolvent].nat);
932         gmx_fio_do_int(fio, swap->grp[eGrpSplit0].nat);
933         gmx_fio_do_gmx_bool(fio, swap->massw_split[eChannel0]);
934         gmx_fio_do_int(fio, swap->grp[eGrpSplit1].nat);
935         gmx_fio_do_gmx_bool(fio, swap->massw_split[eChannel1]);
936         gmx_fio_do_int(fio, swap->nstswap);
937         gmx_fio_do_int(fio, swap->nAverage);
938         gmx_fio_do_real(fio, swap->threshold);
939         gmx_fio_do_real(fio, swap->cyl0r);
940         gmx_fio_do_real(fio, swap->cyl0u);
941         gmx_fio_do_real(fio, swap->cyl0l);
942         gmx_fio_do_real(fio, swap->cyl1r);
943         gmx_fio_do_real(fio, swap->cyl1u);
944         gmx_fio_do_real(fio, swap->cyl1l);
945
946         // The order[] array keeps compatibility with older .tpr files
947         // by reading in the groups in the classic order
948         {
949             const int order[4] = {3, eGrpSolvent, eGrpSplit0, eGrpSplit1 };
950
951             for (int ig = 0; ig < 4; ig++)
952             {
953                 int g = order[ig];
954                 snew(swap->grp[g].ind, swap->grp[g].nat);
955                 gmx_fio_ndo_int(fio, swap->grp[g].ind, swap->grp[g].nat);
956             }
957         }
958
959         for (int j = eCompA; j <= eCompB; j++)
960         {
961             gmx_fio_do_int(fio, swap->grp[3].nmolReq[j]); // group 3 = anions
962             gmx_fio_do_int(fio, swap->grp[4].nmolReq[j]); // group 4 = cations
963         }
964     }                                                     /* End support reading older CompEl .tpr files */
965
966     if (file_version >= tpxv_CompElWithSwapLayerOffset)
967     {
968         gmx_fio_do_real(fio, swap->bulkOffset[eCompA]);
969         gmx_fio_do_real(fio, swap->bulkOffset[eCompB]);
970     }
971
972 }
973
974 static void do_legacy_efield(t_fileio *fio, gmx::KeyValueTreeObjectBuilder *root)
975 {
976     const char *const dimName[] = { "x", "y", "z" };
977
978     auto              appliedForcesObj = root->addObject("applied-forces");
979     auto              efieldObj        = appliedForcesObj.addObject("electric-field");
980     // The content of the tpr file for this feature has
981     // been the same since gromacs 4.0 that was used for
982     // developing.
983     for (int j = 0; j < DIM; ++j)
984     {
985         int n, nt;
986         gmx_fio_do_int(fio, n);
987         gmx_fio_do_int(fio, nt);
988         std::vector<real> aa(n+1), phi(nt+1), at(nt+1), phit(nt+1);
989         gmx_fio_ndo_real(fio, aa.data(),  n);
990         gmx_fio_ndo_real(fio, phi.data(), n);
991         gmx_fio_ndo_real(fio, at.data(),  nt);
992         gmx_fio_ndo_real(fio, phit.data(), nt);
993         if (n > 0)
994         {
995             if (n > 1 || nt > 1)
996             {
997                 gmx_fatal(FARGS, "Can not handle tpr files with more than one electric field term per direction.");
998             }
999             auto dimObj = efieldObj.addObject(dimName[j]);
1000             dimObj.addValue<real>("E0", aa[0]);
1001             dimObj.addValue<real>("omega", at[0]);
1002             dimObj.addValue<real>("t0", phi[0]);
1003             dimObj.addValue<real>("sigma", phit[0]);
1004         }
1005     }
1006 }
1007
1008
1009 static void do_inputrec(t_fileio *fio, t_inputrec *ir, gmx_bool bRead,
1010                         int file_version)
1011 {
1012     int      i, j, k, idum = 0;
1013     real     rdum;
1014     gmx_bool bdum = false;
1015
1016     if (file_version != tpx_version)
1017     {
1018         /* Give a warning about features that are not accessible */
1019         fprintf(stderr, "Note: file tpx version %d, software tpx version %d\n",
1020                 file_version, tpx_version);
1021     }
1022
1023     if (file_version == 0)
1024     {
1025         return;
1026     }
1027
1028     gmx::KeyValueTreeBuilder       paramsBuilder;
1029     gmx::KeyValueTreeObjectBuilder paramsObj = paramsBuilder.rootObject();
1030
1031     /* Basic inputrec stuff */
1032     gmx_fio_do_int(fio, ir->eI);
1033     if (file_version >= 62)
1034     {
1035         gmx_fio_do_int64(fio, ir->nsteps);
1036     }
1037     else
1038     {
1039         gmx_fio_do_int(fio, idum);
1040         ir->nsteps = idum;
1041     }
1042
1043     if (file_version >= 62)
1044     {
1045         gmx_fio_do_int64(fio, ir->init_step);
1046     }
1047     else
1048     {
1049         gmx_fio_do_int(fio, idum);
1050         ir->init_step = idum;
1051     }
1052
1053     gmx_fio_do_int(fio, ir->simulation_part);
1054
1055     if (file_version >= 67)
1056     {
1057         gmx_fio_do_int(fio, ir->nstcalcenergy);
1058     }
1059     else
1060     {
1061         ir->nstcalcenergy = 1;
1062     }
1063     if (file_version >= 81)
1064     {
1065         gmx_fio_do_int(fio, ir->cutoff_scheme);
1066         if (file_version < 94)
1067         {
1068             ir->cutoff_scheme = 1 - ir->cutoff_scheme;
1069         }
1070     }
1071     else
1072     {
1073         ir->cutoff_scheme = ecutsGROUP;
1074     }
1075     gmx_fio_do_int(fio, ir->ns_type);
1076     gmx_fio_do_int(fio, ir->nstlist);
1077     gmx_fio_do_int(fio, idum); /* used to be ndelta; not used anymore */
1078
1079     gmx_fio_do_real(fio, ir->rtpi);
1080
1081     gmx_fio_do_int(fio, ir->nstcomm);
1082     gmx_fio_do_int(fio, ir->comm_mode);
1083
1084     /* ignore nstcheckpoint */
1085     if (file_version < tpxv_RemoveObsoleteParameters1)
1086     {
1087         gmx_fio_do_int(fio, idum);
1088     }
1089
1090     gmx_fio_do_int(fio, ir->nstcgsteep);
1091
1092     gmx_fio_do_int(fio, ir->nbfgscorr);
1093
1094     gmx_fio_do_int(fio, ir->nstlog);
1095     gmx_fio_do_int(fio, ir->nstxout);
1096     gmx_fio_do_int(fio, ir->nstvout);
1097     gmx_fio_do_int(fio, ir->nstfout);
1098     gmx_fio_do_int(fio, ir->nstenergy);
1099     gmx_fio_do_int(fio, ir->nstxout_compressed);
1100     if (file_version >= 59)
1101     {
1102         gmx_fio_do_double(fio, ir->init_t);
1103         gmx_fio_do_double(fio, ir->delta_t);
1104     }
1105     else
1106     {
1107         gmx_fio_do_real(fio, rdum);
1108         ir->init_t = rdum;
1109         gmx_fio_do_real(fio, rdum);
1110         ir->delta_t = rdum;
1111     }
1112     gmx_fio_do_real(fio, ir->x_compression_precision);
1113     if (file_version >= 81)
1114     {
1115         gmx_fio_do_real(fio, ir->verletbuf_tol);
1116     }
1117     else
1118     {
1119         ir->verletbuf_tol = 0;
1120     }
1121     gmx_fio_do_real(fio, ir->rlist);
1122     if (file_version >= 67 && file_version < tpxv_RemoveTwinRange)
1123     {
1124         if (bRead)
1125         {
1126             // Reading such a file version could invoke the twin-range
1127             // scheme, about which mdrun should give a fatal error.
1128             real dummy_rlistlong = -1;
1129             gmx_fio_do_real(fio, dummy_rlistlong);
1130
1131             if (ir->rlist > 0 && (dummy_rlistlong == 0 || dummy_rlistlong > ir->rlist))
1132             {
1133                 // Get mdrun to issue an error (regardless of
1134                 // ir->cutoff_scheme).
1135                 ir->useTwinRange = true;
1136             }
1137             else
1138             {
1139                 // grompp used to set rlistlong actively. Users were
1140                 // probably also confused and set rlistlong == rlist.
1141                 // However, in all remaining cases, it is safe to let
1142                 // mdrun proceed normally.
1143                 ir->useTwinRange = false;
1144             }
1145         }
1146     }
1147     else
1148     {
1149         // No need to read or write anything
1150         ir->useTwinRange = false;
1151     }
1152     if (file_version >= 82 && file_version != 90)
1153     {
1154         // Multiple time-stepping is no longer enabled, but the old
1155         // support required the twin-range scheme, for which mdrun
1156         // already emits a fatal error.
1157         int dummy_nstcalclr = -1;
1158         gmx_fio_do_int(fio, dummy_nstcalclr);
1159     }
1160     gmx_fio_do_int(fio, ir->coulombtype);
1161     if (file_version >= 81)
1162     {
1163         gmx_fio_do_int(fio, ir->coulomb_modifier);
1164     }
1165     else
1166     {
1167         ir->coulomb_modifier = (ir->cutoff_scheme == ecutsVERLET ? eintmodPOTSHIFT : eintmodNONE);
1168     }
1169     gmx_fio_do_real(fio, ir->rcoulomb_switch);
1170     gmx_fio_do_real(fio, ir->rcoulomb);
1171     gmx_fio_do_int(fio, ir->vdwtype);
1172     if (file_version >= 81)
1173     {
1174         gmx_fio_do_int(fio, ir->vdw_modifier);
1175     }
1176     else
1177     {
1178         ir->vdw_modifier = (ir->cutoff_scheme == ecutsVERLET ? eintmodPOTSHIFT : eintmodNONE);
1179     }
1180     gmx_fio_do_real(fio, ir->rvdw_switch);
1181     gmx_fio_do_real(fio, ir->rvdw);
1182     gmx_fio_do_int(fio, ir->eDispCorr);
1183     gmx_fio_do_real(fio, ir->epsilon_r);
1184     gmx_fio_do_real(fio, ir->epsilon_rf);
1185     gmx_fio_do_real(fio, ir->tabext);
1186
1187     // This permits reading a .tpr file that used implicit solvent,
1188     // and later permitting mdrun to refuse to run it.
1189     if (bRead)
1190     {
1191         if (file_version < tpxv_RemoveImplicitSolvation)
1192         {
1193             gmx_fio_do_int(fio, idum);
1194             gmx_fio_do_int(fio, idum);
1195             gmx_fio_do_real(fio, rdum);
1196             gmx_fio_do_real(fio, rdum);
1197             gmx_fio_do_int(fio, idum);
1198             ir->implicit_solvent = (idum > 0);
1199         }
1200         else
1201         {
1202             ir->implicit_solvent = false;
1203         }
1204         if (file_version < tpxv_RemoveImplicitSolvation)
1205         {
1206             gmx_fio_do_real(fio, rdum);
1207             gmx_fio_do_real(fio, rdum);
1208             gmx_fio_do_real(fio, rdum);
1209             gmx_fio_do_real(fio, rdum);
1210             if (file_version >= 60)
1211             {
1212                 gmx_fio_do_real(fio, rdum);
1213                 gmx_fio_do_int(fio, idum);
1214             }
1215             gmx_fio_do_real(fio, rdum);
1216         }
1217     }
1218
1219     if (file_version >= 81)
1220     {
1221         gmx_fio_do_real(fio, ir->fourier_spacing);
1222     }
1223     else
1224     {
1225         ir->fourier_spacing = 0.0;
1226     }
1227     gmx_fio_do_int(fio, ir->nkx);
1228     gmx_fio_do_int(fio, ir->nky);
1229     gmx_fio_do_int(fio, ir->nkz);
1230     gmx_fio_do_int(fio, ir->pme_order);
1231     gmx_fio_do_real(fio, ir->ewald_rtol);
1232
1233     if (file_version >= 93)
1234     {
1235         gmx_fio_do_real(fio, ir->ewald_rtol_lj);
1236     }
1237     else
1238     {
1239         ir->ewald_rtol_lj = ir->ewald_rtol;
1240     }
1241     gmx_fio_do_int(fio, ir->ewald_geometry);
1242     gmx_fio_do_real(fio, ir->epsilon_surface);
1243
1244     /* ignore bOptFFT */
1245     if (file_version < tpxv_RemoveObsoleteParameters1)
1246     {
1247         gmx_fio_do_gmx_bool(fio, bdum);
1248     }
1249
1250     if (file_version >= 93)
1251     {
1252         gmx_fio_do_int(fio, ir->ljpme_combination_rule);
1253     }
1254     gmx_fio_do_gmx_bool(fio, ir->bContinuation);
1255     gmx_fio_do_int(fio, ir->etc);
1256     /* before version 18, ir->etc was a gmx_bool (ir->btc),
1257      * but the values 0 and 1 still mean no and
1258      * berendsen temperature coupling, respectively.
1259      */
1260     if (file_version >= 79)
1261     {
1262         gmx_fio_do_gmx_bool(fio, ir->bPrintNHChains);
1263     }
1264     if (file_version >= 71)
1265     {
1266         gmx_fio_do_int(fio, ir->nsttcouple);
1267     }
1268     else
1269     {
1270         ir->nsttcouple = ir->nstcalcenergy;
1271     }
1272     gmx_fio_do_int(fio, ir->epc);
1273     gmx_fio_do_int(fio, ir->epct);
1274     if (file_version >= 71)
1275     {
1276         gmx_fio_do_int(fio, ir->nstpcouple);
1277     }
1278     else
1279     {
1280         ir->nstpcouple = ir->nstcalcenergy;
1281     }
1282     gmx_fio_do_real(fio, ir->tau_p);
1283     gmx_fio_do_rvec(fio, ir->ref_p[XX]);
1284     gmx_fio_do_rvec(fio, ir->ref_p[YY]);
1285     gmx_fio_do_rvec(fio, ir->ref_p[ZZ]);
1286     gmx_fio_do_rvec(fio, ir->compress[XX]);
1287     gmx_fio_do_rvec(fio, ir->compress[YY]);
1288     gmx_fio_do_rvec(fio, ir->compress[ZZ]);
1289     gmx_fio_do_int(fio, ir->refcoord_scaling);
1290     gmx_fio_do_rvec(fio, ir->posres_com);
1291     gmx_fio_do_rvec(fio, ir->posres_comB);
1292
1293     if (file_version < 79)
1294     {
1295         gmx_fio_do_int(fio, ir->andersen_seed);
1296     }
1297     else
1298     {
1299         ir->andersen_seed = 0;
1300     }
1301
1302     gmx_fio_do_real(fio, ir->shake_tol);
1303
1304     gmx_fio_do_int(fio, ir->efep);
1305     do_fepvals(fio, ir->fepvals, bRead, file_version);
1306
1307     if (file_version >= 79)
1308     {
1309         gmx_fio_do_gmx_bool(fio, ir->bSimTemp);
1310         if (ir->bSimTemp)
1311         {
1312             ir->bSimTemp = TRUE;
1313         }
1314     }
1315     else
1316     {
1317         ir->bSimTemp = FALSE;
1318     }
1319     if (ir->bSimTemp)
1320     {
1321         do_simtempvals(fio, ir->simtempvals, ir->fepvals->n_lambda, bRead, file_version);
1322     }
1323
1324     if (file_version >= 79)
1325     {
1326         gmx_fio_do_gmx_bool(fio, ir->bExpanded);
1327         if (ir->bExpanded)
1328         {
1329             ir->bExpanded = TRUE;
1330         }
1331         else
1332         {
1333             ir->bExpanded = FALSE;
1334         }
1335     }
1336     if (ir->bExpanded)
1337     {
1338         do_expandedvals(fio, ir->expandedvals, ir->fepvals, bRead, file_version);
1339     }
1340
1341     gmx_fio_do_int(fio, ir->eDisre);
1342     gmx_fio_do_int(fio, ir->eDisreWeighting);
1343     gmx_fio_do_gmx_bool(fio, ir->bDisreMixed);
1344     gmx_fio_do_real(fio, ir->dr_fc);
1345     gmx_fio_do_real(fio, ir->dr_tau);
1346     gmx_fio_do_int(fio, ir->nstdisreout);
1347     gmx_fio_do_real(fio, ir->orires_fc);
1348     gmx_fio_do_real(fio, ir->orires_tau);
1349     gmx_fio_do_int(fio, ir->nstorireout);
1350
1351     /* ignore dihre_fc */
1352     if (file_version < 79)
1353     {
1354         gmx_fio_do_real(fio, rdum);
1355     }
1356
1357     gmx_fio_do_real(fio, ir->em_stepsize);
1358     gmx_fio_do_real(fio, ir->em_tol);
1359     gmx_fio_do_gmx_bool(fio, ir->bShakeSOR);
1360     gmx_fio_do_int(fio, ir->niter);
1361     gmx_fio_do_real(fio, ir->fc_stepsize);
1362     gmx_fio_do_int(fio, ir->eConstrAlg);
1363     gmx_fio_do_int(fio, ir->nProjOrder);
1364     gmx_fio_do_real(fio, ir->LincsWarnAngle);
1365     gmx_fio_do_int(fio, ir->nLincsIter);
1366     gmx_fio_do_real(fio, ir->bd_fric);
1367     if (file_version >= tpxv_Use64BitRandomSeed)
1368     {
1369         gmx_fio_do_int64(fio, ir->ld_seed);
1370     }
1371     else
1372     {
1373         gmx_fio_do_int(fio, idum);
1374         ir->ld_seed = idum;
1375     }
1376
1377     for (i = 0; i < DIM; i++)
1378     {
1379         gmx_fio_do_rvec(fio, ir->deform[i]);
1380     }
1381     gmx_fio_do_real(fio, ir->cos_accel);
1382
1383     gmx_fio_do_int(fio, ir->userint1);
1384     gmx_fio_do_int(fio, ir->userint2);
1385     gmx_fio_do_int(fio, ir->userint3);
1386     gmx_fio_do_int(fio, ir->userint4);
1387     gmx_fio_do_real(fio, ir->userreal1);
1388     gmx_fio_do_real(fio, ir->userreal2);
1389     gmx_fio_do_real(fio, ir->userreal3);
1390     gmx_fio_do_real(fio, ir->userreal4);
1391
1392     /* AdResS is removed, but we need to be able to read old files,
1393        and let mdrun refuse to run them */
1394     if (file_version >= 77 && file_version < tpxv_RemoveAdress)
1395     {
1396         gmx_fio_do_gmx_bool(fio, ir->bAdress);
1397         if (ir->bAdress)
1398         {
1399             int  idum, numThermoForceGroups, numEnergyGroups;
1400             real rdum;
1401             rvec rvecdum;
1402             gmx_fio_do_int(fio, idum);
1403             gmx_fio_do_real(fio, rdum);
1404             gmx_fio_do_real(fio, rdum);
1405             gmx_fio_do_real(fio, rdum);
1406             gmx_fio_do_int(fio, idum);
1407             gmx_fio_do_int(fio, idum);
1408             gmx_fio_do_rvec(fio, rvecdum);
1409             gmx_fio_do_int(fio, numThermoForceGroups);
1410             gmx_fio_do_real(fio, rdum);
1411             gmx_fio_do_int(fio, numEnergyGroups);
1412             gmx_fio_do_int(fio, idum);
1413
1414             if (numThermoForceGroups > 0)
1415             {
1416                 std::vector<int> idumn(numThermoForceGroups);
1417                 gmx_fio_ndo_int(fio, idumn.data(), idumn.size());
1418             }
1419             if (numEnergyGroups > 0)
1420             {
1421                 std::vector<int> idumn(numEnergyGroups);
1422                 gmx_fio_ndo_int(fio, idumn.data(), idumn.size());
1423             }
1424         }
1425     }
1426     else
1427     {
1428         ir->bAdress = FALSE;
1429     }
1430
1431     /* pull stuff */
1432     {
1433         int ePullOld = 0;
1434
1435         if (file_version >= tpxv_PullCoordTypeGeom)
1436         {
1437             gmx_fio_do_gmx_bool(fio, ir->bPull);
1438         }
1439         else
1440         {
1441             gmx_fio_do_int(fio, ePullOld);
1442             ir->bPull = (ePullOld > 0);
1443             /* We removed the first ePull=ePullNo for the enum */
1444             ePullOld -= 1;
1445         }
1446         if (ir->bPull)
1447         {
1448             if (bRead)
1449             {
1450                 snew(ir->pull, 1);
1451             }
1452             do_pull(fio, ir->pull, bRead, file_version, ePullOld);
1453         }
1454     }
1455
1456     if (file_version >= tpxv_AcceleratedWeightHistogram)
1457     {
1458         gmx_fio_do_gmx_bool(fio, ir->bDoAwh);
1459
1460         if (ir->bDoAwh)
1461         {
1462             if (bRead)
1463             {
1464                 snew(ir->awhParams, 1);
1465             }
1466             do_awh(fio, ir->awhParams, bRead, file_version);
1467         }
1468     }
1469     else
1470     {
1471         ir->bDoAwh = FALSE;
1472     }
1473
1474     /* Enforced rotation */
1475     if (file_version >= 74)
1476     {
1477         gmx_fio_do_gmx_bool(fio, ir->bRot);
1478         if (ir->bRot)
1479         {
1480             if (bRead)
1481             {
1482                 snew(ir->rot, 1);
1483             }
1484             do_rot(fio, ir->rot, bRead);
1485         }
1486     }
1487     else
1488     {
1489         ir->bRot = FALSE;
1490     }
1491
1492     /* Interactive molecular dynamics */
1493     if (file_version >= tpxv_InteractiveMolecularDynamics)
1494     {
1495         gmx_fio_do_gmx_bool(fio, ir->bIMD);
1496         if (ir->bIMD)
1497         {
1498             if (bRead)
1499             {
1500                 snew(ir->imd, 1);
1501             }
1502             do_imd(fio, ir->imd, bRead);
1503         }
1504     }
1505     else
1506     {
1507         /* We don't support IMD sessions for old .tpr files */
1508         ir->bIMD = FALSE;
1509     }
1510
1511     /* grpopts stuff */
1512     gmx_fio_do_int(fio, ir->opts.ngtc);
1513     if (file_version >= 69)
1514     {
1515         gmx_fio_do_int(fio, ir->opts.nhchainlength);
1516     }
1517     else
1518     {
1519         ir->opts.nhchainlength = 1;
1520     }
1521     gmx_fio_do_int(fio, ir->opts.ngacc);
1522     gmx_fio_do_int(fio, ir->opts.ngfrz);
1523     gmx_fio_do_int(fio, ir->opts.ngener);
1524
1525     if (bRead)
1526     {
1527         snew(ir->opts.nrdf,   ir->opts.ngtc);
1528         snew(ir->opts.ref_t,  ir->opts.ngtc);
1529         snew(ir->opts.annealing, ir->opts.ngtc);
1530         snew(ir->opts.anneal_npoints, ir->opts.ngtc);
1531         snew(ir->opts.anneal_time, ir->opts.ngtc);
1532         snew(ir->opts.anneal_temp, ir->opts.ngtc);
1533         snew(ir->opts.tau_t,  ir->opts.ngtc);
1534         snew(ir->opts.nFreeze, ir->opts.ngfrz);
1535         snew(ir->opts.acc,    ir->opts.ngacc);
1536         snew(ir->opts.egp_flags, ir->opts.ngener*ir->opts.ngener);
1537     }
1538     if (ir->opts.ngtc > 0)
1539     {
1540         gmx_fio_ndo_real(fio, ir->opts.nrdf, ir->opts.ngtc);
1541         gmx_fio_ndo_real(fio, ir->opts.ref_t, ir->opts.ngtc);
1542         gmx_fio_ndo_real(fio, ir->opts.tau_t, ir->opts.ngtc);
1543     }
1544     if (ir->opts.ngfrz > 0)
1545     {
1546         gmx_fio_ndo_ivec(fio, ir->opts.nFreeze, ir->opts.ngfrz);
1547     }
1548     if (ir->opts.ngacc > 0)
1549     {
1550         gmx_fio_ndo_rvec(fio, ir->opts.acc, ir->opts.ngacc);
1551     }
1552     gmx_fio_ndo_int(fio, ir->opts.egp_flags,
1553                     ir->opts.ngener*ir->opts.ngener);
1554
1555     /* First read the lists with annealing and npoints for each group */
1556     gmx_fio_ndo_int(fio, ir->opts.annealing, ir->opts.ngtc);
1557     gmx_fio_ndo_int(fio, ir->opts.anneal_npoints, ir->opts.ngtc);
1558     for (j = 0; j < (ir->opts.ngtc); j++)
1559     {
1560         k = ir->opts.anneal_npoints[j];
1561         if (bRead)
1562         {
1563             snew(ir->opts.anneal_time[j], k);
1564             snew(ir->opts.anneal_temp[j], k);
1565         }
1566         gmx_fio_ndo_real(fio, ir->opts.anneal_time[j], k);
1567         gmx_fio_ndo_real(fio, ir->opts.anneal_temp[j], k);
1568     }
1569     /* Walls */
1570     {
1571         gmx_fio_do_int(fio, ir->nwall);
1572         gmx_fio_do_int(fio, ir->wall_type);
1573         gmx_fio_do_real(fio, ir->wall_r_linpot);
1574         gmx_fio_do_int(fio, ir->wall_atomtype[0]);
1575         gmx_fio_do_int(fio, ir->wall_atomtype[1]);
1576         gmx_fio_do_real(fio, ir->wall_density[0]);
1577         gmx_fio_do_real(fio, ir->wall_density[1]);
1578         gmx_fio_do_real(fio, ir->wall_ewald_zfac);
1579     }
1580
1581     /* Cosine stuff for electric fields */
1582     if (file_version < tpxv_GenericParamsForElectricField)
1583     {
1584         do_legacy_efield(fio, &paramsObj);
1585     }
1586
1587     /* Swap ions */
1588     if (file_version >= tpxv_ComputationalElectrophysiology)
1589     {
1590         gmx_fio_do_int(fio, ir->eSwapCoords);
1591         if (ir->eSwapCoords != eswapNO)
1592         {
1593             if (bRead)
1594             {
1595                 snew(ir->swap, 1);
1596             }
1597             do_swapcoords_tpx(fio, ir->swap, bRead, file_version);
1598         }
1599     }
1600
1601     /* QMMM stuff */
1602     {
1603         gmx_fio_do_gmx_bool(fio, ir->bQMMM);
1604         gmx_fio_do_int(fio, ir->QMMMscheme);
1605         gmx_fio_do_real(fio, ir->scalefactor);
1606         gmx_fio_do_int(fio, ir->opts.ngQM);
1607         if (bRead)
1608         {
1609             snew(ir->opts.QMmethod,    ir->opts.ngQM);
1610             snew(ir->opts.QMbasis,     ir->opts.ngQM);
1611             snew(ir->opts.QMcharge,    ir->opts.ngQM);
1612             snew(ir->opts.QMmult,      ir->opts.ngQM);
1613             snew(ir->opts.bSH,         ir->opts.ngQM);
1614             snew(ir->opts.CASorbitals, ir->opts.ngQM);
1615             snew(ir->opts.CASelectrons, ir->opts.ngQM);
1616             snew(ir->opts.SAon,        ir->opts.ngQM);
1617             snew(ir->opts.SAoff,       ir->opts.ngQM);
1618             snew(ir->opts.SAsteps,     ir->opts.ngQM);
1619         }
1620         if (ir->opts.ngQM > 0)
1621         {
1622             gmx_fio_ndo_int(fio, ir->opts.QMmethod, ir->opts.ngQM);
1623             gmx_fio_ndo_int(fio, ir->opts.QMbasis, ir->opts.ngQM);
1624             gmx_fio_ndo_int(fio, ir->opts.QMcharge, ir->opts.ngQM);
1625             gmx_fio_ndo_int(fio, ir->opts.QMmult, ir->opts.ngQM);
1626             gmx_fio_ndo_gmx_bool(fio, ir->opts.bSH, ir->opts.ngQM);
1627             gmx_fio_ndo_int(fio, ir->opts.CASorbitals, ir->opts.ngQM);
1628             gmx_fio_ndo_int(fio, ir->opts.CASelectrons, ir->opts.ngQM);
1629             gmx_fio_ndo_real(fio, ir->opts.SAon, ir->opts.ngQM);
1630             gmx_fio_ndo_real(fio, ir->opts.SAoff, ir->opts.ngQM);
1631             gmx_fio_ndo_int(fio, ir->opts.SAsteps, ir->opts.ngQM);
1632             /* We leave in dummy i/o for removed parameters to avoid
1633              * changing the tpr format for every QMMM change.
1634              */
1635             std::vector<int> dummy(ir->opts.ngQM, 0);
1636             gmx_fio_ndo_int(fio, dummy.data(), ir->opts.ngQM);
1637             gmx_fio_ndo_int(fio, dummy.data(), ir->opts.ngQM);
1638         }
1639         /* end of QMMM stuff */
1640     }
1641
1642     if (file_version >= tpxv_GenericParamsForElectricField)
1643     {
1644         gmx::FileIOXdrSerializer serializer(fio);
1645         if (bRead)
1646         {
1647             paramsObj.mergeObject(
1648                     gmx::deserializeKeyValueTree(&serializer));
1649         }
1650         else
1651         {
1652             GMX_RELEASE_ASSERT(ir->params != nullptr,
1653                                "Parameters should be present when writing inputrec");
1654             gmx::serializeKeyValueTree(*ir->params, &serializer);
1655         }
1656     }
1657     if (bRead)
1658     {
1659         ir->params = new gmx::KeyValueTreeObject(paramsBuilder.build());
1660     }
1661 }
1662
1663
1664 static void do_harm(t_fileio *fio, t_iparams *iparams)
1665 {
1666     gmx_fio_do_real(fio, iparams->harmonic.rA);
1667     gmx_fio_do_real(fio, iparams->harmonic.krA);
1668     gmx_fio_do_real(fio, iparams->harmonic.rB);
1669     gmx_fio_do_real(fio, iparams->harmonic.krB);
1670 }
1671
1672 static void do_iparams(t_fileio *fio, t_functype ftype, t_iparams *iparams,
1673                        gmx_bool bRead, int file_version)
1674 {
1675     int      idum;
1676     real     rdum;
1677
1678     switch (ftype)
1679     {
1680         case F_ANGLES:
1681         case F_G96ANGLES:
1682         case F_BONDS:
1683         case F_G96BONDS:
1684         case F_HARMONIC:
1685         case F_IDIHS:
1686             do_harm(fio, iparams);
1687             if ((ftype == F_ANGRES || ftype == F_ANGRESZ) && bRead)
1688             {
1689                 /* Correct incorrect storage of parameters */
1690                 iparams->pdihs.phiB = iparams->pdihs.phiA;
1691                 iparams->pdihs.cpB  = iparams->pdihs.cpA;
1692             }
1693             break;
1694         case F_RESTRANGLES:
1695             gmx_fio_do_real(fio, iparams->harmonic.rA);
1696             gmx_fio_do_real(fio, iparams->harmonic.krA);
1697             break;
1698         case F_LINEAR_ANGLES:
1699             gmx_fio_do_real(fio, iparams->linangle.klinA);
1700             gmx_fio_do_real(fio, iparams->linangle.aA);
1701             gmx_fio_do_real(fio, iparams->linangle.klinB);
1702             gmx_fio_do_real(fio, iparams->linangle.aB);
1703             break;
1704         case F_FENEBONDS:
1705             gmx_fio_do_real(fio, iparams->fene.bm);
1706             gmx_fio_do_real(fio, iparams->fene.kb);
1707             break;
1708
1709         case F_RESTRBONDS:
1710             gmx_fio_do_real(fio, iparams->restraint.lowA);
1711             gmx_fio_do_real(fio, iparams->restraint.up1A);
1712             gmx_fio_do_real(fio, iparams->restraint.up2A);
1713             gmx_fio_do_real(fio, iparams->restraint.kA);
1714             gmx_fio_do_real(fio, iparams->restraint.lowB);
1715             gmx_fio_do_real(fio, iparams->restraint.up1B);
1716             gmx_fio_do_real(fio, iparams->restraint.up2B);
1717             gmx_fio_do_real(fio, iparams->restraint.kB);
1718             break;
1719         case F_TABBONDS:
1720         case F_TABBONDSNC:
1721         case F_TABANGLES:
1722         case F_TABDIHS:
1723             gmx_fio_do_real(fio, iparams->tab.kA);
1724             gmx_fio_do_int(fio, iparams->tab.table);
1725             gmx_fio_do_real(fio, iparams->tab.kB);
1726             break;
1727         case F_CROSS_BOND_BONDS:
1728             gmx_fio_do_real(fio, iparams->cross_bb.r1e);
1729             gmx_fio_do_real(fio, iparams->cross_bb.r2e);
1730             gmx_fio_do_real(fio, iparams->cross_bb.krr);
1731             break;
1732         case F_CROSS_BOND_ANGLES:
1733             gmx_fio_do_real(fio, iparams->cross_ba.r1e);
1734             gmx_fio_do_real(fio, iparams->cross_ba.r2e);
1735             gmx_fio_do_real(fio, iparams->cross_ba.r3e);
1736             gmx_fio_do_real(fio, iparams->cross_ba.krt);
1737             break;
1738         case F_UREY_BRADLEY:
1739             gmx_fio_do_real(fio, iparams->u_b.thetaA);
1740             gmx_fio_do_real(fio, iparams->u_b.kthetaA);
1741             gmx_fio_do_real(fio, iparams->u_b.r13A);
1742             gmx_fio_do_real(fio, iparams->u_b.kUBA);
1743             if (file_version >= 79)
1744             {
1745                 gmx_fio_do_real(fio, iparams->u_b.thetaB);
1746                 gmx_fio_do_real(fio, iparams->u_b.kthetaB);
1747                 gmx_fio_do_real(fio, iparams->u_b.r13B);
1748                 gmx_fio_do_real(fio, iparams->u_b.kUBB);
1749             }
1750             else
1751             {
1752                 iparams->u_b.thetaB  = iparams->u_b.thetaA;
1753                 iparams->u_b.kthetaB = iparams->u_b.kthetaA;
1754                 iparams->u_b.r13B    = iparams->u_b.r13A;
1755                 iparams->u_b.kUBB    = iparams->u_b.kUBA;
1756             }
1757             break;
1758         case F_QUARTIC_ANGLES:
1759             gmx_fio_do_real(fio, iparams->qangle.theta);
1760             gmx_fio_ndo_real(fio, iparams->qangle.c, 5);
1761             break;
1762         case F_BHAM:
1763             gmx_fio_do_real(fio, iparams->bham.a);
1764             gmx_fio_do_real(fio, iparams->bham.b);
1765             gmx_fio_do_real(fio, iparams->bham.c);
1766             break;
1767         case F_MORSE:
1768             gmx_fio_do_real(fio, iparams->morse.b0A);
1769             gmx_fio_do_real(fio, iparams->morse.cbA);
1770             gmx_fio_do_real(fio, iparams->morse.betaA);
1771             if (file_version >= 79)
1772             {
1773                 gmx_fio_do_real(fio, iparams->morse.b0B);
1774                 gmx_fio_do_real(fio, iparams->morse.cbB);
1775                 gmx_fio_do_real(fio, iparams->morse.betaB);
1776             }
1777             else
1778             {
1779                 iparams->morse.b0B   = iparams->morse.b0A;
1780                 iparams->morse.cbB   = iparams->morse.cbA;
1781                 iparams->morse.betaB = iparams->morse.betaA;
1782             }
1783             break;
1784         case F_CUBICBONDS:
1785             gmx_fio_do_real(fio, iparams->cubic.b0);
1786             gmx_fio_do_real(fio, iparams->cubic.kb);
1787             gmx_fio_do_real(fio, iparams->cubic.kcub);
1788             break;
1789         case F_CONNBONDS:
1790             break;
1791         case F_POLARIZATION:
1792             gmx_fio_do_real(fio, iparams->polarize.alpha);
1793             break;
1794         case F_ANHARM_POL:
1795             gmx_fio_do_real(fio, iparams->anharm_polarize.alpha);
1796             gmx_fio_do_real(fio, iparams->anharm_polarize.drcut);
1797             gmx_fio_do_real(fio, iparams->anharm_polarize.khyp);
1798             break;
1799         case F_WATER_POL:
1800             gmx_fio_do_real(fio, iparams->wpol.al_x);
1801             gmx_fio_do_real(fio, iparams->wpol.al_y);
1802             gmx_fio_do_real(fio, iparams->wpol.al_z);
1803             gmx_fio_do_real(fio, iparams->wpol.rOH);
1804             gmx_fio_do_real(fio, iparams->wpol.rHH);
1805             gmx_fio_do_real(fio, iparams->wpol.rOD);
1806             break;
1807         case F_THOLE_POL:
1808             gmx_fio_do_real(fio, iparams->thole.a);
1809             gmx_fio_do_real(fio, iparams->thole.alpha1);
1810             gmx_fio_do_real(fio, iparams->thole.alpha2);
1811             gmx_fio_do_real(fio, iparams->thole.rfac);
1812             break;
1813         case F_LJ:
1814             gmx_fio_do_real(fio, iparams->lj.c6);
1815             gmx_fio_do_real(fio, iparams->lj.c12);
1816             break;
1817         case F_LJ14:
1818             gmx_fio_do_real(fio, iparams->lj14.c6A);
1819             gmx_fio_do_real(fio, iparams->lj14.c12A);
1820             gmx_fio_do_real(fio, iparams->lj14.c6B);
1821             gmx_fio_do_real(fio, iparams->lj14.c12B);
1822             break;
1823         case F_LJC14_Q:
1824             gmx_fio_do_real(fio, iparams->ljc14.fqq);
1825             gmx_fio_do_real(fio, iparams->ljc14.qi);
1826             gmx_fio_do_real(fio, iparams->ljc14.qj);
1827             gmx_fio_do_real(fio, iparams->ljc14.c6);
1828             gmx_fio_do_real(fio, iparams->ljc14.c12);
1829             break;
1830         case F_LJC_PAIRS_NB:
1831             gmx_fio_do_real(fio, iparams->ljcnb.qi);
1832             gmx_fio_do_real(fio, iparams->ljcnb.qj);
1833             gmx_fio_do_real(fio, iparams->ljcnb.c6);
1834             gmx_fio_do_real(fio, iparams->ljcnb.c12);
1835             break;
1836         case F_PDIHS:
1837         case F_PIDIHS:
1838         case F_ANGRES:
1839         case F_ANGRESZ:
1840             gmx_fio_do_real(fio, iparams->pdihs.phiA);
1841             gmx_fio_do_real(fio, iparams->pdihs.cpA);
1842             gmx_fio_do_real(fio, iparams->pdihs.phiB);
1843             gmx_fio_do_real(fio, iparams->pdihs.cpB);
1844             gmx_fio_do_int(fio, iparams->pdihs.mult);
1845             break;
1846         case F_RESTRDIHS:
1847             gmx_fio_do_real(fio, iparams->pdihs.phiA);
1848             gmx_fio_do_real(fio, iparams->pdihs.cpA);
1849             break;
1850         case F_DISRES:
1851             gmx_fio_do_int(fio, iparams->disres.label);
1852             gmx_fio_do_int(fio, iparams->disres.type);
1853             gmx_fio_do_real(fio, iparams->disres.low);
1854             gmx_fio_do_real(fio, iparams->disres.up1);
1855             gmx_fio_do_real(fio, iparams->disres.up2);
1856             gmx_fio_do_real(fio, iparams->disres.kfac);
1857             break;
1858         case F_ORIRES:
1859             gmx_fio_do_int(fio, iparams->orires.ex);
1860             gmx_fio_do_int(fio, iparams->orires.label);
1861             gmx_fio_do_int(fio, iparams->orires.power);
1862             gmx_fio_do_real(fio, iparams->orires.c);
1863             gmx_fio_do_real(fio, iparams->orires.obs);
1864             gmx_fio_do_real(fio, iparams->orires.kfac);
1865             break;
1866         case F_DIHRES:
1867             if (file_version < 82)
1868             {
1869                 gmx_fio_do_int(fio, idum);
1870                 gmx_fio_do_int(fio, idum);
1871             }
1872             gmx_fio_do_real(fio, iparams->dihres.phiA);
1873             gmx_fio_do_real(fio, iparams->dihres.dphiA);
1874             gmx_fio_do_real(fio, iparams->dihres.kfacA);
1875             if (file_version >= 82)
1876             {
1877                 gmx_fio_do_real(fio, iparams->dihres.phiB);
1878                 gmx_fio_do_real(fio, iparams->dihres.dphiB);
1879                 gmx_fio_do_real(fio, iparams->dihres.kfacB);
1880             }
1881             else
1882             {
1883                 iparams->dihres.phiB  = iparams->dihres.phiA;
1884                 iparams->dihres.dphiB = iparams->dihres.dphiA;
1885                 iparams->dihres.kfacB = iparams->dihres.kfacA;
1886             }
1887             break;
1888         case F_POSRES:
1889             gmx_fio_do_rvec(fio, iparams->posres.pos0A);
1890             gmx_fio_do_rvec(fio, iparams->posres.fcA);
1891             gmx_fio_do_rvec(fio, iparams->posres.pos0B);
1892             gmx_fio_do_rvec(fio, iparams->posres.fcB);
1893             break;
1894         case F_FBPOSRES:
1895             gmx_fio_do_int(fio, iparams->fbposres.geom);
1896             gmx_fio_do_rvec(fio, iparams->fbposres.pos0);
1897             gmx_fio_do_real(fio, iparams->fbposres.r);
1898             gmx_fio_do_real(fio, iparams->fbposres.k);
1899             break;
1900         case F_CBTDIHS:
1901             gmx_fio_ndo_real(fio, iparams->cbtdihs.cbtcA, NR_CBTDIHS);
1902             break;
1903         case F_RBDIHS:
1904             gmx_fio_ndo_real(fio, iparams->rbdihs.rbcA, NR_RBDIHS);
1905             gmx_fio_ndo_real(fio, iparams->rbdihs.rbcB, NR_RBDIHS);
1906             break;
1907         case F_FOURDIHS:
1908             /* Fourier dihedrals are internally represented
1909              * as Ryckaert-Bellemans since those are faster to compute.
1910              */
1911             gmx_fio_ndo_real(fio, iparams->rbdihs.rbcA, NR_RBDIHS);
1912             gmx_fio_ndo_real(fio, iparams->rbdihs.rbcB, NR_RBDIHS);
1913             break;
1914         case F_CONSTR:
1915         case F_CONSTRNC:
1916             gmx_fio_do_real(fio, iparams->constr.dA);
1917             gmx_fio_do_real(fio, iparams->constr.dB);
1918             break;
1919         case F_SETTLE:
1920             gmx_fio_do_real(fio, iparams->settle.doh);
1921             gmx_fio_do_real(fio, iparams->settle.dhh);
1922             break;
1923         case F_VSITE2:
1924             gmx_fio_do_real(fio, iparams->vsite.a);
1925             break;
1926         case F_VSITE3:
1927         case F_VSITE3FD:
1928         case F_VSITE3FAD:
1929             gmx_fio_do_real(fio, iparams->vsite.a);
1930             gmx_fio_do_real(fio, iparams->vsite.b);
1931             break;
1932         case F_VSITE3OUT:
1933         case F_VSITE4FD:
1934         case F_VSITE4FDN:
1935             gmx_fio_do_real(fio, iparams->vsite.a);
1936             gmx_fio_do_real(fio, iparams->vsite.b);
1937             gmx_fio_do_real(fio, iparams->vsite.c);
1938             break;
1939         case F_VSITEN:
1940             gmx_fio_do_int(fio, iparams->vsiten.n);
1941             gmx_fio_do_real(fio, iparams->vsiten.a);
1942             break;
1943         case F_GB12_NOLONGERUSED:
1944         case F_GB13_NOLONGERUSED:
1945         case F_GB14_NOLONGERUSED:
1946             // Implicit solvent parameters can still be read, but never used
1947             if (bRead)
1948             {
1949                 if (file_version < 68)
1950                 {
1951                     gmx_fio_do_real(fio, rdum);
1952                     gmx_fio_do_real(fio, rdum);
1953                     gmx_fio_do_real(fio, rdum);
1954                     gmx_fio_do_real(fio, rdum);
1955                 }
1956                 if (file_version < tpxv_RemoveImplicitSolvation)
1957                 {
1958                     gmx_fio_do_real(fio, rdum);
1959                     gmx_fio_do_real(fio, rdum);
1960                     gmx_fio_do_real(fio, rdum);
1961                     gmx_fio_do_real(fio, rdum);
1962                     gmx_fio_do_real(fio, rdum);
1963                 }
1964             }
1965             break;
1966         case F_CMAP:
1967             gmx_fio_do_int(fio, iparams->cmap.cmapA);
1968             gmx_fio_do_int(fio, iparams->cmap.cmapB);
1969             break;
1970         default:
1971             gmx_fatal(FARGS, "unknown function type %d (%s) in %s line %d",
1972                       ftype, interaction_function[ftype].name, __FILE__, __LINE__);
1973     }
1974 }
1975
1976 static void do_ilist(t_fileio *fio, InteractionList *ilist, gmx_bool bRead)
1977 {
1978     int nr = ilist->size();
1979     gmx_fio_do_int(fio, nr);
1980     if (bRead)
1981     {
1982         ilist->iatoms.resize(nr);
1983     }
1984     gmx_fio_ndo_int(fio, ilist->iatoms.data(), ilist->size());
1985 }
1986
1987 static void do_ffparams(t_fileio *fio, gmx_ffparams_t *ffparams,
1988                         gmx_bool bRead, int file_version)
1989 {
1990     gmx_fio_do_int(fio, ffparams->atnr);
1991     int numTypes = ffparams->numTypes();
1992     gmx_fio_do_int(fio, numTypes);
1993     if (bRead)
1994     {
1995         ffparams->functype.resize(numTypes);
1996         ffparams->iparams.resize(numTypes);
1997     }
1998     /* Read/write all the function types */
1999     gmx_fio_ndo_int(fio, ffparams->functype.data(), ffparams->functype.size());
2000
2001     if (file_version >= 66)
2002     {
2003         gmx_fio_do_double(fio, ffparams->reppow);
2004     }
2005     else
2006     {
2007         ffparams->reppow = 12.0;
2008     }
2009
2010     gmx_fio_do_real(fio, ffparams->fudgeQQ);
2011
2012     /* Check whether all these function types are supported by the code.
2013      * In practice the code is backwards compatible, which means that the
2014      * numbering may have to be altered from old numbering to new numbering
2015      */
2016     for (int i = 0; i < ffparams->numTypes(); i++)
2017     {
2018         if (bRead)
2019         {
2020             /* Loop over file versions */
2021             for (int k = 0; k < NFTUPD; k++)
2022             {
2023                 /* Compare the read file_version to the update table */
2024                 if ((file_version < ftupd[k].fvnr) &&
2025                     (ffparams->functype[i] >= ftupd[k].ftype))
2026                 {
2027                     ffparams->functype[i] += 1;
2028                 }
2029             }
2030         }
2031
2032         do_iparams(fio, ffparams->functype[i], &ffparams->iparams[i], bRead,
2033                    file_version);
2034     }
2035 }
2036
2037 static void add_settle_atoms(InteractionList *ilist)
2038 {
2039     int i;
2040
2041     /* Settle used to only store the first atom: add the other two */
2042     ilist->iatoms.resize(2*ilist->size());
2043     for (i = ilist->size()/4 - 1; i >= 0; i--)
2044     {
2045         ilist->iatoms[4*i+0] = ilist->iatoms[2*i+0];
2046         ilist->iatoms[4*i+1] = ilist->iatoms[2*i+1];
2047         ilist->iatoms[4*i+2] = ilist->iatoms[2*i+1] + 1;
2048         ilist->iatoms[4*i+3] = ilist->iatoms[2*i+1] + 2;
2049     }
2050 }
2051
2052 static void do_ilists(t_fileio *fio, InteractionLists *ilists, gmx_bool bRead,
2053                       int file_version)
2054 {
2055     GMX_RELEASE_ASSERT(ilists, "Need a valid ilists object");
2056     GMX_RELEASE_ASSERT(ilists->size() == F_NRE, "The code needs to be in sync with InteractionLists");
2057
2058     for (int j = 0; j < F_NRE; j++)
2059     {
2060         InteractionList &ilist  = (*ilists)[j];
2061         gmx_bool         bClear = FALSE;
2062         if (bRead)
2063         {
2064             for (int k = 0; k < NFTUPD; k++)
2065             {
2066                 if ((file_version < ftupd[k].fvnr) && (j == ftupd[k].ftype))
2067                 {
2068                     bClear = TRUE;
2069                 }
2070             }
2071         }
2072         if (bClear)
2073         {
2074             ilist.iatoms.clear();
2075         }
2076         else
2077         {
2078             do_ilist(fio, &ilist, bRead);
2079             if (file_version < 78 && j == F_SETTLE && ilist.size() > 0)
2080             {
2081                 add_settle_atoms(&ilist);
2082             }
2083         }
2084     }
2085 }
2086
2087 static void do_block(t_fileio *fio, t_block *block, gmx_bool bRead)
2088 {
2089     gmx_fio_do_int(fio, block->nr);
2090     if (bRead)
2091     {
2092         if ((block->nalloc_index > 0) && (nullptr != block->index))
2093         {
2094             sfree(block->index);
2095         }
2096         block->nalloc_index = block->nr+1;
2097         snew(block->index, block->nalloc_index);
2098     }
2099     gmx_fio_ndo_int(fio, block->index, block->nr+1);
2100 }
2101
2102 static void do_blocka(t_fileio *fio, t_blocka *block, gmx_bool bRead)
2103 {
2104     gmx_fio_do_int(fio, block->nr);
2105     gmx_fio_do_int(fio, block->nra);
2106     if (bRead)
2107     {
2108         block->nalloc_index = block->nr+1;
2109         snew(block->index, block->nalloc_index);
2110         block->nalloc_a = block->nra;
2111         snew(block->a, block->nalloc_a);
2112     }
2113     gmx_fio_ndo_int(fio, block->index, block->nr+1);
2114     gmx_fio_ndo_int(fio, block->a, block->nra);
2115 }
2116
2117 /* This is a primitive routine to make it possible to translate atomic numbers
2118  * to element names when reading TPR files, without making the Gromacs library
2119  * directory a dependency on mdrun (which is the case if we need elements.dat).
2120  */
2121 static const char *
2122 atomicnumber_to_element(int atomicnumber)
2123 {
2124     const char * p;
2125
2126     /* This does not have to be complete, so we only include elements likely
2127      * to occur in PDB files.
2128      */
2129     switch (atomicnumber)
2130     {
2131         case 1:  p = "H";  break;
2132         case 5:  p = "B";  break;
2133         case 6:  p = "C";  break;
2134         case 7:  p = "N";  break;
2135         case 8:  p = "O";  break;
2136         case 9:  p = "F";  break;
2137         case 11: p = "Na"; break;
2138         case 12: p = "Mg"; break;
2139         case 15: p = "P";  break;
2140         case 16: p = "S";  break;
2141         case 17: p = "Cl"; break;
2142         case 18: p = "Ar"; break;
2143         case 19: p = "K";  break;
2144         case 20: p = "Ca"; break;
2145         case 25: p = "Mn"; break;
2146         case 26: p = "Fe"; break;
2147         case 28: p = "Ni"; break;
2148         case 29: p = "Cu"; break;
2149         case 30: p = "Zn"; break;
2150         case 35: p = "Br"; break;
2151         case 47: p = "Ag"; break;
2152         default: p = "";   break;
2153     }
2154     return p;
2155 }
2156
2157
2158 static void do_atom(t_fileio *fio, t_atom *atom, gmx_bool bRead)
2159 {
2160     gmx_fio_do_real(fio, atom->m);
2161     gmx_fio_do_real(fio, atom->q);
2162     gmx_fio_do_real(fio, atom->mB);
2163     gmx_fio_do_real(fio, atom->qB);
2164     gmx_fio_do_ushort(fio, atom->type);
2165     gmx_fio_do_ushort(fio, atom->typeB);
2166     gmx_fio_do_int(fio, atom->ptype);
2167     gmx_fio_do_int(fio, atom->resind);
2168     gmx_fio_do_int(fio, atom->atomnumber);
2169     if (bRead)
2170     {
2171         /* Set element string from atomic number if present.
2172          * This routine returns an empty string if the name is not found.
2173          */
2174         std::strncpy(atom->elem, atomicnumber_to_element(atom->atomnumber), 4);
2175         /* avoid warnings about potentially unterminated string */
2176         atom->elem[3] = '\0';
2177     }
2178 }
2179
2180 static void do_grps(t_fileio *fio, int ngrp, t_grps grps[], gmx_bool bRead)
2181 {
2182     for (int j = 0; j < ngrp; j++)
2183     {
2184         gmx_fio_do_int(fio, grps[j].nr);
2185         if (bRead)
2186         {
2187             snew(grps[j].nm_ind, grps[j].nr);
2188         }
2189         gmx_fio_ndo_int(fio, grps[j].nm_ind, grps[j].nr);
2190     }
2191 }
2192
2193 static void do_symstr(t_fileio *fio, char ***nm, gmx_bool bRead, t_symtab *symtab)
2194 {
2195     int ls;
2196
2197     if (bRead)
2198     {
2199         gmx_fio_do_int(fio, ls);
2200         *nm = get_symtab_handle(symtab, ls);
2201     }
2202     else
2203     {
2204         ls = lookup_symtab(symtab, *nm);
2205         gmx_fio_do_int(fio, ls);
2206     }
2207 }
2208
2209 static void do_strstr(t_fileio *fio, int nstr, char ***nm, gmx_bool bRead,
2210                       t_symtab *symtab)
2211 {
2212     int  j;
2213
2214     for (j = 0; (j < nstr); j++)
2215     {
2216         do_symstr(fio, &(nm[j]), bRead, symtab);
2217     }
2218 }
2219
2220 static void do_resinfo(t_fileio *fio, int n, t_resinfo *ri, gmx_bool bRead,
2221                        t_symtab *symtab, int file_version)
2222 {
2223     int  j;
2224
2225     for (j = 0; (j < n); j++)
2226     {
2227         do_symstr(fio, &(ri[j].name), bRead, symtab);
2228         if (file_version >= 63)
2229         {
2230             gmx_fio_do_int(fio, ri[j].nr);
2231             gmx_fio_do_uchar(fio, ri[j].ic);
2232         }
2233         else
2234         {
2235             ri[j].nr = j + 1;
2236             ri[j].ic = ' ';
2237         }
2238     }
2239 }
2240
2241 static void do_atoms(t_fileio *fio, t_atoms *atoms, gmx_bool bRead, t_symtab *symtab,
2242                      int file_version)
2243 {
2244     int i;
2245
2246     gmx_fio_do_int(fio, atoms->nr);
2247     gmx_fio_do_int(fio, atoms->nres);
2248     if (bRead)
2249     {
2250         /* Since we have always written all t_atom properties in the tpr file
2251          * (at least for all backward compatible versions), we don't store
2252          * but simple set the booleans here.
2253          */
2254         atoms->haveMass    = TRUE;
2255         atoms->haveCharge  = TRUE;
2256         atoms->haveType    = TRUE;
2257         atoms->haveBState  = TRUE;
2258         atoms->havePdbInfo = FALSE;
2259
2260         snew(atoms->atom, atoms->nr);
2261         snew(atoms->atomname, atoms->nr);
2262         snew(atoms->atomtype, atoms->nr);
2263         snew(atoms->atomtypeB, atoms->nr);
2264         snew(atoms->resinfo, atoms->nres);
2265         atoms->pdbinfo = nullptr;
2266     }
2267     else
2268     {
2269         GMX_RELEASE_ASSERT(atoms->haveMass && atoms->haveCharge && atoms->haveType && atoms->haveBState, "Mass, charge, atomtype and B-state parameters should be present in t_atoms when writing a tpr file");
2270     }
2271     for (i = 0; (i < atoms->nr); i++)
2272     {
2273         do_atom(fio, &atoms->atom[i], bRead);
2274     }
2275     do_strstr(fio, atoms->nr, atoms->atomname, bRead, symtab);
2276     do_strstr(fio, atoms->nr, atoms->atomtype, bRead, symtab);
2277     do_strstr(fio, atoms->nr, atoms->atomtypeB, bRead, symtab);
2278
2279     do_resinfo(fio, atoms->nres, atoms->resinfo, bRead, symtab, file_version);
2280 }
2281
2282 static void do_groups(t_fileio *fio, gmx_groups_t *groups,
2283                       gmx_bool bRead, t_symtab *symtab)
2284 {
2285     int      g;
2286
2287     do_grps(fio, egcNR, groups->grps, bRead);
2288     gmx_fio_do_int(fio, groups->ngrpname);
2289     if (bRead)
2290     {
2291         snew(groups->grpname, groups->ngrpname);
2292     }
2293     do_strstr(fio, groups->ngrpname, groups->grpname, bRead, symtab);
2294     for (g = 0; g < egcNR; g++)
2295     {
2296         gmx_fio_do_int(fio, groups->ngrpnr[g]);
2297         if (groups->ngrpnr[g] == 0)
2298         {
2299             if (bRead)
2300             {
2301                 groups->grpnr[g] = nullptr;
2302             }
2303         }
2304         else
2305         {
2306             if (bRead)
2307             {
2308                 snew(groups->grpnr[g], groups->ngrpnr[g]);
2309             }
2310             gmx_fio_ndo_uchar(fio, groups->grpnr[g], groups->ngrpnr[g]);
2311         }
2312     }
2313 }
2314
2315 static void do_atomtypes(t_fileio *fio, t_atomtypes *atomtypes, gmx_bool bRead,
2316                          int file_version)
2317 {
2318     int      j;
2319
2320     gmx_fio_do_int(fio, atomtypes->nr);
2321     j = atomtypes->nr;
2322     if (bRead)
2323     {
2324         snew(atomtypes->atomnumber, j);
2325     }
2326     if (bRead && file_version < tpxv_RemoveImplicitSolvation)
2327     {
2328         std::vector<real> dummy(atomtypes->nr, 0);
2329         gmx_fio_ndo_real(fio, dummy.data(), dummy.size());
2330         gmx_fio_ndo_real(fio, dummy.data(), dummy.size());
2331         gmx_fio_ndo_real(fio, dummy.data(), dummy.size());
2332     }
2333     gmx_fio_ndo_int(fio, atomtypes->atomnumber, j);
2334
2335     if (bRead && file_version >= 60 && file_version < tpxv_RemoveImplicitSolvation)
2336     {
2337         std::vector<real> dummy(atomtypes->nr, 0);
2338         gmx_fio_ndo_real(fio, dummy.data(), dummy.size());
2339         gmx_fio_ndo_real(fio, dummy.data(), dummy.size());
2340     }
2341 }
2342
2343 static void do_symtab(t_fileio *fio, t_symtab *symtab, gmx_bool bRead)
2344 {
2345     int       i, nr;
2346     t_symbuf *symbuf;
2347     char      buf[STRLEN];
2348
2349     gmx_fio_do_int(fio, symtab->nr);
2350     nr     = symtab->nr;
2351     if (bRead)
2352     {
2353         snew(symtab->symbuf, 1);
2354         symbuf          = symtab->symbuf;
2355         symbuf->bufsize = nr;
2356         snew(symbuf->buf, nr);
2357         for (i = 0; (i < nr); i++)
2358         {
2359             gmx_fio_do_string(fio, buf);
2360             symbuf->buf[i] = gmx_strdup(buf);
2361         }
2362     }
2363     else
2364     {
2365         symbuf = symtab->symbuf;
2366         while (symbuf != nullptr)
2367         {
2368             for (i = 0; (i < symbuf->bufsize) && (i < nr); i++)
2369             {
2370                 gmx_fio_do_string(fio, symbuf->buf[i]);
2371             }
2372             nr    -= i;
2373             symbuf = symbuf->next;
2374         }
2375         if (nr != 0)
2376         {
2377             gmx_fatal(FARGS, "nr of symtab strings left: %d", nr);
2378         }
2379     }
2380 }
2381
2382 static void do_cmap(t_fileio *fio, gmx_cmap_t *cmap_grid, gmx_bool bRead)
2383 {
2384
2385     int ngrid = cmap_grid->cmapdata.size();
2386     gmx_fio_do_int(fio, ngrid);
2387     gmx_fio_do_int(fio, cmap_grid->grid_spacing);
2388
2389     int gs    = cmap_grid->grid_spacing;
2390     int nelem = gs * gs;
2391
2392     if (bRead)
2393     {
2394         cmap_grid->cmapdata.resize(ngrid);
2395
2396         for (int i = 0; i < ngrid; i++)
2397         {
2398             cmap_grid->cmapdata[i].cmap.resize(4*nelem);
2399         }
2400     }
2401
2402     for (int i = 0; i < ngrid; i++)
2403     {
2404         for (int j = 0; j < nelem; j++)
2405         {
2406             gmx_fio_do_real(fio, cmap_grid->cmapdata[i].cmap[j*4]);
2407             gmx_fio_do_real(fio, cmap_grid->cmapdata[i].cmap[j*4+1]);
2408             gmx_fio_do_real(fio, cmap_grid->cmapdata[i].cmap[j*4+2]);
2409             gmx_fio_do_real(fio, cmap_grid->cmapdata[i].cmap[j*4+3]);
2410         }
2411     }
2412 }
2413
2414
2415 static void do_moltype(t_fileio *fio, gmx_moltype_t *molt, gmx_bool bRead,
2416                        t_symtab *symtab, int file_version)
2417 {
2418     do_symstr(fio, &(molt->name), bRead, symtab);
2419
2420     do_atoms(fio, &molt->atoms, bRead, symtab, file_version);
2421
2422     do_ilists(fio, &molt->ilist, bRead, file_version);
2423
2424     do_block(fio, &molt->cgs, bRead);
2425
2426     /* This used to be in the atoms struct */
2427     do_blocka(fio, &molt->excls, bRead);
2428 }
2429
2430 static void do_molblock(t_fileio *fio, gmx_molblock_t *molb,
2431                         int numAtomsPerMolecule,
2432                         gmx_bool bRead)
2433 {
2434     gmx_fio_do_int(fio, molb->type);
2435     gmx_fio_do_int(fio, molb->nmol);
2436     /* To maintain forward topology reading compatibility, we store #atoms.
2437      * TODO: Change this to conditional reading of a dummy int when we
2438      *       increase tpx_generation.
2439      */
2440     gmx_fio_do_int(fio, numAtomsPerMolecule);
2441     /* Position restraint coordinates */
2442     int numPosres_xA = molb->posres_xA.size();
2443     gmx_fio_do_int(fio, numPosres_xA);
2444     if (numPosres_xA > 0)
2445     {
2446         if (bRead)
2447         {
2448             molb->posres_xA.resize(numPosres_xA);
2449         }
2450         gmx_fio_ndo_rvec(fio, as_rvec_array(molb->posres_xA.data()), numPosres_xA);
2451     }
2452     int numPosres_xB = molb->posres_xB.size();
2453     gmx_fio_do_int(fio, numPosres_xB);
2454     if (numPosres_xB > 0)
2455     {
2456         if (bRead)
2457         {
2458             molb->posres_xB.resize(numPosres_xB);
2459         }
2460         gmx_fio_ndo_rvec(fio, as_rvec_array(molb->posres_xB.data()), numPosres_xB);
2461     }
2462
2463 }
2464
2465 static void set_disres_npair(gmx_mtop_t *mtop)
2466 {
2467     gmx_mtop_ilistloop_t     iloop;
2468     int                      nmol;
2469
2470     gmx::ArrayRef<t_iparams> ip = mtop->ffparams.iparams;
2471
2472     iloop     = gmx_mtop_ilistloop_init(mtop);
2473     while (const InteractionLists *ilist = gmx_mtop_ilistloop_next(iloop, &nmol))
2474     {
2475         const InteractionList &il = (*ilist)[F_DISRES];
2476
2477         if (il.size() > 0)
2478         {
2479             gmx::ArrayRef<const int> a     = il.iatoms;
2480             int                      npair = 0;
2481             for (int i = 0; i < il.size(); i += 3)
2482             {
2483                 npair++;
2484                 if (i+3 == il.size() || ip[a[i]].disres.label != ip[a[i+3]].disres.label)
2485                 {
2486                     ip[a[i]].disres.npair = npair;
2487                     npair                 = 0;
2488                 }
2489             }
2490         }
2491     }
2492 }
2493
2494 static void do_mtop(t_fileio *fio, gmx_mtop_t *mtop, gmx_bool bRead,
2495                     int file_version)
2496 {
2497     do_symtab(fio, &(mtop->symtab), bRead);
2498
2499     do_symstr(fio, &(mtop->name), bRead, &(mtop->symtab));
2500
2501     do_ffparams(fio, &mtop->ffparams, bRead, file_version);
2502
2503     int nmoltype = mtop->moltype.size();
2504     gmx_fio_do_int(fio, nmoltype);
2505     if (bRead)
2506     {
2507         mtop->moltype.resize(nmoltype);
2508     }
2509     for (gmx_moltype_t &moltype : mtop->moltype)
2510     {
2511         do_moltype(fio, &moltype, bRead, &mtop->symtab, file_version);
2512     }
2513
2514     int nmolblock = mtop->molblock.size();
2515     gmx_fio_do_int(fio, nmolblock);
2516     if (bRead)
2517     {
2518         mtop->molblock.resize(nmolblock);
2519     }
2520     for (gmx_molblock_t &molblock : mtop->molblock)
2521     {
2522         int numAtomsPerMolecule = (bRead ? 0 : mtop->moltype[molblock.type].atoms.nr);
2523         do_molblock(fio, &molblock, numAtomsPerMolecule, bRead);
2524     }
2525     gmx_fio_do_int(fio, mtop->natoms);
2526
2527     if (file_version >= tpxv_IntermolecularBondeds)
2528     {
2529         gmx_fio_do_gmx_bool(fio, mtop->bIntermolecularInteractions);
2530         if (mtop->bIntermolecularInteractions)
2531         {
2532             if (bRead)
2533             {
2534                 mtop->intermolecular_ilist = gmx::compat::make_unique<InteractionLists>();
2535             }
2536             do_ilists(fio, mtop->intermolecular_ilist.get(), bRead, file_version);
2537         }
2538     }
2539     else
2540     {
2541         mtop->bIntermolecularInteractions = FALSE;
2542     }
2543
2544     do_atomtypes (fio, &(mtop->atomtypes), bRead, file_version);
2545
2546     if (file_version >= 65)
2547     {
2548         do_cmap(fio, &mtop->ffparams.cmap_grid, bRead);
2549     }
2550     else
2551     {
2552         mtop->ffparams.cmap_grid.grid_spacing = 0;
2553         mtop->ffparams.cmap_grid.cmapdata.clear();
2554     }
2555
2556     do_groups(fio, &mtop->groups, bRead, &(mtop->symtab));
2557
2558     mtop->haveMoleculeIndices = true;
2559
2560     if (bRead)
2561     {
2562         close_symtab(&(mtop->symtab));
2563     }
2564 }
2565
2566 /* If TopOnlyOK is TRUE then we can read even future versions
2567  * of tpx files, provided the fileGeneration hasn't changed.
2568  * If it is FALSE, we need the inputrecord too, and bail out
2569  * if the file is newer than the program.
2570  *
2571  * The version and generation of the topology (see top of this file)
2572  * are returned in the two last arguments, if those arguments are non-NULL.
2573  *
2574  * If possible, we will read the inputrec even when TopOnlyOK is TRUE.
2575  */
2576 static void do_tpxheader(t_fileio *fio, gmx_bool bRead, t_tpxheader *tpx,
2577                          gmx_bool TopOnlyOK, int *fileVersionPointer, int *fileGenerationPointer)
2578 {
2579     char      buf[STRLEN];
2580     char      file_tag[STRLEN];
2581     gmx_bool  bDouble;
2582     int       precision;
2583     int       idum = 0;
2584     real      rdum = 0;
2585     int       fileVersion;    /* Version number of the code that wrote the file */
2586     int       fileGeneration; /* Generation version number of the code that wrote the file */
2587
2588     /* XDR binary topology file */
2589     precision = sizeof(real);
2590     if (bRead)
2591     {
2592         gmx_fio_do_string(fio, buf);
2593         if (std::strncmp(buf, "VERSION", 7) != 0)
2594         {
2595             gmx_fatal(FARGS, "Can not read file %s,\n"
2596                       "             this file is from a GROMACS version which is older than 2.0\n"
2597                       "             Make a new one with grompp or use a gro or pdb file, if possible",
2598                       gmx_fio_getname(fio));
2599         }
2600         gmx_fio_do_int(fio, precision);
2601         bDouble = (precision == sizeof(double));
2602         if ((precision != sizeof(float)) && !bDouble)
2603         {
2604             gmx_fatal(FARGS, "Unknown precision in file %s: real is %d bytes "
2605                       "instead of %zu or %zu",
2606                       gmx_fio_getname(fio), precision, sizeof(float), sizeof(double));
2607         }
2608         gmx_fio_setprecision(fio, bDouble);
2609         fprintf(stderr, "Reading file %s, %s (%s precision)\n",
2610                 gmx_fio_getname(fio), buf, bDouble ? "double" : "single");
2611     }
2612     else
2613     {
2614         snprintf(buf, STRLEN, "VERSION %s", gmx_version());
2615         gmx_fio_write_string(fio, buf);
2616         bDouble = (precision == sizeof(double));
2617         gmx_fio_setprecision(fio, bDouble);
2618         gmx_fio_do_int(fio, precision);
2619         fileVersion = tpx_version;
2620         sprintf(file_tag, "%s", tpx_tag);
2621         fileGeneration = tpx_generation;
2622     }
2623
2624     /* Check versions! */
2625     gmx_fio_do_int(fio, fileVersion);
2626
2627     /* This is for backward compatibility with development versions 77-79
2628      * where the tag was, mistakenly, placed before the generation,
2629      * which would cause a segv instead of a proper error message
2630      * when reading the topology only from tpx with <77 code.
2631      */
2632     if (fileVersion >= 77 && fileVersion <= 79)
2633     {
2634         gmx_fio_do_string(fio, file_tag);
2635     }
2636
2637     gmx_fio_do_int(fio, fileGeneration);
2638
2639     if (fileVersion >= 81)
2640     {
2641         gmx_fio_do_string(fio, file_tag);
2642     }
2643     if (bRead)
2644     {
2645         if (fileVersion < 77)
2646         {
2647             /* Versions before 77 don't have the tag, set it to release */
2648             sprintf(file_tag, "%s", TPX_TAG_RELEASE);
2649         }
2650
2651         if (std::strcmp(file_tag, tpx_tag) != 0)
2652         {
2653             fprintf(stderr, "Note: file tpx tag '%s', software tpx tag '%s'\n",
2654                     file_tag, tpx_tag);
2655
2656             /* We only support reading tpx files with the same tag as the code
2657              * or tpx files with the release tag and with lower version number.
2658              */
2659             if (std::strcmp(file_tag, TPX_TAG_RELEASE) != 0 && fileVersion < tpx_version)
2660             {
2661                 gmx_fatal(FARGS, "tpx tag/version mismatch: reading tpx file (%s) version %d, tag '%s' with program for tpx version %d, tag '%s'",
2662                           gmx_fio_getname(fio), fileVersion, file_tag,
2663                           tpx_version, tpx_tag);
2664             }
2665         }
2666     }
2667
2668     if (fileVersionPointer)
2669     {
2670         *fileVersionPointer = fileVersion;
2671     }
2672     if (fileGenerationPointer)
2673     {
2674         *fileGenerationPointer = fileGeneration;
2675     }
2676
2677     if ((fileVersion <= tpx_incompatible_version) ||
2678         ((fileVersion > tpx_version) && !TopOnlyOK) ||
2679         (fileGeneration > tpx_generation) ||
2680         tpx_version == 80) /*80 was used by both 5.0-dev and 4.6-dev*/
2681     {
2682         gmx_fatal(FARGS, "reading tpx file (%s) version %d with version %d program",
2683                   gmx_fio_getname(fio), fileVersion, tpx_version);
2684     }
2685
2686     gmx_fio_do_int(fio, tpx->natoms);
2687     gmx_fio_do_int(fio, tpx->ngtc);
2688
2689     if (fileVersion < 62)
2690     {
2691         gmx_fio_do_int(fio, idum);
2692         gmx_fio_do_real(fio, rdum);
2693     }
2694     if (fileVersion >= 79)
2695     {
2696         gmx_fio_do_int(fio, tpx->fep_state);
2697     }
2698     gmx_fio_do_real(fio, tpx->lambda);
2699     gmx_fio_do_gmx_bool(fio, tpx->bIr);
2700     gmx_fio_do_gmx_bool(fio, tpx->bTop);
2701     gmx_fio_do_gmx_bool(fio, tpx->bX);
2702     gmx_fio_do_gmx_bool(fio, tpx->bV);
2703     gmx_fio_do_gmx_bool(fio, tpx->bF);
2704     gmx_fio_do_gmx_bool(fio, tpx->bBox);
2705
2706     if ((fileGeneration > tpx_generation))
2707     {
2708         /* This can only happen if TopOnlyOK=TRUE */
2709         tpx->bIr = FALSE;
2710     }
2711 }
2712
2713 static int do_tpx(t_fileio *fio, gmx_bool bRead,
2714                   t_inputrec *ir, t_state *state, rvec *x, rvec *v,
2715                   gmx_mtop_t *mtop)
2716 {
2717     t_tpxheader     tpx;
2718     gmx_bool        TopOnlyOK;
2719     int             ePBC;
2720     gmx_bool        bPeriodicMols;
2721
2722     if (!bRead)
2723     {
2724         GMX_RELEASE_ASSERT(state != nullptr, "Cannot write a null state");
2725         GMX_RELEASE_ASSERT(x == nullptr && v == nullptr, "Passing separate x and v pointers to do_tpx() is not supported when writing");
2726
2727         tpx.natoms    = state->natoms;
2728         tpx.ngtc      = state->ngtc;
2729         tpx.fep_state = state->fep_state;
2730         tpx.lambda    = state->lambda[efptFEP];
2731         tpx.bIr       = ir       != nullptr;
2732         tpx.bTop      = mtop     != nullptr;
2733         tpx.bX        = (state->flags & (1 << estX)) != 0;
2734         tpx.bV        = (state->flags & (1 << estV)) != 0;
2735         tpx.bF        = FALSE;
2736         tpx.bBox      = TRUE;
2737     }
2738     else
2739     {
2740         GMX_RELEASE_ASSERT(!(x == nullptr && v != nullptr), "Passing x==NULL and v!=NULL is not supported");
2741     }
2742
2743     TopOnlyOK = (ir == nullptr);
2744
2745     int fileVersion;    /* Version number of the code that wrote the file */
2746     int fileGeneration; /* Generation version number of the code that wrote the file */
2747     do_tpxheader(fio, bRead, &tpx, TopOnlyOK, &fileVersion, &fileGeneration);
2748
2749     if (bRead)
2750     {
2751         state->flags = 0;
2752         init_gtc_state(state, tpx.ngtc, 0, 0);
2753         if (x == nullptr)
2754         {
2755             // v is also nullptr by the above assertion, so we may
2756             // need to make memory in state for storing the contents
2757             // of the tpx file.
2758             if (tpx.bX)
2759             {
2760                 state->flags |= (1 << estX);
2761             }
2762             if (tpx.bV)
2763             {
2764                 state->flags |= (1 << estV);
2765             }
2766             state_change_natoms(state, tpx.natoms);
2767         }
2768     }
2769
2770     if (x == nullptr)
2771     {
2772         x = state->x.rvec_array();
2773         v = state->v.rvec_array();
2774     }
2775
2776 #define do_test(fio, b, p) if (bRead && ((p) != NULL) && !(b)) gmx_fatal(FARGS, "No %s in %s",#p, gmx_fio_getname(fio))
2777
2778     do_test(fio, tpx.bBox, state->box);
2779     if (tpx.bBox)
2780     {
2781         gmx_fio_ndo_rvec(fio, state->box, DIM);
2782         if (fileVersion >= 51)
2783         {
2784             gmx_fio_ndo_rvec(fio, state->box_rel, DIM);
2785         }
2786         else
2787         {
2788             /* We initialize box_rel after reading the inputrec */
2789             clear_mat(state->box_rel);
2790         }
2791         gmx_fio_ndo_rvec(fio, state->boxv, DIM);
2792         if (fileVersion < 56)
2793         {
2794             matrix mdum;
2795             gmx_fio_ndo_rvec(fio, mdum, DIM);
2796         }
2797     }
2798
2799     if (state->ngtc > 0)
2800     {
2801         real *dumv;
2802         snew(dumv, state->ngtc);
2803         if (fileVersion < 69)
2804         {
2805             gmx_fio_ndo_real(fio, dumv, state->ngtc);
2806         }
2807         /* These used to be the Berendsen tcoupl_lambda's */
2808         gmx_fio_ndo_real(fio, dumv, state->ngtc);
2809         sfree(dumv);
2810     }
2811
2812     do_test(fio, tpx.bTop, mtop);
2813     if (tpx.bTop)
2814     {
2815         if (mtop)
2816         {
2817             do_mtop(fio, mtop, bRead, fileVersion);
2818         }
2819         else
2820         {
2821             gmx_mtop_t dum_top;
2822             do_mtop(fio, &dum_top, bRead, fileVersion);
2823         }
2824     }
2825     do_test(fio, tpx.bX, x);
2826     if (tpx.bX)
2827     {
2828         if (bRead)
2829         {
2830             state->flags |= (1<<estX);
2831         }
2832         gmx_fio_ndo_rvec(fio, x, tpx.natoms);
2833     }
2834
2835     do_test(fio, tpx.bV, v);
2836     if (tpx.bV)
2837     {
2838         if (bRead)
2839         {
2840             state->flags |= (1<<estV);
2841         }
2842         gmx_fio_ndo_rvec(fio, v, tpx.natoms);
2843     }
2844
2845     // No need to run do_test when the last argument is NULL
2846     if (tpx.bF)
2847     {
2848         rvec *dummyForces;
2849         snew(dummyForces, state->natoms);
2850         gmx_fio_ndo_rvec(fio, dummyForces, tpx.natoms);
2851         sfree(dummyForces);
2852     }
2853
2854     /* Starting with tpx version 26, we have the inputrec
2855      * at the end of the file, so we can ignore it
2856      * if the file is never than the software (but still the
2857      * same generation - see comments at the top of this file.
2858      *
2859      *
2860      */
2861     ePBC          = -1;
2862     bPeriodicMols = FALSE;
2863
2864     do_test(fio, tpx.bIr, ir);
2865     if (tpx.bIr)
2866     {
2867         if (fileVersion >= 53)
2868         {
2869             /* Removed the pbc info from do_inputrec, since we always want it */
2870             if (!bRead)
2871             {
2872                 ePBC          = ir->ePBC;
2873                 bPeriodicMols = ir->bPeriodicMols;
2874             }
2875             gmx_fio_do_int(fio, ePBC);
2876             gmx_fio_do_gmx_bool(fio, bPeriodicMols);
2877         }
2878         if (fileGeneration <= tpx_generation && ir)
2879         {
2880             do_inputrec(fio, ir, bRead, fileVersion);
2881             if (fileVersion < 51)
2882             {
2883                 set_box_rel(ir, state);
2884             }
2885             if (fileVersion < 53)
2886             {
2887                 ePBC          = ir->ePBC;
2888                 bPeriodicMols = ir->bPeriodicMols;
2889             }
2890         }
2891         if (bRead && ir && fileVersion >= 53)
2892         {
2893             /* We need to do this after do_inputrec, since that initializes ir */
2894             ir->ePBC          = ePBC;
2895             ir->bPeriodicMols = bPeriodicMols;
2896         }
2897     }
2898
2899     if (bRead)
2900     {
2901         if (tpx.bIr && ir)
2902         {
2903             if (state->ngtc == 0)
2904             {
2905                 /* Reading old version without tcoupl state data: set it */
2906                 init_gtc_state(state, ir->opts.ngtc, 0, ir->opts.nhchainlength);
2907             }
2908             if (tpx.bTop && mtop)
2909             {
2910                 if (fileVersion < 57)
2911                 {
2912                     if (mtop->moltype[0].ilist[F_DISRES].size() > 0)
2913                     {
2914                         ir->eDisre = edrSimple;
2915                     }
2916                     else
2917                     {
2918                         ir->eDisre = edrNone;
2919                     }
2920                 }
2921                 set_disres_npair(mtop);
2922             }
2923         }
2924
2925         if (tpx.bTop && mtop)
2926         {
2927             gmx_mtop_finalize(mtop);
2928         }
2929     }
2930
2931     return ePBC;
2932 }
2933
2934 static t_fileio *open_tpx(const char *fn, const char *mode)
2935 {
2936     return gmx_fio_open(fn, mode);
2937 }
2938
2939 static void close_tpx(t_fileio *fio)
2940 {
2941     gmx_fio_close(fio);
2942 }
2943
2944 /************************************************************
2945  *
2946  *  The following routines are the exported ones
2947  *
2948  ************************************************************/
2949
2950 void read_tpxheader(const char *fn, t_tpxheader *tpx, gmx_bool TopOnlyOK)
2951 {
2952     t_fileio *fio;
2953
2954     fio = open_tpx(fn, "r");
2955     do_tpxheader(fio, TRUE, tpx, TopOnlyOK, nullptr, nullptr);
2956     close_tpx(fio);
2957 }
2958
2959 void write_tpx_state(const char *fn,
2960                      const t_inputrec *ir, const t_state *state, const gmx_mtop_t *mtop)
2961 {
2962     t_fileio *fio;
2963
2964     fio = open_tpx(fn, "w");
2965     do_tpx(fio, FALSE,
2966            const_cast<t_inputrec *>(ir),
2967            const_cast<t_state *>(state), nullptr, nullptr,
2968            const_cast<gmx_mtop_t *>(mtop));
2969     close_tpx(fio);
2970 }
2971
2972 void read_tpx_state(const char *fn,
2973                     t_inputrec *ir, t_state *state, gmx_mtop_t *mtop)
2974 {
2975     t_fileio *fio;
2976
2977     fio = open_tpx(fn, "r");
2978     do_tpx(fio, TRUE, ir, state, nullptr, nullptr, mtop);
2979     close_tpx(fio);
2980 }
2981
2982 int read_tpx(const char *fn,
2983              t_inputrec *ir, matrix box, int *natoms,
2984              rvec *x, rvec *v, gmx_mtop_t *mtop)
2985 {
2986     t_fileio *fio;
2987     t_state   state;
2988     int       ePBC;
2989
2990     fio     = open_tpx(fn, "r");
2991     ePBC    = do_tpx(fio, TRUE, ir, &state, x, v, mtop);
2992     close_tpx(fio);
2993     *natoms = mtop->natoms;
2994     if (box)
2995     {
2996         copy_mat(state.box, box);
2997     }
2998
2999     return ePBC;
3000 }
3001
3002 int read_tpx_top(const char *fn,
3003                  t_inputrec *ir, matrix box, int *natoms,
3004                  rvec *x, rvec *v, t_topology *top)
3005 {
3006     gmx_mtop_t  mtop;
3007     int         ePBC;
3008
3009     ePBC = read_tpx(fn, ir, box, natoms, x, v, &mtop);
3010
3011     *top = gmx_mtop_t_to_t_topology(&mtop, true);
3012
3013     return ePBC;
3014 }
3015
3016 gmx_bool fn2bTPX(const char *file)
3017 {
3018     return (efTPR == fn2ftp(file));
3019 }
3020
3021 void pr_tpxheader(FILE *fp, int indent, const char *title, const t_tpxheader *sh)
3022 {
3023     if (available(fp, sh, indent, title))
3024     {
3025         indent = pr_title(fp, indent, title);
3026         pr_indent(fp, indent);
3027         fprintf(fp, "bIr    = %spresent\n", sh->bIr ? "" : "not ");
3028         pr_indent(fp, indent);
3029         fprintf(fp, "bBox   = %spresent\n", sh->bBox ? "" : "not ");
3030         pr_indent(fp, indent);
3031         fprintf(fp, "bTop   = %spresent\n", sh->bTop ? "" : "not ");
3032         pr_indent(fp, indent);
3033         fprintf(fp, "bX     = %spresent\n", sh->bX ? "" : "not ");
3034         pr_indent(fp, indent);
3035         fprintf(fp, "bV     = %spresent\n", sh->bV ? "" : "not ");
3036         pr_indent(fp, indent);
3037         fprintf(fp, "bF     = %spresent\n", sh->bF ? "" : "not ");
3038
3039         pr_indent(fp, indent);
3040         fprintf(fp, "natoms = %d\n", sh->natoms);
3041         pr_indent(fp, indent);
3042         fprintf(fp, "lambda = %e\n", sh->lambda);
3043     }
3044 }