Merge release-5-0 into master
[alexxy/gromacs.git] / src / gromacs / gmxlib / checkpoint.cpp
similarity index 91%
rename from src/gromacs/gmxlib/checkpoint.c
rename to src/gromacs/gmxlib/checkpoint.cpp
index 28b4dd8d7151be748d9d44c00ef9e4a70bac2b14..607f94974a2caa82ae7c2e59b4b7e990cda42c75 100644 (file)
 
 /* The source code in this file should be thread-safe.
    Please keep it that way. */
+#include "gmxpre.h"
 
+#include "gromacs/legacyheaders/checkpoint.h"
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#include "config.h"
 
+#include <errno.h>
+#include <stdlib.h>
 #include <string.h>
-#include <time.h>
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
 
+#include <fcntl.h>
 #ifdef GMX_NATIVE_WINDOWS
-/* _chsize_s */
 #include <io.h>
 #include <sys/locking.h>
 #endif
 
-#include "copyrite.h"
-#include "names.h"
-#include "typedefs.h"
-#include "types/commrec.h"
-#include "gromacs/utility/smalloc.h"
-#include "txtdump.h"
-#include "vec.h"
-#include "network.h"
-#include "checkpoint.h"
-#include "main.h"
-#include "gromacs/utility/cstringutil.h"
-#include <fcntl.h>
-
+#include "buildinfo.h"
 #include "gromacs/fileio/filenm.h"
-#include "gromacs/fileio/futil.h"
 #include "gromacs/fileio/gmxfio.h"
-#include "gromacs/fileio/xdrf.h"
 #include "gromacs/fileio/xdr_datatype.h"
+#include "gromacs/fileio/xdrf.h"
+#include "gromacs/legacyheaders/copyrite.h"
+#include "gromacs/legacyheaders/names.h"
+#include "gromacs/legacyheaders/network.h"
+#include "gromacs/legacyheaders/txtdump.h"
+#include "gromacs/legacyheaders/typedefs.h"
+#include "gromacs/legacyheaders/types/commrec.h"
+#include "gromacs/math/vec.h"
 #include "gromacs/utility/baseversion.h"
-#include "gmx_fatal.h"
-
-#include "buildinfo.h"
+#include "gromacs/utility/cstringutil.h"
+#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/futil.h"
+#include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/sysinfo.h"
 
 #ifdef GMX_FAHCORE
 #include "corewrap.h"
@@ -159,34 +148,6 @@ const char *edfh_names[edfhNR] =
     "accumulated_plus", "accumulated_minus", "accumulated_plus_2",  "accumulated_minus_2", "Tij", "Tij_empirical"
 };
 
-#ifdef GMX_NATIVE_WINDOWS
-static int
-gmx_wintruncate(const char *filename, __int64 size)
-{
-#ifdef GMX_FAHCORE
-    /*we do this elsewhere*/
-    return 0;
-#else
-    FILE *fp;
-    int   rc;
-
-    fp = fopen(filename, "rb+");
-
-    if (fp == NULL)
-    {
-        return -1;
-    }
-
-#ifdef _MSC_VER
-    return _chsize_s( fileno(fp), size);
-#else
-    return _chsize( fileno(fp), size);
-#endif
-#endif
-}
-#endif
-
-
 enum {
     ecprREAL, ecprRVEC, ecprMATRIX
 };
