Remove read_checkpoint_state
[gromacs.git] / src / gromacs / fileio / checkpoint.cpp
blobf34a9950721dcf128232dacb2b07f66c09f8a50c
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
36 /* The source code in this file should be thread-safe.
37 Please keep it that way. */
38 #include "gmxpre.h"
40 #include "checkpoint.h"
42 #include "config.h"
44 #include <cerrno>
45 #include <cstdlib>
46 #include <cstring>
48 #include <fcntl.h>
49 #if GMX_NATIVE_WINDOWS
50 #include <io.h>
51 #include <sys/locking.h>
52 #endif
54 #include "buildinfo.h"
55 #include "gromacs/fileio/filetypes.h"
56 #include "gromacs/fileio/gmxfio.h"
57 #include "gromacs/fileio/gmxfio-xdr.h"
58 #include "gromacs/fileio/xdr_datatype.h"
59 #include "gromacs/fileio/xdrf.h"
60 #include "gromacs/gmxlib/network.h"
61 #include "gromacs/math/vec.h"
62 #include "gromacs/math/vecdump.h"
63 #include "gromacs/math/vectypes.h"
64 #include "gromacs/mdtypes/awh-correlation-history.h"
65 #include "gromacs/mdtypes/awh-history.h"
66 #include "gromacs/mdtypes/commrec.h"
67 #include "gromacs/mdtypes/df_history.h"
68 #include "gromacs/mdtypes/edsamhistory.h"
69 #include "gromacs/mdtypes/energyhistory.h"
70 #include "gromacs/mdtypes/inputrec.h"
71 #include "gromacs/mdtypes/md_enums.h"
72 #include "gromacs/mdtypes/observableshistory.h"
73 #include "gromacs/mdtypes/state.h"
74 #include "gromacs/mdtypes/swaphistory.h"
75 #include "gromacs/trajectory/trajectoryframe.h"
76 #include "gromacs/utility/arrayref.h"
77 #include "gromacs/utility/baseversion.h"
78 #include "gromacs/utility/cstringutil.h"
79 #include "gromacs/utility/fatalerror.h"
80 #include "gromacs/utility/futil.h"
81 #include "gromacs/utility/gmxassert.h"
82 #include "gromacs/utility/int64_to_int.h"
83 #include "gromacs/utility/programcontext.h"
84 #include "gromacs/utility/smalloc.h"
85 #include "gromacs/utility/sysinfo.h"
86 #include "gromacs/utility/txtdump.h"
88 #ifdef GMX_FAHCORE
89 #include "corewrap.h"
90 #endif
92 #define CPT_MAGIC1 171817
93 #define CPT_MAGIC2 171819
94 #define CPTSTRLEN 1024
96 /* cpt_version should normally only be changed
97 * when the header or footer format changes.
98 * The state data format itself is backward and forward compatible.
99 * But old code can not read a new entry that is present in the file
100 * (but can read a new format when new entries are not present).
102 static const int cpt_version = 17;
105 const char *est_names[estNR] =
107 "FE-lambda",
108 "box", "box-rel", "box-v", "pres_prev",
109 "nosehoover-xi", "thermostat-integral",
110 "x", "v", "sdx-unsupported", "CGp", "LD-rng-unsupported", "LD-rng-i-unsupported",
111 "disre_initf", "disre_rm3tav",
112 "orire_initf", "orire_Dtav",
113 "svir_prev", "nosehoover-vxi", "v_eta", "vol0", "nhpres_xi", "nhpres_vxi", "fvir_prev", "fep_state", "MC-rng-unsupported", "MC-rng-i-unsupported"
114 "barostat-integral"
117 enum {
118 eeksEKIN_N, eeksEKINH, eeksDEKINDL, eeksMVCOS, eeksEKINF, eeksEKINO, eeksEKINSCALEF, eeksEKINSCALEH, eeksVSCALE, eeksEKINTOTAL, eeksNR
121 const char *eeks_names[eeksNR] =
123 "Ekin_n", "Ekinh", "dEkindlambda", "mv_cos",
124 "Ekinf", "Ekinh_old", "EkinScaleF_NHC", "EkinScaleH_NHC", "Vscale_NHC", "Ekin_Total"
127 enum {
128 eenhENERGY_N, eenhENERGY_AVER, eenhENERGY_SUM, eenhENERGY_NSUM,
129 eenhENERGY_SUM_SIM, eenhENERGY_NSUM_SIM,
130 eenhENERGY_NSTEPS, eenhENERGY_NSTEPS_SIM,
131 eenhENERGY_DELTA_H_NN,
132 eenhENERGY_DELTA_H_LIST,
133 eenhENERGY_DELTA_H_STARTTIME,
134 eenhENERGY_DELTA_H_STARTLAMBDA,
135 eenhNR
138 const char *eenh_names[eenhNR] =
140 "energy_n", "energy_aver", "energy_sum", "energy_nsum",
141 "energy_sum_sim", "energy_nsum_sim",
142 "energy_nsteps", "energy_nsteps_sim",
143 "energy_delta_h_nn",
144 "energy_delta_h_list",
145 "energy_delta_h_start_time",
146 "energy_delta_h_start_lambda"
149 /* free energy history variables -- need to be preserved over checkpoint */
150 enum {
151 edfhBEQUIL, edfhNATLAMBDA, edfhWLHISTO, edfhWLDELTA, edfhSUMWEIGHTS, edfhSUMDG, edfhSUMMINVAR, edfhSUMVAR,
152 edfhACCUMP, edfhACCUMM, edfhACCUMP2, edfhACCUMM2, edfhTIJ, edfhTIJEMP, edfhNR
154 /* free energy history variable names */
155 const char *edfh_names[edfhNR] =
157 "bEquilibrated", "N_at_state", "Wang-Landau Histogram", "Wang-Landau Delta", "Weights", "Free Energies", "minvar", "variance",
158 "accumulated_plus", "accumulated_minus", "accumulated_plus_2", "accumulated_minus_2", "Tij", "Tij_empirical"
161 /* AWH biasing history variables */
162 enum {
163 eawhhIN_INITIAL,
164 eawhhEQUILIBRATEHISTOGRAM,
165 eawhhHISTSIZE,
166 eawhhNPOINTS,
167 eawhhCOORDPOINT, eawhhUMBRELLAGRIDPOINT,
168 eawhhUPDATELIST,
169 eawhhLOGSCALEDSAMPLEWEIGHT,
170 eawhhNUMUPDATES,
171 eawhhFORCECORRELATIONGRID,
172 eawhhNR
175 const char *eawhh_names[eawhhNR] =
177 "awh_in_initial",
178 "awh_equilibrateHistogram",
179 "awh_histsize",
180 "awh_npoints",
181 "awh_coordpoint", "awh_umbrellaGridpoint",
182 "awh_updatelist",
183 "awh_logScaledSampleWeight",
184 "awh_numupdates"
185 "awh_forceCorrelationGrid"
188 //! Higher level vector element type, only used for formatting checkpoint dumps
189 enum class CptElementType
191 integer, //!< integer
192 real, //!< float or double, not linked to precision of type real
193 real3, //!< float[3] or double[3], not linked to precision of type real
194 matrix3x3 //!< float[3][3] or double[3][3], not linked to precision of type real
197 //! \brief Parts of the checkpoint state, only used for reporting
198 enum class StatePart
200 microState, //!< The microstate of the simulated system
201 kineticEnergy, //!< Kinetic energy, needed for T/P-coupling state
202 energyHistory, //!< Energy observable statistics
203 freeEnergyHistory, //!< Free-energy state and observable statistics
204 accWeightHistogram //!< Accelerated weight histogram method state
207 //! \brief Return the name of a checkpoint entry based on part and part entry
208 static const char *entryName(StatePart part, int ecpt)
210 switch (part)
212 case StatePart::microState: return est_names [ecpt];
213 case StatePart::kineticEnergy: return eeks_names[ecpt];
214 case StatePart::energyHistory: return eenh_names[ecpt];
215 case StatePart::freeEnergyHistory: return edfh_names[ecpt];
216 case StatePart::accWeightHistogram: return eawhh_names[ecpt];
219 return nullptr;
222 static void cp_warning(FILE *fp)
224 fprintf(fp, "\nWARNING: Checkpoint file is corrupted or truncated\n\n");
227 static void cp_error()
229 gmx_fatal(FARGS, "Checkpoint file corrupted/truncated, or maybe you are out of disk space?");
232 static void do_cpt_string_err(XDR *xd, gmx_bool bRead, const char *desc, char **s, FILE *list)
234 if (bRead)
236 snew(*s, CPTSTRLEN);
238 if (xdr_string(xd, s, CPTSTRLEN) == 0)
240 cp_error();
242 if (list)
244 fprintf(list, "%s = %s\n", desc, *s);
245 sfree(*s);
249 static int do_cpt_int(XDR *xd, const char *desc, int *i, FILE *list)
251 if (xdr_int(xd, i) == 0)
253 return -1;
255 if (list)
257 fprintf(list, "%s = %d\n", desc, *i);
259 return 0;
262 static int do_cpt_u_chars(XDR *xd, const char *desc, int n, unsigned char *i, FILE *list)
264 if (list)
266 fprintf(list, "%s = ", desc);
268 bool_t res = 1;
269 for (int j = 0; j < n && res; j++)
271 res &= xdr_u_char(xd, &i[j]);
272 if (list)
274 fprintf(list, "%02x", i[j]);
277 if (list)
279 fprintf(list, "\n");
281 if (res == 0)
283 return -1;
286 return 0;
289 static void do_cpt_int_err(XDR *xd, const char *desc, int *i, FILE *list)
291 if (do_cpt_int(xd, desc, i, list) < 0)
293 cp_error();
297 static void do_cpt_step_err(XDR *xd, const char *desc, gmx_int64_t *i, FILE *list)
299 char buf[STEPSTRSIZE];
301 if (xdr_int64(xd, i) == 0)
303 cp_error();
305 if (list)
307 fprintf(list, "%s = %s\n", desc, gmx_step_str(*i, buf));
311 static void do_cpt_double_err(XDR *xd, const char *desc, double *f, FILE *list)
313 if (xdr_double(xd, f) == 0)
315 cp_error();
317 if (list)
319 fprintf(list, "%s = %f\n", desc, *f);
323 static void do_cpt_real_err(XDR *xd, real *f)
325 #if GMX_DOUBLE
326 bool_t res = xdr_double(xd, f);
327 #else
328 bool_t res = xdr_float(xd, f);
329 #endif
330 if (res == 0)
332 cp_error();
336 static void do_cpt_n_rvecs_err(XDR *xd, const char *desc, int n, rvec f[], FILE *list)
338 for (int i = 0; i < n; i++)
340 for (int j = 0; j < DIM; j++)
342 do_cpt_real_err(xd, &f[i][j]);
346 if (list)
348 pr_rvecs(list, 0, desc, f, n);
352 template <typename T>
353 struct xdr_type
357 template <>
358 struct xdr_type<int>
360 // cppcheck-suppress unusedStructMember
361 static const int value = xdr_datatype_int;
364 template <>
365 struct xdr_type<float>
367 // cppcheck-suppress unusedStructMember
368 static const int value = xdr_datatype_float;
371 template <>
372 struct xdr_type<double>
374 // cppcheck-suppress unusedStructMember
375 static const int value = xdr_datatype_double;
378 //! \brief Returns size in byte of an xdr_datatype
379 static inline unsigned int sizeOfXdrType(int xdrType)
381 switch (xdrType)
383 case xdr_datatype_int:
384 return sizeof(int);
385 break;
386 case xdr_datatype_float:
387 return sizeof(float);
388 break;
389 case xdr_datatype_double:
390 return sizeof(double);
391 break;
392 default: GMX_RELEASE_ASSERT(false, "XDR data type not implemented");
395 return 0;
398 //! \brief Returns the XDR process function for i/o of an XDR type
399 static inline xdrproc_t xdrProc(int xdrType)
401 switch (xdrType)
403 case xdr_datatype_int:
404 return reinterpret_cast<xdrproc_t>(xdr_int);
405 break;
406 case xdr_datatype_float:
407 return reinterpret_cast<xdrproc_t>(xdr_float);
408 break;
409 case xdr_datatype_double:
410 return reinterpret_cast<xdrproc_t>(xdr_double);
411 break;
412 default: GMX_RELEASE_ASSERT(false, "XDR data type not implemented");
415 return nullptr;
418 /*! \brief Lists or only reads an xdr vector from checkpoint file
420 * When list!=NULL reads and lists the \p nf vector elements of type \p xdrType.
421 * The header for the print is set by \p part and \p ecpt.
422 * The formatting of the printing is set by \p cptElementType.
423 * When list==NULL only reads the elements.
425 static bool_t listXdrVector(XDR *xd, StatePart part, int ecpt, int nf, int xdrType,
426 FILE *list, CptElementType cptElementType)
428 bool_t res = 0;
430 const unsigned int elemSize = sizeOfXdrType(xdrType);
431 std::vector<char> data(nf*elemSize);
432 res = xdr_vector(xd, data.data(), nf, elemSize, xdrProc(xdrType));
434 if (list != nullptr)
436 switch (xdrType)
438 case xdr_datatype_int:
439 pr_ivec(list, 0, entryName(part, ecpt), reinterpret_cast<const int *>(data.data()), nf, TRUE);
440 break;
441 case xdr_datatype_float:
442 #if !GMX_DOUBLE
443 if (cptElementType == CptElementType::real3)
445 // cppcheck-suppress invalidPointerCast
446 pr_rvecs(list, 0, entryName(part, ecpt), reinterpret_cast<const rvec *>(data.data()), nf/3);
448 else
449 #endif
451 /* Note: With double precision code dumping a single precision rvec will produce float iso rvec print, but that's a minor annoyance */
452 // cppcheck-suppress invalidPointerCast
453 pr_fvec(list, 0, entryName(part, ecpt), reinterpret_cast<const float *>(data.data()), nf, TRUE);
455 break;
456 case xdr_datatype_double:
457 #if GMX_DOUBLE
458 if (cptElementType == CptElementType::real3)
460 // cppcheck-suppress invalidPointerCast
461 pr_rvecs(list, 0, entryName(part, ecpt), reinterpret_cast<const rvec *>(data.data()), nf/3);
463 else
464 #endif
466 /* Note: With single precision code dumping a double precision rvec will produce float iso rvec print, but that's a minor annoyance */
467 // cppcheck-suppress invalidPointerCast
468 pr_dvec(list, 0, entryName(part, ecpt), reinterpret_cast<const double *>(data.data()), nf, TRUE);
470 break;
471 default: GMX_RELEASE_ASSERT(false, "Data type not implemented for listing");
475 return res;
478 //! \brief Convert a double array, typed char*, to float
479 gmx_unused static void convertArrayRealPrecision(const char *c, float *v, int n)
481 // cppcheck-suppress invalidPointerCast
482 const double *d = reinterpret_cast<const double *>(c);
483 for (int i = 0; i < n; i++)
485 v[i] = static_cast<float>(d[i]);
489 //! \brief Convert a float array, typed char*, to double
490 static void convertArrayRealPrecision(const char *c, double *v, int n)
492 // cppcheck-suppress invalidPointerCast
493 const float *f = reinterpret_cast<const float *>(c);
494 for (int i = 0; i < n; i++)
496 v[i] = static_cast<double>(f[i]);
500 //! \brief Generate an error for trying to convert to integer
501 static void convertArrayRealPrecision(const char gmx_unused *c, int gmx_unused *v, int gmx_unused n)
503 GMX_RELEASE_ASSERT(false, "We only expect type mismatches between float and double, not integer");
506 /*! \brief Low-level routine for reading/writing a vector of reals from/to file.
508 * This is the only routine that does the actually i/o of real vector,
509 * all other routines are intermediate level routines for specific real
510 * data types, calling this routine.
511 * Currently this routine is (too) complex, since it handles both real *
512 * and std::vector<real>. Using real * is deprecated and this routine
513 * will simplify a lot when only std::vector needs to be supported.
515 * The routine is generic to vectors with different allocators,
516 * because as part of reading a checkpoint there are vectors whose
517 * size is not known until reading has progressed far enough, so a
518 * resize method must be called.
520 * When not listing, we use either v or vector, depending on which is !=NULL.
521 * If nval >= 0, nval is used; on read this should match the passed value.
522 * If nval n<0, *nptr (with v) or vector->size() is used. On read using v,
523 * the value is stored in nptr
525 template<typename T, typename AllocatorType>
526 static int doVectorLow(XDR *xd, StatePart part, int ecpt, int sflags,
527 int nval, int *nptr,
528 T **v, std::vector<T, AllocatorType> *vector,
529 FILE *list, CptElementType cptElementType)
531 GMX_RELEASE_ASSERT(list != nullptr || (v != nullptr && vector == nullptr) || (v == nullptr && vector != nullptr), "Without list, we should have exactly one of v and vector != NULL");
533 bool_t res = 0;
535 int numElemInTheFile;
536 if (list == nullptr)
538 if (nval >= 0)
540 GMX_RELEASE_ASSERT(nptr == nullptr, "With nval>=0 we should have nptr==NULL");
541 numElemInTheFile = nval;
543 else
545 if (v != nullptr)
547 GMX_RELEASE_ASSERT(nptr != nullptr, "With nval<0 we should have nptr!=NULL");
548 // cppcheck-suppress nullPointer
549 numElemInTheFile = *nptr;
551 else
553 numElemInTheFile = vector->size();
557 /* Read/write the vector element count */
558 res = xdr_int(xd, &numElemInTheFile);
559 if (res == 0)
561 return -1;
563 /* Read/write the element data type */
564 constexpr int xdrTypeInTheCode = xdr_type<T>::value;
565 int xdrTypeInTheFile = xdrTypeInTheCode;
566 res = xdr_int(xd, &xdrTypeInTheFile);
567 if (res == 0)
569 return -1;
572 if (list == nullptr && (sflags & (1 << ecpt)))
574 if (nval >= 0)
576 if (numElemInTheFile != nval)
578 gmx_fatal(FARGS, "Count mismatch for state entry %s, code count is %d, file count is %d\n", entryName(part, ecpt), nval, numElemInTheFile);
581 else if (nptr != nullptr)
583 *nptr = numElemInTheFile;
586 bool typesMatch = (xdrTypeInTheFile == xdrTypeInTheCode);
587 if (!typesMatch)
589 char buf[STRLEN];
590 sprintf(buf, "mismatch for state entry %s, code precision is %s, file precision is %s",
591 entryName(part, ecpt),
592 xdr_datatype_names[xdrTypeInTheCode],
593 xdr_datatype_names[xdrTypeInTheFile]);
595 /* Matching int and real should never occur, but check anyhow */
596 if (xdrTypeInTheFile == xdr_datatype_int ||
597 xdrTypeInTheCode == xdr_datatype_int)
599 gmx_fatal(FARGS, "Type %s: incompatible checkpoint formats or corrupted checkpoint file.", buf);
601 fprintf(stderr, "Precision %s\n", buf);
604 T *vp;
605 if (v != nullptr)
607 if (*v == nullptr)
609 snew(*v, numElemInTheFile);
611 vp = *v;
613 else
615 /* This conditional ensures that we don't resize on write.
616 * In particular in the state where this code was written
617 * PaddedRVecVector has a size of numElemInThefile and we
618 * don't want to lose that padding here.
620 if (vector->size() < static_cast<unsigned int>(numElemInTheFile))
622 vector->resize(numElemInTheFile);
624 vp = vector->data();
627 char *vChar;
628 if (typesMatch)
630 vChar = reinterpret_cast<char *>(vp);
632 else
634 snew(vChar, numElemInTheFile*sizeOfXdrType(xdrTypeInTheFile));
636 res = xdr_vector(xd, vChar,
637 numElemInTheFile, sizeOfXdrType(xdrTypeInTheFile),
638 xdrProc(xdrTypeInTheFile));
639 if (res == 0)
641 return -1;
644 if (!typesMatch)
646 /* In the old code float-double conversion came for free.
647 * In the new code we still support it, mainly because
648 * the tip4p_continue regression test makes use of this.
649 * It's an open question if we do or don't want to allow this.
651 convertArrayRealPrecision(vChar, vp, numElemInTheFile);
652 sfree(vChar);
655 else
657 res = listXdrVector(xd, part, ecpt, numElemInTheFile, xdrTypeInTheFile,
658 list, cptElementType);
661 return 0;
664 //! \brief Read/Write a std::vector.
665 template <typename T>
666 static int doVector(XDR *xd, StatePart part, int ecpt, int sflags,
667 std::vector<T> *vector, FILE *list)
669 return doVectorLow<T>(xd, part, ecpt, sflags, -1, nullptr, nullptr, vector, list, CptElementType::real);
672 //! \brief Read/Write an ArrayRef<real>.
673 static int doRealArrayRef(XDR *xd, StatePart part, int ecpt, int sflags,
674 gmx::ArrayRef<real> vector, FILE *list)
676 real *v_real = vector.data();
677 return doVectorLow < real, std::allocator < real>>(xd, part, ecpt, sflags, vector.size(), nullptr, &v_real, nullptr, list, CptElementType::real);
680 //! \brief Read/Write a vector whose value_type is RVec and whose allocator is \c AllocatorType.
681 template <typename AllocatorType>
682 static int doRvecVector(XDR *xd, StatePart part, int ecpt, int sflags,
683 std::vector<gmx::RVec, AllocatorType> *v, int numAtoms, FILE *list)
685 const int numReals = numAtoms*DIM;
687 if (list == nullptr)
689 GMX_RELEASE_ASSERT(sflags & (1 << ecpt), "When not listing, the flag for the entry should be set when requesting i/o");
690 GMX_RELEASE_ASSERT(v->size() >= static_cast<size_t>(numAtoms), "v should have sufficient size for numAtoms");
692 real *v_real = v->data()->as_vec();
694 // PaddedRVecVector is padded beyond numAtoms, we should only write
695 // numAtoms RVecs
696 gmx::ArrayRef<real> ref(v_real, v_real + numReals);
698 return doRealArrayRef(xd, part, ecpt, sflags, ref, list);
700 else
702 // Use the rebind facility to change the value_type of the
703 // allocator from RVec to real.
704 using realAllocator = typename AllocatorType::template rebind<real>::other;
705 return doVectorLow<real, realAllocator>(xd, part, ecpt, sflags, numReals, nullptr, nullptr, nullptr, list, CptElementType::real);
709 /* This function stores n along with the reals for reading,
710 * but on reading it assumes that n matches the value in the checkpoint file,
711 * a fatal error is generated when this is not the case.
713 static int do_cpte_reals(XDR *xd, StatePart part, int ecpt, int sflags,
714 int n, real **v, FILE *list)
716 return doVectorLow < real, std::allocator < real>>(xd, part, ecpt, sflags, n, nullptr, v, nullptr, list, CptElementType::real);
719 /* This function does the same as do_cpte_reals,
720 * except that on reading it ignores the passed value of *n
721 * and stores the value read from the checkpoint file in *n.
723 static int do_cpte_n_reals(XDR *xd, StatePart part, int ecpt, int sflags,
724 int *n, real **v, FILE *list)
726 return doVectorLow < real, std::allocator < real>>(xd, part, ecpt, sflags, -1, n, v, nullptr, list, CptElementType::real);
729 static int do_cpte_real(XDR *xd, StatePart part, int ecpt, int sflags,
730 real *r, FILE *list)
732 return doVectorLow < real, std::allocator < real>>(xd, part, ecpt, sflags, 1, nullptr, &r, nullptr, list, CptElementType::real);
735 static int do_cpte_ints(XDR *xd, StatePart part, int ecpt, int sflags,
736 int n, int **v, FILE *list)
738 return doVectorLow < int, std::allocator < int>>(xd, part, ecpt, sflags, n, nullptr, v, nullptr, list, CptElementType::integer);
741 static int do_cpte_int(XDR *xd, StatePart part, int ecpt, int sflags,
742 int *i, FILE *list)
744 return do_cpte_ints(xd, part, ecpt, sflags, 1, &i, list);
747 static int do_cpte_doubles(XDR *xd, StatePart part, int ecpt, int sflags,
748 int n, double **v, FILE *list)
750 return doVectorLow < double, std::allocator < double>>(xd, part, ecpt, sflags, n, nullptr, v, nullptr, list, CptElementType::real);
753 static int do_cpte_double(XDR *xd, StatePart part, int ecpt, int sflags,
754 double *r, FILE *list)
756 return do_cpte_doubles(xd, part, ecpt, sflags, 1, &r, list);
759 static int do_cpte_matrix(XDR *xd, StatePart part, int ecpt, int sflags,
760 matrix v, FILE *list)
762 real *vr;
763 int ret;
765 vr = &(v[0][0]);
766 ret = doVectorLow < real, std::allocator < real>>(xd, part, ecpt, sflags,
767 DIM*DIM, nullptr, &vr, nullptr, nullptr, CptElementType::matrix3x3);
769 if (list && ret == 0)
771 pr_rvecs(list, 0, entryName(part, ecpt), v, DIM);
774 return ret;
778 static int do_cpte_nmatrix(XDR *xd, StatePart part, int ecpt, int sflags,
779 int n, real **v, FILE *list)
781 int i;
782 int ret, reti;
783 char name[CPTSTRLEN];
785 ret = 0;
786 if (v == nullptr)
788 snew(v, n);
790 for (i = 0; i < n; i++)
792 reti = doVectorLow < real, std::allocator < real>>(xd, part, ecpt, sflags, n, nullptr, &(v[i]), nullptr, nullptr, CptElementType::matrix3x3);
793 if (list && reti == 0)
795 sprintf(name, "%s[%d]", entryName(part, ecpt), i);
796 pr_reals(list, 0, name, v[i], n);
798 if (reti != 0)
800 ret = reti;
803 return ret;
806 static int do_cpte_matrices(XDR *xd, StatePart part, int ecpt, int sflags,
807 int n, matrix **v, FILE *list)
809 bool_t res = 0;
810 matrix *vp, *va = nullptr;
811 real *vr;
812 int nf, i, j, k;
813 int ret;
815 nf = n;
816 res = xdr_int(xd, &nf);
817 if (res == 0)
819 return -1;
821 if (list == nullptr && nf != n)
823 gmx_fatal(FARGS, "Count mismatch for state entry %s, code count is %d, file count is %d\n", entryName(part, ecpt), n, nf);
825 if (list || !(sflags & (1<<ecpt)))
827 snew(va, nf);
828 vp = va;
830 else
832 if (*v == nullptr)
834 snew(*v, nf);
836 vp = *v;
838 snew(vr, nf*DIM*DIM);
839 for (i = 0; i < nf; i++)
841 for (j = 0; j < DIM; j++)
843 for (k = 0; k < DIM; k++)
845 vr[(i*DIM+j)*DIM+k] = vp[i][j][k];
849 ret = doVectorLow < real, std::allocator < real>>(xd, part, ecpt, sflags,
850 nf*DIM*DIM, nullptr, &vr, nullptr, nullptr,
851 CptElementType::matrix3x3);
852 for (i = 0; i < nf; i++)
854 for (j = 0; j < DIM; j++)
856 for (k = 0; k < DIM; k++)
858 vp[i][j][k] = vr[(i*DIM+j)*DIM+k];
862 sfree(vr);
864 if (list && ret == 0)
866 for (i = 0; i < nf; i++)
868 pr_rvecs(list, 0, entryName(part, ecpt), vp[i], DIM);
871 if (va)
873 sfree(va);
876 return ret;
879 static void do_cpt_header(XDR *xd, gmx_bool bRead, int *file_version,
880 char **version, char **btime, char **buser, char **bhost,
881 int *double_prec,
882 char **fprog, char **ftime,
883 int *eIntegrator, int *simulation_part,
884 gmx_int64_t *step, double *t,
885 int *nnodes, int *dd_nc, int *npme,
886 int *natoms, int *ngtc, int *nnhpres, int *nhchainlength,
887 int *nlambda, int *flags_state,
888 int *flags_eks, int *flags_enh, int *flags_dfh, int *flags_awhh,
889 int *nED, int *eSwapCoords,
890 FILE *list)
892 bool_t res = 0;
893 int magic;
894 int idum = 0;
895 char *fhost;
897 if (bRead)
899 magic = -1;
901 else
903 magic = CPT_MAGIC1;
905 res = xdr_int(xd, &magic);
906 if (res == 0)
908 gmx_fatal(FARGS, "The checkpoint file is empty/corrupted, or maybe you are out of disk space?");
910 if (magic != CPT_MAGIC1)
912 gmx_fatal(FARGS, "Start of file magic number mismatch, checkpoint file has %d, should be %d\n"
913 "The checkpoint file is corrupted or not a checkpoint file",
914 magic, CPT_MAGIC1);
916 if (!bRead)
918 snew(fhost, 255);
919 gmx_gethostname(fhost, 255);
921 do_cpt_string_err(xd, bRead, "GROMACS version", version, list);
922 do_cpt_string_err(xd, bRead, "GROMACS build time", btime, list);
923 do_cpt_string_err(xd, bRead, "GROMACS build user", buser, list);
924 do_cpt_string_err(xd, bRead, "GROMACS build host", bhost, list);
925 do_cpt_string_err(xd, bRead, "generating program", fprog, list);
926 do_cpt_string_err(xd, bRead, "generation time", ftime, list);
927 *file_version = cpt_version;
928 do_cpt_int_err(xd, "checkpoint file version", file_version, list);
929 if (*file_version > cpt_version)
931 gmx_fatal(FARGS, "Attempting to read a checkpoint file of version %d with code of version %d\n", *file_version, cpt_version);
933 if (*file_version >= 13)
935 do_cpt_int_err(xd, "GROMACS double precision", double_prec, list);
937 else
939 *double_prec = -1;
941 if (*file_version >= 12)
943 do_cpt_string_err(xd, bRead, "generating host", &fhost, list);
944 if (list == nullptr)
946 sfree(fhost);
949 do_cpt_int_err(xd, "#atoms", natoms, list);
950 do_cpt_int_err(xd, "#T-coupling groups", ngtc, list);
951 if (*file_version >= 10)
953 do_cpt_int_err(xd, "#Nose-Hoover T-chains", nhchainlength, list);
955 else
957 *nhchainlength = 1;
959 if (*file_version >= 11)
961 do_cpt_int_err(xd, "#Nose-Hoover T-chains for barostat ", nnhpres, list);
963 else
965 *nnhpres = 0;
967 if (*file_version >= 14)
969 do_cpt_int_err(xd, "# of total lambda states ", nlambda, list);
971 else
973 *nlambda = 0;
975 do_cpt_int_err(xd, "integrator", eIntegrator, list);
976 if (*file_version >= 3)
978 do_cpt_int_err(xd, "simulation part #", simulation_part, list);
980 else
982 *simulation_part = 1;
984 if (*file_version >= 5)
986 do_cpt_step_err(xd, "step", step, list);
988 else
990 do_cpt_int_err(xd, "step", &idum, list);
991 *step = idum;
993 do_cpt_double_err(xd, "t", t, list);
994 do_cpt_int_err(xd, "#PP-ranks", nnodes, list);
995 idum = 1;
996 do_cpt_int_err(xd, "dd_nc[x]", dd_nc ? &(dd_nc[0]) : &idum, list);
997 do_cpt_int_err(xd, "dd_nc[y]", dd_nc ? &(dd_nc[1]) : &idum, list);
998 do_cpt_int_err(xd, "dd_nc[z]", dd_nc ? &(dd_nc[2]) : &idum, list);
999 do_cpt_int_err(xd, "#PME-only ranks", npme, list);
1000 do_cpt_int_err(xd, "state flags", flags_state, list);
1001 if (*file_version >= 4)
1003 do_cpt_int_err(xd, "ekin data flags", flags_eks, list);
1004 do_cpt_int_err(xd, "energy history flags", flags_enh, list);
1006 else
1008 *flags_eks = 0;
1009 *flags_enh = (*flags_state >> (estORIRE_DTAV+1));
1010 *flags_state = (*flags_state & ~((1<<(estORIRE_DTAV+1)) |
1011 (1<<(estORIRE_DTAV+2)) |
1012 (1<<(estORIRE_DTAV+3))));
1014 if (*file_version >= 14)
1016 do_cpt_int_err(xd, "df history flags", flags_dfh, list);
1018 else
1020 *flags_dfh = 0;
1023 if (*file_version >= 15)
1025 do_cpt_int_err(xd, "ED data sets", nED, list);
1027 else
1029 *nED = 0;
1032 if (*file_version >= 16)
1034 do_cpt_int_err(xd, "swap", eSwapCoords, list);
1036 else
1038 *eSwapCoords = eswapNO;
1041 if (*file_version >= 17)
1043 do_cpt_int_err(xd, "AWH history flags", flags_awhh, list);
1045 else
1047 *flags_awhh = 0;
1051 static int do_cpt_footer(XDR *xd, int file_version)
1053 bool_t res = 0;
1054 int magic;
1056 if (file_version >= 2)
1058 magic = CPT_MAGIC2;
1059 res = xdr_int(xd, &magic);
1060 if (res == 0)
1062 cp_error();
1064 if (magic != CPT_MAGIC2)
1066 return -1;
1070 return 0;
1073 static int do_cpt_state(XDR *xd,
1074 int fflags, t_state *state,
1075 FILE *list)
1077 int ret = 0;
1078 const StatePart part = StatePart::microState;
1079 const int sflags = state->flags;
1080 // If reading, state->natoms was probably just read, so
1081 // allocations need to be managed. If writing, this won't change
1082 // anything that matters.
1083 state_change_natoms(state, state->natoms);
1084 for (int i = 0; (i < estNR && ret == 0); i++)
1086 if (fflags & (1<<i))
1088 switch (i)
1090 case estLAMBDA: ret = doRealArrayRef(xd, part, i, sflags, gmx::arrayRefFromArray<real>(state->lambda.data(), state->lambda.size()), list); break;
1091 case estFEPSTATE: ret = do_cpte_int (xd, part, i, sflags, &state->fep_state, list); break;
1092 case estBOX: ret = do_cpte_matrix(xd, part, i, sflags, state->box, list); break;
1093 case estBOX_REL: ret = do_cpte_matrix(xd, part, i, sflags, state->box_rel, list); break;
1094 case estBOXV: ret = do_cpte_matrix(xd, part, i, sflags, state->boxv, list); break;
1095 case estPRES_PREV: ret = do_cpte_matrix(xd, part, i, sflags, state->pres_prev, list); break;
1096 case estSVIR_PREV: ret = do_cpte_matrix(xd, part, i, sflags, state->svir_prev, list); break;
1097 case estFVIR_PREV: ret = do_cpte_matrix(xd, part, i, sflags, state->fvir_prev, list); break;
1098 case estNH_XI: ret = doVector<double>(xd, part, i, sflags, &state->nosehoover_xi, list); break;
1099 case estNH_VXI: ret = doVector<double>(xd, part, i, sflags, &state->nosehoover_vxi, list); break;
1100 case estNHPRES_XI: ret = doVector<double>(xd, part, i, sflags, &state->nhpres_xi, list); break;
1101 case estNHPRES_VXI: ret = doVector<double>(xd, part, i, sflags, &state->nhpres_vxi, list); break;
1102 case estTHERM_INT: ret = doVector<double>(xd, part, i, sflags, &state->therm_integral, list); break;
1103 case estBAROS_INT: ret = do_cpte_double(xd, part, i, sflags, &state->baros_integral, list); break;
1104 case estVETA: ret = do_cpte_real(xd, part, i, sflags, &state->veta, list); break;
1105 case estVOL0: ret = do_cpte_real(xd, part, i, sflags, &state->vol0, list); break;
1106 case estX: ret = doRvecVector(xd, part, i, sflags, &state->x, state->natoms, list); break;
1107 case estV: ret = doRvecVector(xd, part, i, sflags, &state->v, state->natoms, list); break;
1108 /* The RNG entries are no longer written,
1109 * the next 4 lines are only for reading old files.
1111 case estLD_RNG_NOTSUPPORTED: ret = do_cpte_ints(xd, part, i, sflags, 0, nullptr, list); break;
1112 case estLD_RNGI_NOTSUPPORTED: ret = do_cpte_ints(xd, part, i, sflags, 0, nullptr, list); break;
1113 case estMC_RNG_NOTSUPPORTED: ret = do_cpte_ints(xd, part, i, sflags, 0, nullptr, list); break;
1114 case estMC_RNGI_NOTSUPPORTED: ret = do_cpte_ints(xd, part, i, sflags, 0, nullptr, list); break;
1115 case estDISRE_INITF: ret = do_cpte_real (xd, part, i, sflags, &state->hist.disre_initf, list); break;
1116 case estDISRE_RM3TAV: ret = do_cpte_n_reals(xd, part, i, sflags, &state->hist.ndisrepairs, &state->hist.disre_rm3tav, list); break;
1117 case estORIRE_INITF: ret = do_cpte_real (xd, part, i, sflags, &state->hist.orire_initf, list); break;
1118 case estORIRE_DTAV: ret = do_cpte_n_reals(xd, part, i, sflags, &state->hist.norire_Dtav, &state->hist.orire_Dtav, list); break;
1119 default:
1120 gmx_fatal(FARGS, "Unknown state entry %d\n"
1121 "You are reading a checkpoint file written by different code, which is not supported", i);
1126 return ret;
1129 static int do_cpt_ekinstate(XDR *xd, int fflags, ekinstate_t *ekins,
1130 FILE *list)
1132 int ret = 0;
1134 const StatePart part = StatePart::kineticEnergy;
1135 for (int i = 0; (i < eeksNR && ret == 0); i++)
1137 if (fflags & (1<<i))
1139 switch (i)
1142 case eeksEKIN_N: ret = do_cpte_int(xd, part, i, fflags, &ekins->ekin_n, list); break;
1143 case eeksEKINH: ret = do_cpte_matrices(xd, part, i, fflags, ekins->ekin_n, &ekins->ekinh, list); break;
1144 case eeksEKINF: ret = do_cpte_matrices(xd, part, i, fflags, ekins->ekin_n, &ekins->ekinf, list); break;
1145 case eeksEKINO: ret = do_cpte_matrices(xd, part, i, fflags, ekins->ekin_n, &ekins->ekinh_old, list); break;
1146 case eeksEKINTOTAL: ret = do_cpte_matrix(xd, part, i, fflags, ekins->ekin_total, list); break;
1147 case eeksEKINSCALEF: ret = doVector<double>(xd, part, i, fflags, &ekins->ekinscalef_nhc, list); break;
1148 case eeksVSCALE: ret = doVector<double>(xd, part, i, fflags, &ekins->vscale_nhc, list); break;
1149 case eeksEKINSCALEH: ret = doVector<double>(xd, part, i, fflags, &ekins->ekinscaleh_nhc, list); break;
1150 case eeksDEKINDL: ret = do_cpte_real(xd, part, i, fflags, &ekins->dekindl, list); break;
1151 case eeksMVCOS: ret = do_cpte_real(xd, part, i, fflags, &ekins->mvcos, list); break;
1152 default:
1153 gmx_fatal(FARGS, "Unknown ekin data state entry %d\n"
1154 "You are probably reading a new checkpoint file with old code", i);
1159 return ret;
1163 static int do_cpt_swapstate(XDR *xd, gmx_bool bRead,
1164 int eSwapCoords, swaphistory_t *swapstate, FILE *list)
1166 int swap_cpt_version = 2;
1168 if (eSwapCoords == eswapNO)
1170 return 0;
1173 swapstate->bFromCpt = bRead;
1174 swapstate->eSwapCoords = eSwapCoords;
1176 do_cpt_int_err(xd, "swap checkpoint version", &swap_cpt_version, list);
1177 if (bRead && swap_cpt_version < 2)
1179 gmx_fatal(FARGS, "Cannot read checkpoint files that were written with old versions"
1180 "of the ion/water position swapping protocol.\n");
1183 do_cpt_int_err(xd, "swap coupling steps", &swapstate->nAverage, list);
1185 /* When reading, init_swapcoords has not been called yet,
1186 * so we have to allocate memory first. */
1187 do_cpt_int_err(xd, "number of ion types", &swapstate->nIonTypes, list);
1188 if (bRead)
1190 snew(swapstate->ionType, swapstate->nIonTypes);
1193 for (int ic = 0; ic < eCompNR; ic++)
1195 for (int ii = 0; ii < swapstate->nIonTypes; ii++)
1197 swapstateIons_t *gs = &swapstate->ionType[ii];
1199 if (bRead)
1201 do_cpt_int_err(xd, "swap requested atoms", &gs->nMolReq[ic], list);
1203 else
1205 do_cpt_int_err(xd, "swap requested atoms p", gs->nMolReq_p[ic], list);
1208 if (bRead)
1210 do_cpt_int_err(xd, "swap influx net", &gs->inflow_net[ic], list);
1212 else
1214 do_cpt_int_err(xd, "swap influx net p", gs->inflow_net_p[ic], list);
1217 if (bRead && (nullptr == gs->nMolPast[ic]) )
1219 snew(gs->nMolPast[ic], swapstate->nAverage);
1222 for (int j = 0; j < swapstate->nAverage; j++)
1224 if (bRead)
1226 do_cpt_int_err(xd, "swap past atom counts", &gs->nMolPast[ic][j], list);
1228 else
1230 do_cpt_int_err(xd, "swap past atom counts p", &gs->nMolPast_p[ic][j], list);
1236 /* Ion flux per channel */
1237 for (int ic = 0; ic < eChanNR; ic++)
1239 for (int ii = 0; ii < swapstate->nIonTypes; ii++)
1241 swapstateIons_t *gs = &swapstate->ionType[ii];
1243 if (bRead)
1245 do_cpt_int_err(xd, "channel flux A->B", &gs->fluxfromAtoB[ic], list);
1247 else
1249 do_cpt_int_err(xd, "channel flux A->B p", gs->fluxfromAtoB_p[ic], list);
1254 /* Ion flux leakage */
1255 if (bRead)
1257 do_cpt_int_err(xd, "flux leakage", &swapstate->fluxleak, list);
1259 else
1261 do_cpt_int_err(xd, "flux leakage", swapstate->fluxleak_p, list);
1264 /* Ion history */
1265 for (int ii = 0; ii < swapstate->nIonTypes; ii++)
1267 swapstateIons_t *gs = &swapstate->ionType[ii];
1269 do_cpt_int_err(xd, "number of ions", &gs->nMol, list);
1271 if (bRead)
1273 snew(gs->channel_label, gs->nMol);
1274 snew(gs->comp_from, gs->nMol);
1277 do_cpt_u_chars(xd, "channel history", gs->nMol, gs->channel_label, list);
1278 do_cpt_u_chars(xd, "domain history", gs->nMol, gs->comp_from, list);
1281 /* Save the last known whole positions to checkpoint
1282 * file to be able to also make multimeric channels whole in PBC */
1283 do_cpt_int_err(xd, "Ch0 atoms", &swapstate->nat[eChan0], list);
1284 do_cpt_int_err(xd, "Ch1 atoms", &swapstate->nat[eChan1], list);
1285 if (bRead)
1287 snew(swapstate->xc_old_whole[eChan0], swapstate->nat[eChan0]);
1288 snew(swapstate->xc_old_whole[eChan1], swapstate->nat[eChan1]);
1289 do_cpt_n_rvecs_err(xd, "Ch0 whole x", swapstate->nat[eChan0], swapstate->xc_old_whole[eChan0], list);
1290 do_cpt_n_rvecs_err(xd, "Ch1 whole x", swapstate->nat[eChan1], swapstate->xc_old_whole[eChan1], list);
1292 else
1294 do_cpt_n_rvecs_err(xd, "Ch0 whole x", swapstate->nat[eChan0], *swapstate->xc_old_whole_p[eChan0], list);
1295 do_cpt_n_rvecs_err(xd, "Ch1 whole x", swapstate->nat[eChan1], *swapstate->xc_old_whole_p[eChan1], list);
1298 return 0;
1302 static int do_cpt_enerhist(XDR *xd, gmx_bool bRead,
1303 int fflags, energyhistory_t *enerhist,
1304 FILE *list)
1306 int ret = 0;
1308 if (fflags == 0)
1310 return ret;
1313 GMX_RELEASE_ASSERT(enerhist != nullptr, "With energy history, we need a valid enerhist pointer");
1315 /* This is stored/read for backward compatibility */
1316 int energyHistoryNumEnergies = 0;
1317 if (bRead)
1319 enerhist->nsteps = 0;
1320 enerhist->nsum = 0;
1321 enerhist->nsteps_sim = 0;
1322 enerhist->nsum_sim = 0;
1324 else if (enerhist != nullptr)
1326 energyHistoryNumEnergies = enerhist->ener_sum_sim.size();
1329 delta_h_history_t *deltaH = enerhist->deltaHForeignLambdas.get();
1330 const StatePart part = StatePart::energyHistory;
1331 for (int i = 0; (i < eenhNR && ret == 0); i++)
1333 if (fflags & (1<<i))
1335 switch (i)
1337 case eenhENERGY_N: ret = do_cpte_int(xd, part, i, fflags, &energyHistoryNumEnergies, list); break;
1338 case eenhENERGY_AVER: ret = doVector<double>(xd, part, i, fflags, &enerhist->ener_ave, list); break;
1339 case eenhENERGY_SUM: ret = doVector<double>(xd, part, i, fflags, &enerhist->ener_sum, list); break;
1340 case eenhENERGY_NSUM: do_cpt_step_err(xd, eenh_names[i], &enerhist->nsum, list); break;
1341 case eenhENERGY_SUM_SIM: ret = doVector<double>(xd, part, i, fflags, &enerhist->ener_sum_sim, list); break;
1342 case eenhENERGY_NSUM_SIM: do_cpt_step_err(xd, eenh_names[i], &enerhist->nsum_sim, list); break;
1343 case eenhENERGY_NSTEPS: do_cpt_step_err(xd, eenh_names[i], &enerhist->nsteps, list); break;
1344 case eenhENERGY_NSTEPS_SIM: do_cpt_step_err(xd, eenh_names[i], &enerhist->nsteps_sim, list); break;
1345 case eenhENERGY_DELTA_H_NN:
1347 int numDeltaH = 0;
1348 if (!bRead && deltaH != nullptr)
1350 numDeltaH = deltaH->dh.size();
1352 do_cpt_int_err(xd, eenh_names[i], &numDeltaH, list);
1353 if (bRead)
1355 if (deltaH == nullptr)
1357 enerhist->deltaHForeignLambdas.reset(new delta_h_history_t);
1358 deltaH = enerhist->deltaHForeignLambdas.get();
1360 deltaH->dh.resize(numDeltaH);
1361 deltaH->start_lambda_set = FALSE;
1363 break;
1365 case eenhENERGY_DELTA_H_LIST:
1366 for (auto dh : deltaH->dh)
1368 ret = doVector<real>(xd, part, i, fflags, &dh, list);
1370 break;
1371 case eenhENERGY_DELTA_H_STARTTIME:
1372 ret = do_cpte_double(xd, part, i, fflags, &(deltaH->start_time), list); break;
1373 case eenhENERGY_DELTA_H_STARTLAMBDA:
1374 ret = do_cpte_double(xd, part, i, fflags, &(deltaH->start_lambda), list); break;
1375 default:
1376 gmx_fatal(FARGS, "Unknown energy history entry %d\n"
1377 "You are probably reading a new checkpoint file with old code", i);
1382 if ((fflags & (1<<eenhENERGY_SUM)) && !(fflags & (1<<eenhENERGY_SUM_SIM)))
1384 /* Assume we have an old file format and copy sum to sum_sim */
1385 enerhist->ener_sum_sim = enerhist->ener_sum;
1388 if ( (fflags & (1<<eenhENERGY_NSUM)) &&
1389 !(fflags & (1<<eenhENERGY_NSTEPS)))
1391 /* Assume we have an old file format and copy nsum to nsteps */
1392 enerhist->nsteps = enerhist->nsum;
1394 if ( (fflags & (1<<eenhENERGY_NSUM_SIM)) &&
1395 !(fflags & (1<<eenhENERGY_NSTEPS_SIM)))
1397 /* Assume we have an old file format and copy nsum to nsteps */
1398 enerhist->nsteps_sim = enerhist->nsum_sim;
1401 return ret;
1404 static int do_cpt_df_hist(XDR *xd, int fflags, int nlambda, df_history_t **dfhistPtr, FILE *list)
1406 int ret = 0;
1408 if (fflags == 0)
1410 return 0;
1413 if (*dfhistPtr == nullptr)
1415 snew(*dfhistPtr, 1);
1416 (*dfhistPtr)->nlambda = nlambda;
1417 init_df_history(*dfhistPtr, nlambda);
1419 df_history_t *dfhist = *dfhistPtr;
1421 const StatePart part = StatePart::freeEnergyHistory;
1422 for (int i = 0; (i < edfhNR && ret == 0); i++)
1424 if (fflags & (1<<i))
1426 switch (i)
1428 case edfhBEQUIL: ret = do_cpte_int(xd, part, i, fflags, &dfhist->bEquil, list); break;
1429 case edfhNATLAMBDA: ret = do_cpte_ints(xd, part, i, fflags, nlambda, &dfhist->n_at_lam, list); break;
1430 case edfhWLHISTO: ret = do_cpte_reals(xd, part, i, fflags, nlambda, &dfhist->wl_histo, list); break;
1431 case edfhWLDELTA: ret = do_cpte_real(xd, part, i, fflags, &dfhist->wl_delta, list); break;
1432 case edfhSUMWEIGHTS: ret = do_cpte_reals(xd, part, i, fflags, nlambda, &dfhist->sum_weights, list); break;
1433 case edfhSUMDG: ret = do_cpte_reals(xd, part, i, fflags, nlambda, &dfhist->sum_dg, list); break;
1434 case edfhSUMMINVAR: ret = do_cpte_reals(xd, part, i, fflags, nlambda, &dfhist->sum_minvar, list); break;
1435 case edfhSUMVAR: ret = do_cpte_reals(xd, part, i, fflags, nlambda, &dfhist->sum_variance, list); break;
1436 case edfhACCUMP: ret = do_cpte_nmatrix(xd, part, i, fflags, nlambda, dfhist->accum_p, list); break;
1437 case edfhACCUMM: ret = do_cpte_nmatrix(xd, part, i, fflags, nlambda, dfhist->accum_m, list); break;
1438 case edfhACCUMP2: ret = do_cpte_nmatrix(xd, part, i, fflags, nlambda, dfhist->accum_p2, list); break;
1439 case edfhACCUMM2: ret = do_cpte_nmatrix(xd, part, i, fflags, nlambda, dfhist->accum_m2, list); break;
1440 case edfhTIJ: ret = do_cpte_nmatrix(xd, part, i, fflags, nlambda, dfhist->Tij, list); break;
1441 case edfhTIJEMP: ret = do_cpte_nmatrix(xd, part, i, fflags, nlambda, dfhist->Tij_empirical, list); break;
1443 default:
1444 gmx_fatal(FARGS, "Unknown df history entry %d\n"
1445 "You are probably reading a new checkpoint file with old code", i);
1450 return ret;
1454 /* This function stores the last whole configuration of the reference and
1455 * average structure in the .cpt file
1457 static int do_cpt_EDstate(XDR *xd, gmx_bool bRead,
1458 int nED, edsamhistory_t *EDstate, FILE *list)
1460 if (nED == 0)
1462 return 0;
1465 EDstate->bFromCpt = bRead;
1466 EDstate->nED = nED;
1468 /* When reading, init_edsam has not been called yet,
1469 * so we have to allocate memory first. */
1470 if (bRead)
1472 snew(EDstate->nref, EDstate->nED);
1473 snew(EDstate->old_sref, EDstate->nED);
1474 snew(EDstate->nav, EDstate->nED);
1475 snew(EDstate->old_sav, EDstate->nED);
1478 /* Read/write the last whole conformation of SREF and SAV for each ED dataset (usually only one) */
1479 for (int i = 0; i < EDstate->nED; i++)
1481 char buf[STRLEN];
1483 /* Reference structure SREF */
1484 sprintf(buf, "ED%d # of atoms in reference structure", i+1);
1485 do_cpt_int_err(xd, buf, &EDstate->nref[i], list);
1486 sprintf(buf, "ED%d x_ref", i+1);
1487 if (bRead)
1489 snew(EDstate->old_sref[i], EDstate->nref[i]);
1490 do_cpt_n_rvecs_err(xd, buf, EDstate->nref[i], EDstate->old_sref[i], list);
1492 else
1494 do_cpt_n_rvecs_err(xd, buf, EDstate->nref[i], EDstate->old_sref_p[i], list);
1497 /* Average structure SAV */
1498 sprintf(buf, "ED%d # of atoms in average structure", i+1);
1499 do_cpt_int_err(xd, buf, &EDstate->nav[i], list);
1500 sprintf(buf, "ED%d x_av", i+1);
1501 if (bRead)
1503 snew(EDstate->old_sav[i], EDstate->nav[i]);
1504 do_cpt_n_rvecs_err(xd, buf, EDstate->nav[i], EDstate->old_sav[i], list);
1506 else
1508 do_cpt_n_rvecs_err(xd, buf, EDstate->nav[i], EDstate->old_sav_p[i], list);
1512 return 0;
1515 static int do_cpt_correlation_grid(XDR *xd, gmx_bool bRead, gmx_unused int fflags,
1516 gmx::CorrelationGridHistory *corrGrid,
1517 FILE *list, int eawhh)
1519 int ret = 0;
1521 do_cpt_int_err(xd, eawhh_names[eawhh], &(corrGrid->numCorrelationTensors), list);
1522 do_cpt_int_err(xd, eawhh_names[eawhh], &(corrGrid->tensorSize), list);
1523 do_cpt_int_err(xd, eawhh_names[eawhh], &(corrGrid->blockDataListSize), list);
1525 if (bRead)
1527 initCorrelationGridHistory(corrGrid, corrGrid->numCorrelationTensors, corrGrid->tensorSize, corrGrid->blockDataListSize);
1530 for (gmx::CorrelationBlockDataHistory &blockData : corrGrid->blockDataBuffer)
1532 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.blockSumWeight), list);
1533 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.blockSumSquareWeight), list);
1534 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.blockSumWeightX), list);
1535 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.blockSumWeightY), list);
1536 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.sumOverBlocksSquareBlockWeight), list);
1537 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.sumOverBlocksBlockSquareWeight), list);
1538 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.sumOverBlocksBlockWeightBlockWeightX), list);
1539 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.sumOverBlocksBlockWeightBlockWeightY), list);
1540 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.blockLength), list);
1541 do_cpt_int_err(xd, eawhh_names[eawhh], &(blockData.previousBlockIndex), list);
1542 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.correlationIntegral), list);
1545 return ret;
1548 static int do_cpt_awh_bias(XDR *xd, gmx_bool bRead,
1549 int fflags, gmx::AwhBiasHistory *biasHistory,
1550 FILE *list)
1552 int ret = 0;
1554 gmx::AwhBiasStateHistory *state = &biasHistory->state;
1555 for (int i = 0; (i < eawhhNR && ret == 0); i++)
1557 if (fflags & (1<<i))
1559 switch (i)
1561 case eawhhIN_INITIAL:
1562 do_cpt_int_err(xd, eawhh_names[i], &state->in_initial, list); break;
1563 case eawhhEQUILIBRATEHISTOGRAM:
1564 do_cpt_int_err(xd, eawhh_names[i], &state->equilibrateHistogram, list); break;
1565 case eawhhHISTSIZE:
1566 do_cpt_double_err(xd, eawhh_names[i], &state->histSize, list); break;
1567 case eawhhNPOINTS:
1569 int numPoints;
1570 if (!bRead)
1572 numPoints = biasHistory->pointState.size();
1574 do_cpt_int_err(xd, eawhh_names[i], &numPoints, list);
1575 if (bRead)
1577 biasHistory->pointState.resize(numPoints);
1580 break;
1581 case eawhhCOORDPOINT:
1582 for (auto &psh : biasHistory->pointState)
1584 do_cpt_double_err(xd, eawhh_names[i], &psh.target, list);
1585 do_cpt_double_err(xd, eawhh_names[i], &psh.free_energy, list);
1586 do_cpt_double_err(xd, eawhh_names[i], &psh.bias, list);
1587 do_cpt_double_err(xd, eawhh_names[i], &psh.weightsum_iteration, list);
1588 do_cpt_double_err(xd, eawhh_names[i], &psh.weightsum_covering, list);
1589 do_cpt_double_err(xd, eawhh_names[i], &psh.weightsum_tot, list);
1590 do_cpt_double_err(xd, eawhh_names[i], &psh.weightsum_ref, list);
1591 do_cpt_step_err(xd, eawhh_names[i], &psh.last_update_index, list);
1592 do_cpt_double_err(xd, eawhh_names[i], &psh.log_pmfsum, list);
1593 do_cpt_double_err(xd, eawhh_names[i], &psh.visits_iteration, list);
1594 do_cpt_double_err(xd, eawhh_names[i], &psh.visits_tot, list);
1596 break;
1597 case eawhhUMBRELLAGRIDPOINT:
1598 do_cpt_int_err(xd, eawhh_names[i], &(state->umbrellaGridpoint), list); break;
1599 case eawhhUPDATELIST:
1600 do_cpt_int_err(xd, eawhh_names[i], &(state->origin_index_updatelist), list);
1601 do_cpt_int_err(xd, eawhh_names[i], &(state->end_index_updatelist), list);
1602 break;
1603 case eawhhLOGSCALEDSAMPLEWEIGHT:
1604 do_cpt_double_err(xd, eawhh_names[i], &(state->logScaledSampleWeight), list);
1605 do_cpt_double_err(xd, eawhh_names[i], &(state->maxLogScaledSampleWeight), list);
1606 break;
1607 case eawhhNUMUPDATES:
1608 do_cpt_step_err(xd, eawhh_names[i], &(state->numUpdates), list);
1609 break;
1610 case eawhhFORCECORRELATIONGRID:
1611 ret = do_cpt_correlation_grid(xd, bRead, fflags, &biasHistory->forceCorrelationGrid, list, i);
1612 break;
1613 default:
1614 gmx_fatal(FARGS, "Unknown awh history entry %d\n", i);
1619 return ret;
1622 static int do_cpt_awh(XDR *xd, gmx_bool bRead,
1623 int fflags, gmx::AwhHistory *awhHistory,
1624 FILE *list)
1626 int ret = 0;
1628 if (fflags != 0)
1630 std::shared_ptr<gmx::AwhHistory> awhHistoryLocal;
1632 if (awhHistory == nullptr)
1634 GMX_RELEASE_ASSERT(bRead, "do_cpt_awh should not be called for writing without an AwhHistory");
1636 awhHistoryLocal = std::shared_ptr<gmx::AwhHistory>(new gmx::AwhHistory());
1637 awhHistory = awhHistoryLocal.get();
1640 /* To be able to read and write the AWH data several parameters determining the layout of the AWH structs need to be known
1641 (nbias, npoints, etc.). The best thing (?) would be to have these passed to this function. When writing to a checkpoint
1642 these parameters are available in awh_history (after calling init_awh_history). When reading from a checkpoint though, there
1643 is no initialized awh_history (it is initialized and set in this function). The AWH parameters have not always been read
1644 at the time when this function is called for reading so I don't know how to pass them as input. Here, this is solved by
1645 when writing a checkpoint, also storing parameters needed for future reading of the checkpoint.
1647 Another issue is that some variables that AWH checkpoints don't have a registered enum and string (e.g. nbias below).
1648 One difficulty is the multilevel structure of the data which would need to be represented somehow. */
1650 int numBias;
1651 if (!bRead)
1653 numBias = awhHistory->bias.size();
1655 do_cpt_int_err(xd, "awh_nbias", &numBias, list);
1657 if (bRead)
1659 awhHistory->bias.resize(numBias);
1661 for (auto &bias : awhHistory->bias)
1663 ret = do_cpt_awh_bias(xd, bRead, fflags, &bias, list);
1664 if (ret)
1666 return ret;
1669 do_cpt_double_err(xd, "awh_potential_offset", &awhHistory->potentialOffset, list);
1671 return ret;
1674 static int do_cpt_files(XDR *xd, gmx_bool bRead,
1675 std::vector<gmx_file_position_t> *outputfiles,
1676 FILE *list, int file_version)
1678 gmx_off_t offset;
1679 gmx_off_t mask = 0xFFFFFFFFL;
1680 int offset_high, offset_low;
1681 char *buf;
1682 GMX_RELEASE_ASSERT(outputfiles, "Must have valid outputfiles");
1684 // Ensure that reading pre-allocates outputfiles, while writing
1685 // writes what is already there.
1686 int nfiles = outputfiles->size();
1687 if (do_cpt_int(xd, "number of output files", &nfiles, list) != 0)
1689 return -1;
1691 if (bRead)
1693 outputfiles->resize(nfiles);
1696 for (auto &outputfile : *outputfiles)
1698 /* 64-bit XDR numbers are not portable, so it is stored as separate high/low fractions */
1699 if (bRead)
1701 do_cpt_string_err(xd, bRead, "output filename", &buf, list);
1702 std::strncpy(outputfile.filename, buf, CPTSTRLEN-1);
1703 if (list == nullptr)
1705 sfree(buf);
1708 if (do_cpt_int(xd, "file_offset_high", &offset_high, list) != 0)
1710 return -1;
1712 if (do_cpt_int(xd, "file_offset_low", &offset_low, list) != 0)
1714 return -1;
1716 outputfile.offset = (static_cast<gmx_off_t>(offset_high) << 32 ) | ( static_cast<gmx_off_t>(offset_low) & mask );
1718 else
1720 buf = outputfile.filename;
1721 do_cpt_string_err(xd, bRead, "output filename", &buf, list);
1722 /* writing */
1723 offset = outputfile.offset;
1724 if (offset == -1)
1726 offset_low = -1;
1727 offset_high = -1;
1729 else
1731 offset_low = static_cast<int>(offset & mask);
1732 offset_high = static_cast<int>((offset >> 32) & mask);
1734 if (do_cpt_int(xd, "file_offset_high", &offset_high, list) != 0)
1736 return -1;
1738 if (do_cpt_int(xd, "file_offset_low", &offset_low, list) != 0)
1740 return -1;
1743 if (file_version >= 8)
1745 if (do_cpt_int(xd, "file_checksum_size", &outputfile.chksum_size,
1746 list) != 0)
1748 return -1;
1750 if (do_cpt_u_chars(xd, "file_checksum", 16, outputfile.chksum, list) != 0)
1752 return -1;
1755 else
1757 outputfile.chksum_size = -1;
1760 return 0;
1764 void write_checkpoint(const char *fn, gmx_bool bNumberAndKeep,
1765 FILE *fplog, t_commrec *cr,
1766 ivec domdecCells, int nppnodes,
1767 int eIntegrator, int simulation_part,
1768 gmx_bool bExpanded, int elamstats,
1769 gmx_int64_t step, double t,
1770 t_state *state, ObservablesHistory *observablesHistory)
1772 t_fileio *fp;
1773 int file_version;
1774 char *version;
1775 char *btime;
1776 char *buser;
1777 char *bhost;
1778 int double_prec;
1779 char *fprog;
1780 char *fntemp; /* the temporary checkpoint file name */
1781 char timebuf[STRLEN];
1782 int npmenodes;
1783 char buf[1024], suffix[5+STEPSTRSIZE], sbuf[STEPSTRSIZE];
1784 char *ftime;
1785 t_fileio *ret;
1787 if (DOMAINDECOMP(cr))
1789 npmenodes = cr->npmenodes;
1791 else
1793 npmenodes = 0;
1796 #if !GMX_NO_RENAME
1797 /* make the new temporary filename */
1798 snew(fntemp, std::strlen(fn)+5+STEPSTRSIZE);
1799 std::strcpy(fntemp, fn);
1800 fntemp[std::strlen(fn) - std::strlen(ftp2ext(fn2ftp(fn))) - 1] = '\0';
1801 sprintf(suffix, "_%s%s", "step", gmx_step_str(step, sbuf));
1802 std::strcat(fntemp, suffix);
1803 std::strcat(fntemp, fn+std::strlen(fn) - std::strlen(ftp2ext(fn2ftp(fn))) - 1);
1804 #else
1805 /* if we can't rename, we just overwrite the cpt file.
1806 * dangerous if interrupted.
1808 snew(fntemp, std::strlen(fn));
1809 std::strcpy(fntemp, fn);
1810 #endif
1811 gmx_format_current_time(timebuf, STRLEN);
1813 if (fplog)
1815 fprintf(fplog, "Writing checkpoint, step %s at %s\n\n",
1816 gmx_step_str(step, buf), timebuf);
1819 /* Get offsets for open files */
1820 auto outputfiles = gmx_fio_get_output_file_positions();
1822 fp = gmx_fio_open(fntemp, "w");
1824 int flags_eks;
1825 if (state->ekinstate.bUpToDate)
1827 flags_eks =
1828 ((1<<eeksEKIN_N) | (1<<eeksEKINH) | (1<<eeksEKINF) |
1829 (1<<eeksEKINO) | (1<<eeksEKINSCALEF) | (1<<eeksEKINSCALEH) |
1830 (1<<eeksVSCALE) | (1<<eeksDEKINDL) | (1<<eeksMVCOS));
1832 else
1834 flags_eks = 0;
1837 energyhistory_t *enerhist = observablesHistory->energyHistory.get();
1838 int flags_enh = 0;
1839 if (enerhist != nullptr && (enerhist->nsum > 0 || enerhist->nsum_sim > 0))
1841 flags_enh |= (1<<eenhENERGY_N) | (1<<eenhENERGY_NSTEPS) | (1<<eenhENERGY_NSTEPS_SIM);
1842 if (enerhist->nsum > 0)
1844 flags_enh |= ((1<<eenhENERGY_AVER) | (1<<eenhENERGY_SUM) |
1845 (1<<eenhENERGY_NSUM));
1847 if (enerhist->nsum_sim > 0)
1849 flags_enh |= ((1<<eenhENERGY_SUM_SIM) | (1<<eenhENERGY_NSUM_SIM));
1851 if (enerhist->deltaHForeignLambdas != nullptr)
1853 flags_enh |= ( (1<< eenhENERGY_DELTA_H_NN) |
1854 (1<< eenhENERGY_DELTA_H_LIST) |
1855 (1<< eenhENERGY_DELTA_H_STARTTIME) |
1856 (1<< eenhENERGY_DELTA_H_STARTLAMBDA) );
1860 int flags_dfh;
1861 if (bExpanded)
1863 flags_dfh = ((1<<edfhBEQUIL) | (1<<edfhNATLAMBDA) | (1<<edfhSUMWEIGHTS) | (1<<edfhSUMDG) |
1864 (1<<edfhTIJ) | (1<<edfhTIJEMP));
1865 if (EWL(elamstats))
1867 flags_dfh |= ((1<<edfhWLDELTA) | (1<<edfhWLHISTO));
1869 if ((elamstats == elamstatsMINVAR) || (elamstats == elamstatsBARKER) || (elamstats == elamstatsMETROPOLIS))
1871 flags_dfh |= ((1<<edfhACCUMP) | (1<<edfhACCUMM) | (1<<edfhACCUMP2) | (1<<edfhACCUMM2)
1872 | (1<<edfhSUMMINVAR) | (1<<edfhSUMVAR));
1875 else
1877 flags_dfh = 0;
1880 int flags_awhh = 0;
1881 if (state->awhHistory != nullptr && state->awhHistory->bias.size() > 0)
1883 flags_awhh |= ( (1 << eawhhIN_INITIAL) |
1884 (1 << eawhhEQUILIBRATEHISTOGRAM) |
1885 (1 << eawhhHISTSIZE) |
1886 (1 << eawhhNPOINTS) |
1887 (1 << eawhhCOORDPOINT) |
1888 (1 << eawhhUMBRELLAGRIDPOINT) |
1889 (1 << eawhhUPDATELIST) |
1890 (1 << eawhhLOGSCALEDSAMPLEWEIGHT) |
1891 (1 << eawhhNUMUPDATES) |
1892 (1 << eawhhFORCECORRELATIONGRID));
1895 /* We can check many more things now (CPU, acceleration, etc), but
1896 * it is highly unlikely to have two separate builds with exactly
1897 * the same version, user, time, and build host!
1900 version = gmx_strdup(gmx_version());
1901 btime = gmx_strdup(BUILD_TIME);
1902 buser = gmx_strdup(BUILD_USER);
1903 bhost = gmx_strdup(BUILD_HOST);
1905 double_prec = GMX_DOUBLE;
1906 fprog = gmx_strdup(gmx::getProgramContext().fullBinaryPath());
1908 ftime = &(timebuf[0]);
1910 int nlambda = (state->dfhist ? state->dfhist->nlambda : 0);
1912 edsamhistory_t *edsamhist = observablesHistory->edsamHistory.get();
1913 int nED = (edsamhist ? edsamhist->nED : 0);
1915 swaphistory_t *swaphist = observablesHistory->swapHistory.get();
1916 int eSwapCoords = (swaphist ? swaphist->eSwapCoords : eswapNO);
1918 do_cpt_header(gmx_fio_getxdr(fp), FALSE, &file_version,
1919 &version, &btime, &buser, &bhost, &double_prec, &fprog, &ftime,
1920 &eIntegrator, &simulation_part, &step, &t, &nppnodes,
1921 DOMAINDECOMP(cr) ? domdecCells : nullptr, &npmenodes,
1922 &state->natoms, &state->ngtc, &state->nnhpres,
1923 &state->nhchainlength, &nlambda, &state->flags, &flags_eks, &flags_enh, &flags_dfh, &flags_awhh,
1924 &nED, &eSwapCoords,
1925 nullptr);
1927 sfree(version);
1928 sfree(btime);
1929 sfree(buser);
1930 sfree(bhost);
1931 sfree(fprog);
1933 if ((do_cpt_state(gmx_fio_getxdr(fp), state->flags, state, nullptr) < 0) ||
1934 (do_cpt_ekinstate(gmx_fio_getxdr(fp), flags_eks, &state->ekinstate, nullptr) < 0) ||
1935 (do_cpt_enerhist(gmx_fio_getxdr(fp), FALSE, flags_enh, enerhist, nullptr) < 0) ||
1936 (do_cpt_df_hist(gmx_fio_getxdr(fp), flags_dfh, nlambda, &state->dfhist, nullptr) < 0) ||
1937 (do_cpt_EDstate(gmx_fio_getxdr(fp), FALSE, nED, edsamhist, nullptr) < 0) ||
1938 (do_cpt_awh(gmx_fio_getxdr(fp), FALSE, flags_awhh, state->awhHistory.get(), NULL) < 0) ||
1939 (do_cpt_swapstate(gmx_fio_getxdr(fp), FALSE, eSwapCoords, swaphist, nullptr) < 0) ||
1940 (do_cpt_files(gmx_fio_getxdr(fp), FALSE, &outputfiles, nullptr,
1941 file_version) < 0))
1943 gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
1946 do_cpt_footer(gmx_fio_getxdr(fp), file_version);
1948 /* we really, REALLY, want to make sure to physically write the checkpoint,
1949 and all the files it depends on, out to disk. Because we've
1950 opened the checkpoint with gmx_fio_open(), it's in our list
1951 of open files. */
1952 ret = gmx_fio_all_output_fsync();
1954 if (ret)
1956 char buf[STRLEN];
1957 sprintf(buf,
1958 "Cannot fsync '%s'; maybe you are out of disk space?",
1959 gmx_fio_getname(ret));
1961 if (getenv(GMX_IGNORE_FSYNC_FAILURE_ENV) == nullptr)
1963 gmx_file(buf);
1965 else
1967 gmx_warning(buf);
1971 if (gmx_fio_close(fp) != 0)
1973 gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
1976 /* we don't move the checkpoint if the user specified they didn't want it,
1977 or if the fsyncs failed */
1978 #if !GMX_NO_RENAME
1979 if (!bNumberAndKeep && !ret)
1981 if (gmx_fexist(fn))
1983 /* Rename the previous checkpoint file */
1984 std::strcpy(buf, fn);
1985 buf[std::strlen(fn) - std::strlen(ftp2ext(fn2ftp(fn))) - 1] = '\0';
1986 std::strcat(buf, "_prev");
1987 std::strcat(buf, fn+std::strlen(fn) - std::strlen(ftp2ext(fn2ftp(fn))) - 1);
1988 #ifndef GMX_FAHCORE
1989 /* we copy here so that if something goes wrong between now and
1990 * the rename below, there's always a state.cpt.
1991 * If renames are atomic (such as in POSIX systems),
1992 * this copying should be unneccesary.
1994 gmx_file_copy(fn, buf, FALSE);
1995 /* We don't really care if this fails:
1996 * there's already a new checkpoint.
1998 #else
1999 gmx_file_rename(fn, buf);
2000 #endif
2002 if (gmx_file_rename(fntemp, fn) != 0)
2004 gmx_file("Cannot rename checkpoint file; maybe you are out of disk space?");
2007 #endif /* GMX_NO_RENAME */
2009 sfree(fntemp);
2011 #ifdef GMX_FAHCORE
2012 /*code for alternate checkpointing scheme. moved from top of loop over
2013 steps */
2014 fcRequestCheckPoint();
2015 if (fcCheckPointParallel( cr->nodeid, NULL, 0) == 0)
2017 gmx_fatal( 3, __FILE__, __LINE__, "Checkpoint error on step %d\n", step );
2019 #endif /* end GMX_FAHCORE block */
2022 static void print_flag_mismatch(FILE *fplog, int sflags, int fflags)
2024 int i;
2026 fprintf(fplog, "\nState entry mismatch between the simulation and the checkpoint file\n");
2027 fprintf(fplog, "Entries which are not present in the checkpoint file will not be updated\n");
2028 fprintf(fplog, " %24s %11s %11s\n", "", "simulation", "checkpoint");
2029 for (i = 0; i < estNR; i++)
2031 if ((sflags & (1<<i)) || (fflags & (1<<i)))
2033 fprintf(fplog, " %24s %11s %11s\n",
2034 est_names[i],
2035 (sflags & (1<<i)) ? " present " : "not present",
2036 (fflags & (1<<i)) ? " present " : "not present");
2041 static void check_int(FILE *fplog, const char *type, int p, int f, gmx_bool *mm)
2043 FILE *fp = fplog ? fplog : stderr;
2045 if (p != f)
2047 fprintf(fp, " %s mismatch,\n", type);
2048 fprintf(fp, " current program: %d\n", p);
2049 fprintf(fp, " checkpoint file: %d\n", f);
2050 fprintf(fp, "\n");
2051 *mm = TRUE;
2055 static void check_string(FILE *fplog, const char *type, const char *p,
2056 const char *f, gmx_bool *mm)
2058 FILE *fp = fplog ? fplog : stderr;
2060 if (std::strcmp(p, f) != 0)
2062 fprintf(fp, " %s mismatch,\n", type);
2063 fprintf(fp, " current program: %s\n", p);
2064 fprintf(fp, " checkpoint file: %s\n", f);
2065 fprintf(fp, "\n");
2066 *mm = TRUE;
2070 static void check_match(FILE *fplog,
2071 char *version,
2072 char *btime, char *buser, char *bhost, int double_prec,
2073 char *fprog,
2074 const t_commrec *cr, int npp_f, int npme_f,
2075 const ivec dd_nc, const ivec dd_nc_f,
2076 gmx_bool reproducibilityRequested)
2078 /* Note that this check_string on the version will also print a message
2079 * when only the minor version differs. But we only print a warning
2080 * message further down with reproducibilityRequested=TRUE.
2082 gmx_bool versionDiffers = FALSE;
2083 check_string(fplog, "Version", gmx_version(), version, &versionDiffers);
2085 gmx_bool precisionDiffers = FALSE;
2086 check_int (fplog, "Double prec.", GMX_DOUBLE, double_prec, &precisionDiffers);
2087 if (precisionDiffers)
2089 const char msg_precision_difference[] =
2090 "You are continuing a simulation with a different precision. Not matching\n"
2091 "single/double precision will lead to precision or performance loss.\n";
2092 fprintf(stderr, "%s\n", msg_precision_difference);
2093 if (fplog)
2095 fprintf(fplog, "%s\n", msg_precision_difference);
2099 gmx_bool mm = (versionDiffers || precisionDiffers);
2101 if (reproducibilityRequested)
2103 check_string(fplog, "Build time", BUILD_TIME, btime, &mm);
2104 check_string(fplog, "Build user", BUILD_USER, buser, &mm);
2105 check_string(fplog, "Build host", BUILD_HOST, bhost, &mm);
2106 check_string(fplog, "Program name", gmx::getProgramContext().fullBinaryPath(), fprog, &mm);
2108 check_int (fplog, "#ranks", cr->nnodes, npp_f+npme_f, &mm);
2111 if (cr->nnodes > 1 && reproducibilityRequested)
2113 check_int (fplog, "#PME-ranks", cr->npmenodes, npme_f, &mm);
2115 int npp = cr->nnodes;
2116 if (cr->npmenodes >= 0)
2118 npp -= cr->npmenodes;
2120 if (npp == npp_f)
2122 check_int (fplog, "#DD-cells[x]", dd_nc[XX], dd_nc_f[XX], &mm);
2123 check_int (fplog, "#DD-cells[y]", dd_nc[YY], dd_nc_f[YY], &mm);
2124 check_int (fplog, "#DD-cells[z]", dd_nc[ZZ], dd_nc_f[ZZ], &mm);
2128 if (mm)
2130 /* Gromacs should be able to continue from checkpoints between
2131 * different patch level versions, but we do not guarantee
2132 * compatibility between different major/minor versions - check this.
2134 int gmx_major;
2135 int cpt_major;
2136 sscanf(gmx_version(), "%5d", &gmx_major);
2137 int ret = sscanf(version, "%5d", &cpt_major);
2138 gmx_bool majorVersionDiffers = (ret < 1 || gmx_major != cpt_major);
2140 const char msg_major_version_difference[] =
2141 "The current GROMACS major version is not identical to the one that\n"
2142 "generated the checkpoint file. In principle GROMACS does not support\n"
2143 "continuation from checkpoints between different versions, so we advise\n"
2144 "against this. If you still want to try your luck we recommend that you use\n"
2145 "the -noappend flag to keep your output files from the two versions separate.\n"
2146 "This might also work around errors where the output fields in the energy\n"
2147 "file have changed between the different versions.\n";
2149 const char msg_mismatch_notice[] =
2150 "GROMACS patchlevel, binary or parallel settings differ from previous run.\n"
2151 "Continuation is exact, but not guaranteed to be binary identical.\n";
2153 const char msg_logdetails[] =
2154 "See the log file for details.\n";
2156 if (majorVersionDiffers)
2158 fprintf(stderr, "%s%s\n", msg_major_version_difference, fplog ? msg_logdetails : "");
2160 if (fplog)
2162 fprintf(fplog, "%s\n", msg_major_version_difference);
2165 else if (reproducibilityRequested)
2167 /* Major & minor versions match at least, but something is different. */
2168 fprintf(stderr, "%s%s\n", msg_mismatch_notice, fplog ? msg_logdetails : "");
2169 if (fplog)
2171 fprintf(fplog, "%s\n", msg_mismatch_notice);
2177 static void read_checkpoint(const char *fn, FILE **pfplog,
2178 const t_commrec *cr,
2179 const ivec dd_nc,
2180 int eIntegrator, int *init_fep_state, gmx_int64_t *step, double *t,
2181 t_state *state, gmx_bool *bReadEkin,
2182 ObservablesHistory *observablesHistory,
2183 int *simulation_part,
2184 gmx_bool bAppendOutputFiles, gmx_bool bForceAppend,
2185 gmx_bool reproducibilityRequested)
2187 t_fileio *fp;
2188 int j, rc;
2189 int file_version;
2190 char *version, *btime, *buser, *bhost, *fprog, *ftime;
2191 int double_prec;
2192 char buf[STEPSTRSIZE];
2193 int eIntegrator_f, nppnodes_f, npmenodes_f;
2194 ivec dd_nc_f;
2195 int natoms, ngtc, nnhpres, nhchainlength, nlambda, fflags, flags_eks, flags_enh, flags_dfh, flags_awhh;
2196 int nED, eSwapCoords;
2197 int ret;
2198 t_fileio *chksum_file;
2199 FILE * fplog = *pfplog;
2200 unsigned char digest[16];
2201 #if !defined __native_client__ && !GMX_NATIVE_WINDOWS
2202 struct flock fl; /* don't initialize here: the struct order is OS
2203 dependent! */
2204 #endif
2206 const char *int_warn =
2207 "WARNING: The checkpoint file was generated with integrator %s,\n"
2208 " while the simulation uses integrator %s\n\n";
2210 #if !defined __native_client__ && !GMX_NATIVE_WINDOWS
2211 fl.l_type = F_WRLCK;
2212 fl.l_whence = SEEK_SET;
2213 fl.l_start = 0;
2214 fl.l_len = 0;
2215 fl.l_pid = 0;
2216 #endif
2218 fp = gmx_fio_open(fn, "r");
2219 do_cpt_header(gmx_fio_getxdr(fp), TRUE, &file_version,
2220 &version, &btime, &buser, &bhost, &double_prec, &fprog, &ftime,
2221 &eIntegrator_f, simulation_part, step, t,
2222 &nppnodes_f, dd_nc_f, &npmenodes_f,
2223 &natoms, &ngtc, &nnhpres, &nhchainlength, &nlambda,
2224 &fflags, &flags_eks, &flags_enh, &flags_dfh, &flags_awhh,
2225 &nED, &eSwapCoords, nullptr);
2227 if (bAppendOutputFiles &&
2228 file_version >= 13 && double_prec != GMX_DOUBLE)
2230 gmx_fatal(FARGS, "Output file appending requested, but the code and checkpoint file precision (single/double) don't match");
2233 if (cr == nullptr || MASTER(cr))
2235 fprintf(stderr, "\nReading checkpoint file %s generated: %s\n\n",
2236 fn, ftime);
2239 /* This will not be written if we do appending, since fplog is still NULL then */
2240 if (fplog)
2242 fprintf(fplog, "\n");
2243 fprintf(fplog, "Reading checkpoint file %s\n", fn);
2244 fprintf(fplog, " file generated by: %s\n", fprog);
2245 fprintf(fplog, " file generated at: %s\n", ftime);
2246 fprintf(fplog, " GROMACS build time: %s\n", btime);
2247 fprintf(fplog, " GROMACS build user: %s\n", buser);
2248 fprintf(fplog, " GROMACS build host: %s\n", bhost);
2249 fprintf(fplog, " GROMACS double prec.: %d\n", double_prec);
2250 fprintf(fplog, " simulation part #: %d\n", *simulation_part);
2251 fprintf(fplog, " step: %s\n", gmx_step_str(*step, buf));
2252 fprintf(fplog, " time: %f\n", *t);
2253 fprintf(fplog, "\n");
2256 if (natoms != state->natoms)
2258 gmx_fatal(FARGS, "Checkpoint file is for a system of %d atoms, while the current system consists of %d atoms", natoms, state->natoms);
2260 if (ngtc != state->ngtc)
2262 gmx_fatal(FARGS, "Checkpoint file is for a system of %d T-coupling groups, while the current system consists of %d T-coupling groups", ngtc, state->ngtc);
2264 if (nnhpres != state->nnhpres)
2266 gmx_fatal(FARGS, "Checkpoint file is for a system of %d NH-pressure-coupling variables, while the current system consists of %d NH-pressure-coupling variables", nnhpres, state->nnhpres);
2269 int nlambdaHistory = (state->dfhist ? state->dfhist->nlambda : 0);
2270 if (nlambda != nlambdaHistory)
2272 gmx_fatal(FARGS, "Checkpoint file is for a system with %d lambda states, while the current system consists of %d lambda states", nlambda, nlambdaHistory);
2275 init_gtc_state(state, state->ngtc, state->nnhpres, nhchainlength); /* need to keep this here to keep the tpr format working */
2276 /* write over whatever was read; we use the number of Nose-Hoover chains from the checkpoint */
2278 if (eIntegrator_f != eIntegrator)
2280 if (MASTER(cr))
2282 fprintf(stderr, int_warn, EI(eIntegrator_f), EI(eIntegrator));
2284 if (bAppendOutputFiles)
2286 gmx_fatal(FARGS,
2287 "Output file appending requested, but input/checkpoint integrators do not match.\n"
2288 "Stopping the run to prevent you from ruining all your data...\n"
2289 "If you _really_ know what you are doing, try with the -noappend option.\n");
2291 if (fplog)
2293 fprintf(fplog, int_warn, EI(eIntegrator_f), EI(eIntegrator));
2297 if (fflags != state->flags)
2300 if (MASTER(cr))
2302 if (bAppendOutputFiles)
2304 gmx_fatal(FARGS,
2305 "Output file appending requested, but input and checkpoint states are not identical.\n"
2306 "Stopping the run to prevent you from ruining all your data...\n"
2307 "You can try with the -noappend option, and get more info in the log file.\n");
2310 if (getenv("GMX_ALLOW_CPT_MISMATCH") == nullptr)
2312 gmx_fatal(FARGS, "You seem to have switched ensemble, integrator, T and/or P-coupling algorithm between the cpt and tpr file, or switched GROMACS version. The recommended way of doing this is passing the cpt file to grompp (with option -t) instead of to mdrun. If you know what you are doing, you can override this error by setting the env.var. GMX_ALLOW_CPT_MISMATCH");
2314 else
2316 fprintf(stderr,
2317 "WARNING: The checkpoint state entries do not match the simulation,\n"
2318 " see the log file for details\n\n");
2322 if (fplog)
2324 print_flag_mismatch(fplog, state->flags, fflags);
2327 else
2329 if (MASTER(cr))
2331 check_match(fplog, version, btime, buser, bhost, double_prec, fprog,
2332 cr, nppnodes_f, npmenodes_f, dd_nc, dd_nc_f,
2333 reproducibilityRequested);
2336 ret = do_cpt_state(gmx_fio_getxdr(fp), fflags, state, nullptr);
2337 *init_fep_state = state->fep_state; /* there should be a better way to do this than setting it here.
2338 Investigate for 5.0. */
2339 if (ret)
2341 cp_error();
2343 ret = do_cpt_ekinstate(gmx_fio_getxdr(fp), flags_eks, &state->ekinstate, nullptr);
2344 if (ret)
2346 cp_error();
2348 *bReadEkin = ((flags_eks & (1<<eeksEKINH)) || (flags_eks & (1<<eeksEKINF)) || (flags_eks & (1<<eeksEKINO)) ||
2349 ((flags_eks & (1<<eeksEKINSCALEF)) | (flags_eks & (1<<eeksEKINSCALEH)) | (flags_eks & (1<<eeksVSCALE))));
2351 if (flags_enh && observablesHistory->energyHistory == nullptr)
2353 observablesHistory->energyHistory = std::unique_ptr<energyhistory_t>(new energyhistory_t {});
2355 ret = do_cpt_enerhist(gmx_fio_getxdr(fp), TRUE,
2356 flags_enh, observablesHistory->energyHistory.get(), nullptr);
2357 if (ret)
2359 cp_error();
2362 if (file_version < 6)
2364 const char *warn = "Reading checkpoint file in old format, assuming that the run that generated this file started at step 0, if this is not the case the averages stored in the energy file will be incorrect.";
2366 fprintf(stderr, "\nWARNING: %s\n\n", warn);
2367 if (fplog)
2369 fprintf(fplog, "\nWARNING: %s\n\n", warn);
2371 observablesHistory->energyHistory->nsum = *step;
2372 observablesHistory->energyHistory->nsum_sim = *step;
2375 ret = do_cpt_df_hist(gmx_fio_getxdr(fp), flags_dfh, nlambda, &state->dfhist, nullptr);
2376 if (ret)
2378 cp_error();
2381 if (nED > 0 && observablesHistory->edsamHistory == nullptr)
2383 observablesHistory->edsamHistory = std::unique_ptr<edsamhistory_t>(new edsamhistory_t {});
2385 ret = do_cpt_EDstate(gmx_fio_getxdr(fp), TRUE, nED, observablesHistory->edsamHistory.get(), nullptr);
2386 if (ret)
2388 cp_error();
2391 if (flags_awhh != 0 && state->awhHistory == nullptr)
2393 state->awhHistory = std::shared_ptr<gmx::AwhHistory>(new gmx::AwhHistory());
2395 ret = do_cpt_awh(gmx_fio_getxdr(fp), TRUE,
2396 flags_awhh, state->awhHistory.get(), NULL);
2397 if (ret)
2399 cp_error();
2402 if (eSwapCoords != eswapNO && observablesHistory->swapHistory == nullptr)
2404 observablesHistory->swapHistory = std::unique_ptr<swaphistory_t>(new swaphistory_t {});
2406 ret = do_cpt_swapstate(gmx_fio_getxdr(fp), TRUE, eSwapCoords, observablesHistory->swapHistory.get(), nullptr);
2407 if (ret)
2409 cp_error();
2412 std::vector<gmx_file_position_t> outputfiles;
2413 ret = do_cpt_files(gmx_fio_getxdr(fp), TRUE, &outputfiles, nullptr, file_version);
2414 if (ret)
2416 cp_error();
2419 ret = do_cpt_footer(gmx_fio_getxdr(fp), file_version);
2420 if (ret)
2422 cp_error();
2424 if (gmx_fio_close(fp) != 0)
2426 gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
2429 sfree(fprog);
2430 sfree(ftime);
2431 sfree(btime);
2432 sfree(buser);
2433 sfree(bhost);
2435 /* If the user wants to append to output files,
2436 * we use the file pointer positions of the output files stored
2437 * in the checkpoint file and truncate the files such that any frames
2438 * written after the checkpoint time are removed.
2439 * All files are md5sum checked such that we can be sure that
2440 * we do not truncate other (maybe imprortant) files.
2442 if (bAppendOutputFiles)
2444 if (outputfiles.empty())
2446 gmx_fatal(FARGS, "No names of output files were recorded in the checkpoint");
2448 if (fn2ftp(outputfiles[0].filename) != efLOG)
2450 /* make sure first file is log file so that it is OK to use it for
2451 * locking
2453 gmx_fatal(FARGS, "The first output file should always be the log "
2454 "file but instead is: %s. Cannot do appending because of this condition.", outputfiles[0].filename);
2456 bool firstFile = true;
2457 for (const auto &outputfile : outputfiles)
2459 if (outputfile.offset < 0)
2461 gmx_fatal(FARGS, "The original run wrote a file called '%s' which "
2462 "is larger than 2 GB, but mdrun did not support large file"
2463 " offsets. Can not append. Run mdrun with -noappend",
2464 outputfile.filename);
2466 #ifdef GMX_FAHCORE
2467 chksum_file = gmx_fio_open(outputfile.filename, "a");
2469 #else
2470 chksum_file = gmx_fio_open(outputfile.filename, "r+");
2472 /* lock log file */
2473 if (firstFile)
2475 /* Note that there are systems where the lock operation
2476 * will succeed, but a second process can also lock the file.
2477 * We should probably try to detect this.
2479 #if defined __native_client__
2480 errno = ENOSYS;
2481 if (1)
2483 #elif GMX_NATIVE_WINDOWS
2484 if (_locking(fileno(gmx_fio_getfp(chksum_file)), _LK_NBLCK, LONG_MAX) == -1)
2485 #else
2486 if (fcntl(fileno(gmx_fio_getfp(chksum_file)), F_SETLK, &fl) == -1)
2487 #endif
2489 if (errno == ENOSYS)
2491 if (!bForceAppend)
2493 gmx_fatal(FARGS, "File locking is not supported on this system. Use -noappend or specify -append explicitly to append anyhow.");
2495 else
2497 fprintf(stderr, "\nNOTE: File locking is not supported on this system, will not lock %s\n\n", outputfile.filename);
2498 if (fplog)
2500 fprintf(fplog, "\nNOTE: File locking not supported on this system, will not lock %s\n\n", outputfile.filename);
2504 else if (errno == EACCES || errno == EAGAIN)
2506 gmx_fatal(FARGS, "Failed to lock: %s. Already running "
2507 "simulation?", outputfile.filename);
2509 else
2511 gmx_fatal(FARGS, "Failed to lock: %s. %s.",
2512 outputfile.filename, std::strerror(errno));
2517 /* compute md5 chksum */
2518 if (outputfile.chksum_size != -1)
2520 if (gmx_fio_get_file_md5(chksum_file, outputfile.offset,
2521 digest) != outputfile.chksum_size) /*at the end of the call the file position is at the end of the file*/
2523 gmx_fatal(FARGS, "Can't read %d bytes of '%s' to compute checksum. The file has been replaced or its contents have been modified. Cannot do appending because of this condition.",
2524 outputfile.chksum_size,
2525 outputfile.filename);
2528 /* log file needs to be seeked in case we need to truncate
2529 * (other files are truncated below)*/
2530 if (firstFile)
2532 if (gmx_fio_seek(chksum_file, outputfile.offset))
2534 gmx_fatal(FARGS, "Seek error! Failed to truncate log-file: %s.", std::strerror(errno));
2537 #endif
2539 /* open log file here - so that lock is never lifted
2540 * after chksum is calculated */
2541 if (firstFile)
2543 *pfplog = gmx_fio_getfp(chksum_file);
2545 else
2547 gmx_fio_close(chksum_file);
2549 #ifndef GMX_FAHCORE
2550 /* compare md5 chksum */
2551 if (outputfile.chksum_size != -1 &&
2552 memcmp(digest, outputfile.chksum, 16) != 0)
2554 if (debug)
2556 fprintf(debug, "chksum for %s: ", outputfile.filename);
2557 for (j = 0; j < 16; j++)
2559 fprintf(debug, "%02x", digest[j]);
2561 fprintf(debug, "\n");
2563 gmx_fatal(FARGS, "Checksum wrong for '%s'. The file has been replaced or its contents have been modified. Cannot do appending because of this condition.",
2564 outputfile.filename);
2566 #endif
2569 if (!firstFile) /* log file is already seeked to correct position */
2571 #if !GMX_NATIVE_WINDOWS || !defined(GMX_FAHCORE)
2572 /* For FAHCORE, we do this elsewhere*/
2573 rc = gmx_truncate(outputfile.filename, outputfile.offset);
2574 if (rc != 0)
2576 gmx_fatal(FARGS, "Truncation of file %s failed. Cannot do appending because of this failure.", outputfile.filename);
2578 #endif
2580 firstFile = false;
2586 void load_checkpoint(const char *fn, FILE **fplog,
2587 const t_commrec *cr, const ivec dd_nc,
2588 t_inputrec *ir, t_state *state,
2589 gmx_bool *bReadEkin,
2590 ObservablesHistory *observablesHistory,
2591 gmx_bool bAppend, gmx_bool bForceAppend,
2592 gmx_bool reproducibilityRequested)
2594 gmx_int64_t step;
2595 double t;
2597 if (SIMMASTER(cr))
2599 /* Read the state from the checkpoint file */
2600 read_checkpoint(fn, fplog,
2601 cr, dd_nc,
2602 ir->eI, &(ir->fepvals->init_fep_state), &step, &t,
2603 state, bReadEkin, observablesHistory,
2604 &ir->simulation_part, bAppend, bForceAppend,
2605 reproducibilityRequested);
2607 if (PAR(cr))
2609 gmx_bcast(sizeof(step), &step, cr);
2610 gmx_bcast(sizeof(*bReadEkin), bReadEkin, cr);
2612 ir->bContinuation = TRUE;
2613 if (ir->nsteps >= 0)
2615 ir->nsteps += ir->init_step - step;
2617 ir->init_step = step;
2618 ir->simulation_part += 1;
2621 void read_checkpoint_part_and_step(const char *filename,
2622 int *simulation_part,
2623 gmx_int64_t *step)
2625 int file_version;
2626 char *version, *btime, *buser, *bhost, *fprog, *ftime;
2627 int double_prec;
2628 int eIntegrator;
2629 int nppnodes, npme;
2630 ivec dd_nc;
2631 int nlambda;
2632 int flags_eks, flags_enh, flags_dfh, flags_awhh;
2633 double t;
2634 t_state state;
2635 int nED, eSwapCoords;
2636 t_fileio *fp;
2638 if (filename == nullptr ||
2639 !gmx_fexist(filename) ||
2640 (!(fp = gmx_fio_open(filename, "r"))))
2642 *simulation_part = 0;
2643 *step = 0;
2644 return;
2647 /* Not calling initializing state before use is nasty, but all we
2648 do is read into its member variables and throw the struct away
2649 again immediately. */
2651 do_cpt_header(gmx_fio_getxdr(fp), TRUE, &file_version,
2652 &version, &btime, &buser, &bhost, &double_prec, &fprog, &ftime,
2653 &eIntegrator, simulation_part, step, &t, &nppnodes, dd_nc, &npme,
2654 &state.natoms, &state.ngtc, &state.nnhpres, &state.nhchainlength,
2655 &nlambda, &state.flags, &flags_eks, &flags_enh, &flags_dfh, &flags_awhh,
2656 &nED, &eSwapCoords, nullptr);
2658 gmx_fio_close(fp);
2661 static void read_checkpoint_data(t_fileio *fp, int *simulation_part,
2662 gmx_int64_t *step, double *t, t_state *state,
2663 std::vector<gmx_file_position_t> *outputfiles)
2665 int file_version;
2666 char *version, *btime, *buser, *bhost, *fprog, *ftime;
2667 int double_prec;
2668 int eIntegrator;
2669 int nppnodes, npme;
2670 ivec dd_nc;
2671 int nlambda;
2672 int flags_eks, flags_enh, flags_dfh, flags_awhh;
2673 int nED, eSwapCoords;
2674 int ret;
2676 do_cpt_header(gmx_fio_getxdr(fp), TRUE, &file_version,
2677 &version, &btime, &buser, &bhost, &double_prec, &fprog, &ftime,
2678 &eIntegrator, simulation_part, step, t, &nppnodes, dd_nc, &npme,
2679 &state->natoms, &state->ngtc, &state->nnhpres, &state->nhchainlength,
2680 &nlambda, &state->flags, &flags_eks, &flags_enh, &flags_dfh, &flags_awhh,
2681 &nED, &eSwapCoords, nullptr);
2682 ret =
2683 do_cpt_state(gmx_fio_getxdr(fp), state->flags, state, nullptr);
2684 if (ret)
2686 cp_error();
2688 ret = do_cpt_ekinstate(gmx_fio_getxdr(fp), flags_eks, &state->ekinstate, nullptr);
2689 if (ret)
2691 cp_error();
2694 energyhistory_t enerhist;
2695 ret = do_cpt_enerhist(gmx_fio_getxdr(fp), TRUE,
2696 flags_enh, &enerhist, nullptr);
2697 if (ret)
2699 cp_error();
2701 ret = do_cpt_df_hist(gmx_fio_getxdr(fp), flags_dfh, nlambda, &state->dfhist, nullptr);
2702 if (ret)
2704 cp_error();
2707 edsamhistory_t edsamhist = {};
2708 ret = do_cpt_EDstate(gmx_fio_getxdr(fp), TRUE, nED, &edsamhist, nullptr);
2709 if (ret)
2711 cp_error();
2714 ret = do_cpt_awh(gmx_fio_getxdr(fp), TRUE,
2715 flags_awhh, state->awhHistory.get(), NULL);
2716 if (ret)
2718 cp_error();
2721 swaphistory_t swaphist = {};
2722 ret = do_cpt_swapstate(gmx_fio_getxdr(fp), TRUE, eSwapCoords, &swaphist, nullptr);
2723 if (ret)
2725 cp_error();
2728 ret = do_cpt_files(gmx_fio_getxdr(fp), TRUE,
2729 outputfiles,
2730 nullptr, file_version);
2732 if (ret)
2734 cp_error();
2737 ret = do_cpt_footer(gmx_fio_getxdr(fp), file_version);
2738 if (ret)
2740 cp_error();
2743 sfree(fprog);
2744 sfree(ftime);
2745 sfree(btime);
2746 sfree(buser);
2747 sfree(bhost);
2750 void read_checkpoint_trxframe(t_fileio *fp, t_trxframe *fr)
2752 t_state state;
2753 int simulation_part;
2754 gmx_int64_t step;
2755 double t;
2757 std::vector<gmx_file_position_t> outputfiles;
2758 read_checkpoint_data(fp, &simulation_part, &step, &t, &state, &outputfiles);
2760 fr->natoms = state.natoms;
2761 fr->bStep = TRUE;
2762 fr->step = gmx_int64_to_int(step,
2763 "conversion of checkpoint to trajectory");
2764 fr->bTime = TRUE;
2765 fr->time = t;
2766 fr->bLambda = TRUE;
2767 fr->lambda = state.lambda[efptFEP];
2768 fr->fep_state = state.fep_state;
2769 fr->bAtoms = FALSE;
2770 fr->bX = (state.flags & (1<<estX));
2771 if (fr->bX)
2773 fr->x = makeRvecArray(state.x, state.natoms);
2775 fr->bV = (state.flags & (1<<estV));
2776 if (fr->bV)
2778 fr->v = makeRvecArray(state.v, state.natoms);
2780 fr->bF = FALSE;
2781 fr->bBox = (state.flags & (1<<estBOX));
2782 if (fr->bBox)
2784 copy_mat(state.box, fr->box);
2788 void list_checkpoint(const char *fn, FILE *out)
2790 t_fileio *fp;
2791 int file_version;
2792 char *version, *btime, *buser, *bhost, *fprog, *ftime;
2793 int double_prec;
2794 int eIntegrator, simulation_part, nppnodes, npme;
2795 gmx_int64_t step;
2796 double t;
2797 ivec dd_nc;
2798 int nlambda;
2799 int flags_eks, flags_enh, flags_dfh, flags_awhh;;
2800 int nED, eSwapCoords;
2801 int ret;
2803 t_state state;
2805 fp = gmx_fio_open(fn, "r");
2806 do_cpt_header(gmx_fio_getxdr(fp), TRUE, &file_version,
2807 &version, &btime, &buser, &bhost, &double_prec, &fprog, &ftime,
2808 &eIntegrator, &simulation_part, &step, &t, &nppnodes, dd_nc, &npme,
2809 &state.natoms, &state.ngtc, &state.nnhpres, &state.nhchainlength,
2810 &nlambda, &state.flags,
2811 &flags_eks, &flags_enh, &flags_dfh, &flags_awhh, &nED, &eSwapCoords,
2812 out);
2813 ret = do_cpt_state(gmx_fio_getxdr(fp), state.flags, &state, out);
2814 if (ret)
2816 cp_error();
2818 ret = do_cpt_ekinstate(gmx_fio_getxdr(fp), flags_eks, &state.ekinstate, out);
2819 if (ret)
2821 cp_error();
2824 energyhistory_t enerhist;
2825 ret = do_cpt_enerhist(gmx_fio_getxdr(fp), TRUE,
2826 flags_enh, &enerhist, out);
2828 if (ret == 0)
2830 ret = do_cpt_df_hist(gmx_fio_getxdr(fp),
2831 flags_dfh, nlambda, &state.dfhist, out);
2834 if (ret == 0)
2836 edsamhistory_t edsamhist = {};
2837 ret = do_cpt_EDstate(gmx_fio_getxdr(fp), TRUE, nED, &edsamhist, out);
2840 if (ret == 0)
2842 ret = do_cpt_awh(gmx_fio_getxdr(fp), TRUE,
2843 flags_awhh, state.awhHistory.get(), out);
2846 if (ret == 0)
2848 swaphistory_t swaphist = {};
2849 ret = do_cpt_swapstate(gmx_fio_getxdr(fp), TRUE, eSwapCoords, &swaphist, out);
2852 if (ret == 0)
2854 std::vector<gmx_file_position_t> outputfiles;
2855 ret = do_cpt_files(gmx_fio_getxdr(fp), TRUE, &outputfiles, out, file_version);
2858 if (ret == 0)
2860 ret = do_cpt_footer(gmx_fio_getxdr(fp), file_version);
2863 if (ret)
2865 cp_warning(out);
2867 if (gmx_fio_close(fp) != 0)
2869 gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
2873 /* This routine cannot print tons of data, since it is called before the log file is opened. */
2874 void
2875 read_checkpoint_simulation_part_and_filenames(t_fileio *fp,
2876 int *simulation_part,
2877 std::vector<gmx_file_position_t> *outputfiles)
2879 gmx_int64_t step = 0;
2880 double t;
2881 t_state state;
2883 read_checkpoint_data(fp, simulation_part, &step, &t, &state, outputfiles);
2884 if (gmx_fio_close(fp) != 0)
2886 gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");