@@ -467,6 +428,8 @@ static int do_cpte_reals_low(XDR *xd, int cptp, int ecpt, int sflags,
     {
         if (dtc == xdr_datatype_double)
         {
+            /* cppcheck-suppress invalidPointerCast
+             * Only executed if real is anyhow double */
             vd = (double *)vp;
         }
         else
@@ -535,8 +498,6 @@ static int do_cpte_n_reals(XDR *xd, int cptp, int ecpt, int sflags,
 static int do_cpte_real(XDR *xd, int cptp, int ecpt, int sflags,
                         real *r, FILE *list)
 {
-    int n;
-
     return do_cpte_reals_low(xd, cptp, ecpt, sflags, 1, NULL, &r, list, ecprREAL);
 }
 
@@ -546,7 +507,7 @@ static int do_cpte_ints(XDR *xd, int cptp, int ecpt, int sflags,
     bool_t res = 0;
     int    dtc = xdr_datatype_int;
     int   *vp, *va = NULL;
-    int    nf, dt, i;
+    int    nf, dt;
 
     nf  = n;
     res = xdr_int(xd, &nf);
@@ -613,7 +574,7 @@ static int do_cpte_doubles(XDR *xd, int cptp, int ecpt, int sflags,
     bool_t  res = 0;
     int     dtc = xdr_datatype_double;
     double *vp, *va = NULL;
-    int     nf, dt, i;
+    int     nf, dt;
 
     nf  = n;
     res = xdr_int(xd, &nf);
@@ -678,8 +639,6 @@ static int do_cpte_double(XDR *xd, int cptp, int ecpt, int sflags,
 static int do_cpte_rvecs(XDR *xd, int cptp, int ecpt, int sflags,
                          int n, rvec **v, FILE *list)
 {
-    int n3;
-
     return do_cpte_reals_low(xd, cptp, ecpt, sflags,
                              n*DIM, NULL, (real **)v, list, ecprRVEC);
 }
@@ -688,7 +647,7 @@ static int do_cpte_matrix(XDR *xd, int cptp, int ecpt, int sflags,
                           matrix v, FILE *list)
 {
     real *vr;
-    real  ret;
+    int   ret;
 
     vr  = (real *)&(v[0][0]);
     ret = do_cpte_reals_low(xd, cptp, ecpt, sflags,
@@ -707,8 +666,7 @@ static int do_cpte_nmatrix(XDR *xd, int cptp, int ecpt, int sflags,
                            int n, real **v, FILE *list)
 {
     int   i;
-    real *vr;
-    real  ret, reti;
+    int   ret, reti;
     char  name[CPTSTRLEN];
 
     ret = 0;
@@ -718,17 +676,15 @@ static int do_cpte_nmatrix(XDR *xd, int cptp, int ecpt, int sflags,
     }
     for (i = 0; i < n; i++)
     {
-        reti = 0;
-        vr   = v[i];
         reti = do_cpte_reals_low(xd, cptp, ecpt, sflags, n, NULL, &(v[i]), NULL, ecprREAL);
         if (list && reti == 0)
         {
             sprintf(name, "%s[%d]", st_names(cptp, ecpt), i);
             pr_reals(list, 0, name, v[i], n);
         }
-        if (reti == 0)
+        if (reti != 0)
         {
-            ret = 0;
+            ret = reti;
         }
     }
     return ret;
@@ -822,7 +778,6 @@ static void do_cpt_header(XDR *xd, gmx_bool bRead, int *file_version,
     bool_t res = 0;
     int    magic;
     int    idum = 0;
-    int    i;
     char  *fhost;
 
     if (bRead)
@@ -1283,7 +1238,6 @@ static int do_cpt_enerhist(XDR *xd, gmx_bool bRead,
         {
             enerhist->ener_sum_sim[i] = enerhist->ener_sum[i];
         }
-        fflags |= (1<<eenhENERGY_SUM_SIM);
     }
 
     if ( (fflags & (1<<eenhENERGY_NSUM)) &&
@@ -1291,14 +1245,12 @@ static int do_cpt_enerhist(XDR *xd, gmx_bool bRead,
     {
         /* Assume we have an old file format and copy nsum to nsteps */
         enerhist->nsteps = enerhist->nsum;
-        fflags          |= (1<<eenhENERGY_NSTEPS);
     }
     if ( (fflags & (1<<eenhENERGY_NSUM_SIM)) &&
          !(fflags & (1<<eenhENERGY_NSTEPS_SIM)))
     {
         /* Assume we have an old file format and copy nsum to nsteps */
         enerhist->nsteps_sim = enerhist->nsum_sim;
-        fflags              |= (1<<eenhENERGY_NSTEPS_SIM);
     }
 
     return ret;
@@ -1350,7 +1302,7 @@ static int do_cpt_df_hist(XDR *xd, int fflags, df_history_t *dfhist, FILE *list)
 static int do_cpt_EDstate(XDR *xd, gmx_bool bRead,
                           edsamstate_t *EDstate, FILE *list)
 {
-    int  i, j;
+    int  i;
     int  ret = 0;
     char buf[STRLEN];
 
@@ -1412,7 +1364,7 @@ static int do_cpt_files(XDR *xd, gmx_bool bRead,
                         gmx_file_position_t **p_outputfiles, int *nfiles,
                         FILE *list, int file_version)
 {
-    int                  i, j;
+    int                  i;
     gmx_off_t            offset;
     gmx_off_t            mask = 0xFFFFFFFFL;
     int                  offset_high, offset_low;
@@ -1514,14 +1466,13 @@ void write_checkpoint(const char *fn, gmx_bool bNumberAndKeep,
     int                  double_prec;
     char                *fprog;
     char                *fntemp; /* the temporary checkpoint file name */
-    time_t               now;
     char                 timebuf[STRLEN];
-    int                  nppnodes, npmenodes, flag_64bit;
+    int                  nppnodes, npmenodes;
     char                 buf[1024], suffix[5+STEPSTRSIZE], sbuf[STEPSTRSIZE];
     gmx_file_position_t *outputfiles;
     int                  noutputfiles;
     char                *ftime;
-    int                  flags_eks, flags_enh, flags_dfh, i;
+    int                  flags_eks, flags_enh, flags_dfh;
     t_fileio            *ret;
 
     if (DOMAINDECOMP(cr))
@@ -1550,8 +1501,7 @@ void write_checkpoint(const char *fn, gmx_bool bNumberAndKeep,
     snew(fntemp, strlen(fn));
     strcpy(fntemp, fn);
 #endif
-    time(&now);
-    gmx_ctime_r(&now, timebuf, STRLEN);
+    gmx_format_current_time(timebuf, STRLEN);
 
     if (fplog)
     {
@@ -1807,9 +1757,10 @@ static void check_match(FILE *fplog,
          */
         int   gmx_major, gmx_minor;
         int   cpt_major, cpt_minor;
-        sscanf(gmx_version(), "VERSION %d.%d", &gmx_major, &gmx_minor);
-        sscanf(version, "VERSION %d.%d", &cpt_major, &cpt_minor);
-        version_differs = (gmx_major != cpt_major || gmx_minor != cpt_minor);
+        sscanf(gmx_version(), "VERSION %5d.%5d", &gmx_major, &gmx_minor);
+        int   ret = sscanf(version, "VERSION %5d.%5d", &cpt_major, &cpt_minor);
+        version_differs = (ret < 2 || gmx_major != cpt_major ||
+                           gmx_minor != cpt_minor);
     }
 
     check_string(fplog, "Build time", BUILD_TIME, btime, &mm);
@@ -1839,8 +1790,8 @@ static void check_match(FILE *fplog,
     if (mm)
     {
         const char msg_version_difference[] =
-            "The current Gromacs major & minor version are not identical to those that\n"
-            "generated the checkpoint file. In principle Gromacs does not support\n"
+            "The current GROMACS major & minor version are not identical to those that\n"
+            "generated the checkpoint file. In principle GROMACS does not support\n"
             "continuation from checkpoints between different versions, so we advise\n"
             "against this. If you still want to try your luck we recommend that you use\n"
             "the -noappend flag to keep your output files from the two versions separate.\n"
@@ -1848,7 +1799,7 @@ static void check_match(FILE *fplog,
             "file have changed between the different major & minor versions.\n";
 
         const char msg_mismatch_notice[] =
-            "Gromacs patchlevel, binary or parallel settings differ from previous run.\n"
+            "GROMACS patchlevel, binary or parallel settings differ from previous run.\n"
             "Continuation is exact, but not guaranteed to be binary identical.\n";
 
         const char msg_logdetails[] =
@@ -1887,8 +1838,8 @@ static void read_checkpoint(const char *fn, FILE **pfplog,
     int                  file_version;
     char                *version, *btime, *buser, *bhost, *fprog, *ftime;
     int                  double_prec;
-    char                 filename[STRLEN], buf[STEPSTRSIZE];
-    int                  nppnodes, eIntegrator_f, nppnodes_f, npmenodes_f;
+    char                 buf[STEPSTRSIZE];
+    int                  eIntegrator_f, nppnodes_f, npmenodes_f;
     ivec                 dd_nc_f;
     int                  natoms, ngtc, nnhpres, nhchainlength, nlambda, fflags, flags_eks, flags_enh, flags_dfh;
     int                  d;
@@ -1995,7 +1946,6 @@ static void read_checkpoint(const char *fn, FILE **pfplog,
 
     if (!PAR(cr))
     {
-        nppnodes      = 1;
         cr->npmenodes = 0;
     }
     else if (cr->nnodes == nppnodes_f + npmenodes_f)
@@ -2004,7 +1954,7 @@ static void read_checkpoint(const char *fn, FILE **pfplog,
         {
             cr->npmenodes = npmenodes_f;
         }
-        nppnodes = cr->nnodes - cr->npmenodes;
+        int nppnodes = cr->nnodes - cr->npmenodes;
         if (nppnodes == nppnodes_f)
         {
             for (d = 0; d < DIM; d++)
@@ -2016,11 +1966,6 @@ static void read_checkpoint(const char *fn, FILE **pfplog,
             }
         }
     }
-    else
-    {
-        /* The number of PP nodes has not been set yet */
-        nppnodes = -1;
-    }
 
     if (fflags != state->flags)
     {
@@ -2263,15 +2208,14 @@ static void read_checkpoint(const char *fn, FILE **pfplog,
 
             if (i != 0) /*log file is already seeked to correct position */
             {
-#ifdef GMX_NATIVE_WINDOWS
-                rc = gmx_wintruncate(outputfiles[i].filename, outputfiles[i].offset);
-#else
-                rc = truncate(outputfiles[i].filename, outputfiles[i].offset);
-#endif
+#if !defined(GMX_NATIVE_WINDOWS) || !defined(GMX_FAHCORE)
+                /* For FAHCORE, we do this elsewhere*/
+                rc = gmx_truncate(outputfiles[i].filename, outputfiles[i].offset);
                 if (rc != 0)
                 {
                     gmx_fatal(FARGS, "Truncation of file %s failed. Cannot do appending because of this failure.", outputfiles[i].filename);
                 }
+#endif
             }
         }
     }
@@ -2313,6 +2257,44 @@ void load_checkpoint(const char *fn, FILE **fplog,
     ir->simulation_part += 1;
 }
 
+void read_checkpoint_part_and_step(const char  *filename,
+                                   int         *simulation_part,
+                                   gmx_int64_t *step)
+{
+    int       file_version;
+    char     *version, *btime, *buser, *bhost, *fprog, *ftime;
+    int       double_prec;
+    int       eIntegrator;
+    int       nppnodes, npme;
+    ivec      dd_nc;
+    int       flags_eks, flags_enh, flags_dfh;
+    double    t;
+    t_state   state;
+    t_fileio *fp;
+
+    if (filename == NULL ||
+        !gmx_fexist(filename) ||
+        (!(fp = gmx_fio_open(filename, "r"))))
+    {
+        *simulation_part = 0;
+        *step            = 0;
+        return;
+    }
+
+    /* Not calling initializing state before use is nasty, but all we
+       do is read into its member variables and throw the struct away
+       again immediately. */
+
+    do_cpt_header(gmx_fio_getxdr(fp), TRUE, &file_version,
+                  &version, &btime, &buser, &bhost, &double_prec, &fprog, &ftime,
+                  &eIntegrator, simulation_part, step, &t, &nppnodes, dd_nc, &npme,
+                  &state.natoms, &state.ngtc, &state.nnhpres, &state.nhchainlength,
+                  &(state.dfhist.nlambda), &state.flags, &flags_eks, &flags_enh, &flags_dfh,
+                  &state.edsamstate.nED, &state.swapstate.eSwapCoords, NULL);
+
+    gmx_fio_close(fp);
+}
+
 static void read_checkpoint_data(t_fileio *fp, int *simulation_part,
                                  gmx_int64_t *step, double *t, t_state *state,
                                  int *nfiles, gmx_file_position_t **outputfiles)
@@ -2469,8 +2451,6 @@ void list_checkpoint(const char *fn, FILE *out)
     ivec                 dd_nc;
     t_state              state;
     int                  flags_eks, flags_enh, flags_dfh;
-    int                  indent;
-    int                  i, j;
     int                  ret;
     gmx_file_position_t *outputfiles;
     int                  nfiles;
@@ -2536,149 +2516,24 @@ void list_checkpoint(const char *fn, FILE *out)
     done_state(&state);
 }
 
-
-static gmx_bool exist_output_file(const char *fnm_cp, int nfile, const t_filenm fnm[])
-{
-    int i;
-
-    /* Check if the output file name stored in the checkpoint file
-     * is one of the output file names of mdrun.
-     */
-    i = 0;
-    while (i < nfile &&
-           !(is_output(&fnm[i]) && strcmp(fnm_cp, fnm[i].fns[0]) == 0))
-    {
-        i++;
-    }
-
-    return (i < nfile && gmx_fexist(fnm_cp));
-}
-
 /* This routine cannot print tons of data, since it is called before the log file is opened. */
-gmx_bool read_checkpoint_simulation_part(const char *filename, int *simulation_part,
-                                         gmx_int64_t *cpt_step, t_commrec *cr,
-                                         gmx_bool bAppendReq,
-                                         int nfile, const t_filenm fnm[],
-                                         const char *part_suffix, gmx_bool *bAddPart)
+void
+read_checkpoint_simulation_part_and_filenames(t_fileio             *fp,
+                                              int                  *simulation_part,
+                                              int                  *nfiles,
+                                              gmx_file_position_t **outputfiles)
 {
-    t_fileio            *fp;
-    gmx_int64_t          step = 0;
-    double               t;
-    /* This next line is nasty because the sub-structures of t_state
-     * cannot be assumed to be zeroed (or even initialized in ways the
-     * rest of the code might assume). Using snew would be better, but
-     * this will all go away for 5.0. */
-    t_state              state;
-    int                  nfiles;
-    gmx_file_position_t *outputfiles;
-    int                  nexist, f;
-    gmx_bool             bAppend;
-    char                *fn, suf_up[STRLEN];
-
-    bAppend = FALSE;
-
-    if (SIMMASTER(cr))
-    {
-        if (!gmx_fexist(filename) || (!(fp = gmx_fio_open(filename, "r")) ))
-        {
-            *simulation_part = 0;
-        }
-        else
-        {
-            init_state(&state, 0, 0, 0, 0, 0);
-
-            read_checkpoint_data(fp, simulation_part, &step, &t, &state,
-                                 &nfiles, &outputfiles);
-            if (gmx_fio_close(fp) != 0)
-            {
-                gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
-            }
-            done_state(&state);
-
-            if (bAppendReq)
-            {
-                nexist = 0;
-                for (f = 0; f < nfiles; f++)
-                {
-                    if (exist_output_file(outputfiles[f].filename, nfile, fnm))
-                    {
-                        nexist++;
-                    }
-                }
-                if (nexist == nfiles)
-                {
-                    bAppend = bAppendReq;
-                }
-                else if (nexist > 0)
-                {
-                    fprintf(stderr,
-                            "Output file appending has been requested,\n"
-                            "but some output files listed in the checkpoint file %s\n"
-                            "are not present or are named differently by the current program:\n",
-                            filename);
-                    fprintf(stderr, "output files present:");
-                    for (f = 0; f < nfiles; f++)
-                    {
-                        if (exist_output_file(outputfiles[f].filename,
-                                              nfile, fnm))
-                        {
-                            fprintf(stderr, " %s", outputfiles[f].filename);
-                        }
-                    }
-                    fprintf(stderr, "\n");
-                    fprintf(stderr, "output files not present or named differently:");
-                    for (f = 0; f < nfiles; f++)
-                    {
-                        if (!exist_output_file(outputfiles[f].filename,
-                                               nfile, fnm))
-                        {
-                            fprintf(stderr, " %s", outputfiles[f].filename);
-                        }
-                    }
-                    fprintf(stderr, "\n");
-
-                    gmx_fatal(FARGS, "File appending requested, but %d of the %d output files are not present or are named differently", nfiles-nexist, nfiles);
-                }
-            }
+    gmx_int64_t step = 0;
+    double      t;
+    t_state     state;
 
-            if (bAppend)
-            {
-                if (nfiles == 0)
-                {
-                    gmx_fatal(FARGS, "File appending requested, but no output file information is stored in the checkpoint file");
-                }
-                fn = outputfiles[0].filename;
-                if (strlen(fn) < 4 ||
-                    gmx_strcasecmp(fn+strlen(fn)-4, ftp2ext(efLOG)) == 0)
-                {
-                    gmx_fatal(FARGS, "File appending requested, but the log file is not the first file listed in the checkpoint file");
-                }
-                /* Set bAddPart to whether the suffix string '.part' is present
-                 * in the log file name.
-                 */
-                strcpy(suf_up, part_suffix);
-                upstring(suf_up);
-                *bAddPart = (strstr(fn, part_suffix) != NULL ||
-                             strstr(fn, suf_up) != NULL);
-            }
-
-            sfree(outputfiles);
-        }
-    }
-    if (PAR(cr))
-    {
-        gmx_bcast(sizeof(*simulation_part), simulation_part, cr);
+    init_state(&state, 0, 0, 0, 0, 0);
 
-        if (*simulation_part > 0 && bAppendReq)
-        {
-            gmx_bcast(sizeof(bAppend), &bAppend, cr);
-            gmx_bcast(sizeof(*bAddPart), bAddPart, cr);
-        }
-    }
-    if (NULL != cpt_step)
+    read_checkpoint_data(fp, simulation_part, &step, &t, &state,
+                         nfiles, outputfiles);
+    if (gmx_fio_close(fp) != 0)
     {
-        *cpt_step = step;
+        gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
     }
-
-    return bAppend;
+    done_state(&state);
 }