2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2008,2009,2010,2011,2012 by the GROMACS development team.
5 * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
6 * Copyright (c) 2018,2019,2020,2021, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
38 /* The source code in this file should be thread-safe.
39 Please keep it that way. */
42 #include "checkpoint.h"
51 #include "buildinfo.h"
52 #include "gromacs/fileio/filetypes.h"
53 #include "gromacs/fileio/gmxfio.h"
54 #include "gromacs/fileio/gmxfio_xdr.h"
55 #include "gromacs/fileio/xdr_datatype.h"
56 #include "gromacs/fileio/xdrf.h"
57 #include "gromacs/gmxlib/network.h"
58 #include "gromacs/math/vec.h"
59 #include "gromacs/math/vecdump.h"
60 #include "gromacs/math/vectypes.h"
61 #include "gromacs/mdtypes/awh_correlation_history.h"
62 #include "gromacs/mdtypes/awh_history.h"
63 #include "gromacs/mdtypes/checkpointdata.h"
64 #include "gromacs/mdtypes/commrec.h"
65 #include "gromacs/mdtypes/df_history.h"
66 #include "gromacs/mdtypes/edsamhistory.h"
67 #include "gromacs/mdtypes/energyhistory.h"
68 #include "gromacs/mdtypes/inputrec.h"
69 #include "gromacs/mdtypes/md_enums.h"
70 #include "gromacs/mdtypes/mdrunoptions.h"
71 #include "gromacs/mdtypes/observableshistory.h"
72 #include "gromacs/mdtypes/pullhistory.h"
73 #include "gromacs/mdtypes/state.h"
74 #include "gromacs/mdtypes/swaphistory.h"
75 #include "gromacs/modularsimulator/modularsimulator.h"
76 #include "gromacs/trajectory/trajectoryframe.h"
77 #include "gromacs/utility/arrayref.h"
78 #include "gromacs/utility/baseversion.h"
79 #include "gromacs/utility/cstringutil.h"
80 #include "gromacs/utility/fatalerror.h"
81 #include "gromacs/utility/futil.h"
82 #include "gromacs/utility/gmxassert.h"
83 #include "gromacs/utility/int64_to_int.h"
84 #include "gromacs/utility/keyvaluetree.h"
85 #include "gromacs/utility/keyvaluetreebuilder.h"
86 #include "gromacs/utility/keyvaluetreeserializer.h"
87 #include "gromacs/utility/mdmodulenotification.h"
88 #include "gromacs/utility/programcontext.h"
89 #include "gromacs/utility/smalloc.h"
90 #include "gromacs/utility/sysinfo.h"
91 #include "gromacs/utility/textwriter.h"
92 #include "gromacs/utility/txtdump.h"
94 #define CPT_MAGIC1 171817
95 #define CPT_MAGIC2 171819
100 template<typename ValueType>
101 void readKvtCheckpointValue(compat::not_null<ValueType*> value,
102 const std::string& name,
103 const std::string& identifier,
104 const KeyValueTreeObject& kvt)
106 const std::string key = identifier + "-" + name;
107 if (!kvt.keyExists(key))
109 std::string errorMessage = "Cannot read requested checkpoint value " + key + " .";
110 GMX_THROW(InternalError(errorMessage));
112 *value = kvt[key].cast<ValueType>();
115 template void readKvtCheckpointValue(compat::not_null<std::int64_t*> value,
116 const std::string& name,
117 const std::string& identifier,
118 const KeyValueTreeObject& kvt);
119 template void readKvtCheckpointValue(compat::not_null<real*> value,
120 const std::string& name,
121 const std::string& identifier,
122 const KeyValueTreeObject& kvt);
124 template<typename ValueType>
125 void writeKvtCheckpointValue(const ValueType& value,
126 const std::string& name,
127 const std::string& identifier,
128 KeyValueTreeObjectBuilder kvtBuilder)
130 kvtBuilder.addValue<ValueType>(identifier + "-" + name, value);
133 template void writeKvtCheckpointValue(const std::int64_t& value,
134 const std::string& name,
135 const std::string& identifier,
136 KeyValueTreeObjectBuilder kvtBuilder);
137 template void writeKvtCheckpointValue(const real& value,
138 const std::string& name,
139 const std::string& identifier,
140 KeyValueTreeObjectBuilder kvtBuilder);
145 /*! \brief Enum of values that describe the contents of a cpt file
146 * whose format matches a version number
148 * The enum helps the code be more self-documenting and ensure merges
149 * do not silently resolve when two patches make the same bump. When
150 * adding new functionality, add a new element just above cptv_Count
151 * in this enumeration, and write code below that does the right thing
152 * according to the value of file_version.
156 cptv_Unknown = 17, /**< Version before numbering scheme */
157 cptv_RemoveBuildMachineInformation, /**< remove functionality that makes mdrun builds non-reproducible */
158 cptv_ComPrevStepAsPullGroupReference, /**< Allow using COM of previous step as pull group PBC reference */
159 cptv_PullAverage, /**< Added possibility to output average pull force and position */
160 cptv_MdModules, /**< Added checkpointing for MdModules */
161 cptv_ModularSimulator, /**< Added checkpointing for modular simulator */
162 cptv_Count /**< the total number of cptv versions */
165 /*! \brief Version number of the file format written to checkpoint
166 * files by this version of the code.
168 * cpt_version should normally only be changed, via adding a new field
169 * to cptv enumeration, when the header or footer format changes.
171 * The state data format itself is backward and forward compatible.
172 * But old code can not read a new entry that is present in the file
173 * (but can read a new format when new entries are not present).
175 * The cpt_version increases whenever the file format in the main
176 * development branch changes, due to an extension of the cptv enum above.
177 * Backward compatibility for reading old run input files is maintained
178 * by checking this version number against that of the file and then using
179 * the correct code path. */
180 static const int cpt_version = cptv_Count - 1;
183 const char* est_names[estNR] = { "FE-lambda",
189 "thermostat-integral",
194 "LD-rng-unsupported",
195 "LD-rng-i-unsupported",
208 "MC-rng-unsupported",
209 "MC-rng-i-unsupported",
210 "barostat-integral" };
227 static const char* eeks_names[eeksNR] = { "Ekin_n", "Ekinh", "dEkindlambda",
228 "mv_cos", "Ekinf", "Ekinh_old",
229 "EkinScaleF_NHC", "EkinScaleH_NHC", "Vscale_NHC",
241 eenhENERGY_NSTEPS_SIM,
242 eenhENERGY_DELTA_H_NN,
243 eenhENERGY_DELTA_H_LIST,
244 eenhENERGY_DELTA_H_STARTTIME,
245 eenhENERGY_DELTA_H_STARTLAMBDA,
251 epullhPULL_NUMCOORDINATES,
252 epullhPULL_NUMGROUPS,
253 epullhPULL_NUMVALUESINXSUM,
254 epullhPULL_NUMVALUESINFSUM,
260 epullcoordh_VALUE_REF_SUM,
261 epullcoordh_VALUE_SUM,
262 epullcoordh_DR01_SUM,
263 epullcoordh_DR23_SUM,
264 epullcoordh_DR45_SUM,
265 epullcoordh_FSCAL_SUM,
266 epullcoordh_DYNAX_SUM,
276 static const char* eenh_names[eenhNR] = { "energy_n",
285 "energy_delta_h_list",
286 "energy_delta_h_start_time",
287 "energy_delta_h_start_lambda" };
289 static const char* ePullhNames[epullhNR] = { "pullhistory_numcoordinates",
290 "pullhistory_numgroups",
291 "pullhistory_numvaluesinxsum",
292 "pullhistory_numvaluesinfsum" };
294 /* free energy history variables -- need to be preserved over checkpoint */
313 /* free energy history variable names */
314 static const char* edfh_names[edfhNR] = { "bEquilibrated",
316 "Wang-Landau Histogram",
324 "accumulated_plus_2",
325 "accumulated_minus_2",
329 /* AWH biasing history variables */
333 eawhhEQUILIBRATEHISTOGRAM,
337 eawhhUMBRELLAGRIDPOINT,
339 eawhhLOGSCALEDSAMPLEWEIGHT,
341 eawhhFORCECORRELATIONGRID,
345 static const char* eawhh_names[eawhhNR] = { "awh_in_initial", "awh_equilibrateHistogram",
346 "awh_histsize", "awh_npoints",
347 "awh_coordpoint", "awh_umbrellaGridpoint",
348 "awh_updatelist", "awh_logScaledSampleWeight",
349 "awh_numupdates", "awh_forceCorrelationGrid" };
357 static const char* epull_prev_step_com_names[epullsNR] = { "Pull groups prev step COM" };
360 //! Higher level vector element type, only used for formatting checkpoint dumps
361 enum class CptElementType
363 integer, //!< integer
364 real, //!< float or double, not linked to precision of type real
365 real3, //!< float[3] or double[3], not linked to precision of type real
366 matrix3x3 //!< float[3][3] or double[3][3], not linked to precision of type real
369 //! \brief Parts of the checkpoint state, only used for reporting
372 microState, //!< The microstate of the simulated system
373 kineticEnergy, //!< Kinetic energy, needed for T/P-coupling state
374 energyHistory, //!< Energy observable statistics
375 freeEnergyHistory, //!< Free-energy state and observable statistics
376 accWeightHistogram, //!< Accelerated weight histogram method state
377 pullState, //!< COM of previous step.
378 pullHistory //!< Pull history statistics (sums since last written output)
381 //! \brief Return the name of a checkpoint entry based on part and part entry
382 static const char* entryName(StatePart part, int ecpt)
386 case StatePart::microState: return est_names[ecpt];
387 case StatePart::kineticEnergy: return eeks_names[ecpt];
388 case StatePart::energyHistory: return eenh_names[ecpt];
389 case StatePart::freeEnergyHistory: return edfh_names[ecpt];
390 case StatePart::accWeightHistogram: return eawhh_names[ecpt];
391 case StatePart::pullState: return epull_prev_step_com_names[ecpt];
392 case StatePart::pullHistory: return ePullhNames[ecpt];
398 static void cp_warning(FILE* fp)
400 fprintf(fp, "\nWARNING: Checkpoint file is corrupted or truncated\n\n");
403 [[noreturn]] static void cp_error()
405 gmx_fatal(FARGS, "Checkpoint file corrupted/truncated, or maybe you are out of disk space?");
408 static void do_cpt_string_err(XDR* xd, const char* desc, gmx::ArrayRef<char> s, FILE* list)
410 char* data = s.data();
411 if (xdr_string(xd, &data, s.size()) == 0)
417 fprintf(list, "%s = %s\n", desc, data);
421 static int do_cpt_int(XDR* xd, const char* desc, int* i, FILE* list)
423 if (xdr_int(xd, i) == 0)
429 fprintf(list, "%s = %d\n", desc, *i);
434 static int do_cpt_u_chars(XDR* xd, const char* desc, int n, unsigned char* i, FILE* list)
438 fprintf(list, "%s = ", desc);
441 for (int j = 0; j < n && res; j++)
443 res &= xdr_u_char(xd, &i[j]);
446 fprintf(list, "%02x", i[j]);
461 static void do_cpt_int_err(XDR* xd, const char* desc, int* i, FILE* list)
463 if (do_cpt_int(xd, desc, i, list) < 0)
469 static void do_cpt_bool_err(XDR* xd, const char* desc, bool* b, FILE* list)
471 int i = static_cast<int>(*b);
473 if (do_cpt_int(xd, desc, &i, list) < 0)
481 static void do_cpt_step_err(XDR* xd, const char* desc, int64_t* i, FILE* list)
483 char buf[STEPSTRSIZE];
485 if (xdr_int64(xd, i) == 0)
491 fprintf(list, "%s = %s\n", desc, gmx_step_str(*i, buf));
495 static void do_cpt_double_err(XDR* xd, const char* desc, double* f, FILE* list)
497 if (xdr_double(xd, f) == 0)
503 fprintf(list, "%s = %f\n", desc, *f);
507 static void do_cpt_real_err(XDR* xd, real* f)
510 bool_t res = xdr_double(xd, f);
512 bool_t res = xdr_float(xd, f);
520 static void do_cpt_n_rvecs_err(XDR* xd, const char* desc, int n, rvec f[], FILE* list)
522 for (int i = 0; i < n; i++)
524 for (int j = 0; j < DIM; j++)
526 do_cpt_real_err(xd, &f[i][j]);
532 pr_rvecs(list, 0, desc, f, n);
544 static const int value = xdr_datatype_int;
548 struct xdr_type<float>
550 static const int value = xdr_datatype_float;
554 struct xdr_type<double>
556 static const int value = xdr_datatype_double;
559 //! \brief Returns size in byte of an xdr_datatype
560 static inline unsigned int sizeOfXdrType(int xdrType)
564 case xdr_datatype_int: return sizeof(int);
565 case xdr_datatype_float: return sizeof(float);
566 case xdr_datatype_double: return sizeof(double);
567 default: GMX_RELEASE_ASSERT(false, "XDR data type not implemented");
573 //! \brief Returns the XDR process function for i/o of an XDR type
574 static inline xdrproc_t xdrProc(int xdrType)
578 case xdr_datatype_int: return reinterpret_cast<xdrproc_t>(xdr_int);
579 case xdr_datatype_float: return reinterpret_cast<xdrproc_t>(xdr_float);
580 case xdr_datatype_double: return reinterpret_cast<xdrproc_t>(xdr_double);
581 default: GMX_RELEASE_ASSERT(false, "XDR data type not implemented");
587 /*! \brief Lists or only reads an xdr vector from checkpoint file
589 * When list!=NULL reads and lists the \p nf vector elements of type \p xdrType.
590 * The header for the print is set by \p part and \p ecpt.
591 * The formatting of the printing is set by \p cptElementType.
592 * When list==NULL only reads the elements.
594 static bool_t listXdrVector(XDR* xd, StatePart part, int ecpt, int nf, int xdrType, FILE* list, CptElementType cptElementType)
598 const unsigned int elemSize = sizeOfXdrType(xdrType);
599 std::vector<char> data(nf * elemSize);
600 res = xdr_vector(xd, data.data(), nf, elemSize, xdrProc(xdrType));
606 case xdr_datatype_int:
607 pr_ivec(list, 0, entryName(part, ecpt), reinterpret_cast<const int*>(data.data()), nf, TRUE);
609 case xdr_datatype_float:
611 if (cptElementType == CptElementType::real3)
613 pr_rvecs(list, 0, entryName(part, ecpt), reinterpret_cast<const rvec*>(data.data()), nf / 3);
618 /* Note: With double precision code dumping a single precision rvec will produce float iso rvec print, but that's a minor annoyance */
619 pr_fvec(list, 0, entryName(part, ecpt), reinterpret_cast<const float*>(data.data()), nf, TRUE);
622 case xdr_datatype_double:
624 if (cptElementType == CptElementType::real3)
626 pr_rvecs(list, 0, entryName(part, ecpt), reinterpret_cast<const rvec*>(data.data()), nf / 3);
631 /* Note: With single precision code dumping a double precision rvec will produce float iso rvec print, but that's a minor annoyance */
632 pr_dvec(list, 0, entryName(part, ecpt), reinterpret_cast<const double*>(data.data()), nf, TRUE);
635 default: GMX_RELEASE_ASSERT(false, "Data type not implemented for listing");
642 //! \brief Convert a double array, typed char*, to float
643 gmx_unused static void convertArrayRealPrecision(const char* c, float* v, int n)
645 const double* d = reinterpret_cast<const double*>(c);
646 for (int i = 0; i < n; i++)
648 v[i] = static_cast<float>(d[i]);
652 //! \brief Convert a float array, typed char*, to double
653 static void convertArrayRealPrecision(const char* c, double* v, int n)
655 const float* f = reinterpret_cast<const float*>(c);
656 for (int i = 0; i < n; i++)
658 v[i] = static_cast<double>(f[i]);
662 //! \brief Generate an error for trying to convert to integer
663 static void convertArrayRealPrecision(const char gmx_unused* c, int gmx_unused* v, int gmx_unused n)
665 GMX_RELEASE_ASSERT(false,
666 "We only expect type mismatches between float and double, not integer");
669 /*! \brief Low-level routine for reading/writing a vector of reals from/to file.
671 * This is the only routine that does the actually i/o of real vector,
672 * all other routines are intermediate level routines for specific real
673 * data types, calling this routine.
674 * Currently this routine is (too) complex, since it handles both real *
675 * and std::vector<real>. Using real * is deprecated and this routine
676 * will simplify a lot when only std::vector needs to be supported.
678 * The routine is generic to vectors with different allocators,
679 * because as part of reading a checkpoint there are vectors whose
680 * size is not known until reading has progressed far enough, so a
681 * resize method must be called.
683 * When not listing, we use either v or vector, depending on which is !=NULL.
684 * If nval >= 0, nval is used; on read this should match the passed value.
685 * If nval n<0, *nptr (with v) or vector->size() is used. On read using v,
686 * the value is stored in nptr
688 template<typename T, typename AllocatorType>
689 static int doVectorLow(XDR* xd,
696 std::vector<T, AllocatorType>* vector,
698 CptElementType cptElementType)
700 GMX_RELEASE_ASSERT(list != nullptr || (v != nullptr && vector == nullptr)
701 || (v == nullptr && vector != nullptr),
702 "Without list, we should have exactly one of v and vector != NULL");
706 int numElemInTheFile;
711 GMX_RELEASE_ASSERT(nptr == nullptr, "With nval>=0 we should have nptr==NULL");
712 numElemInTheFile = nval;
718 GMX_RELEASE_ASSERT(nptr != nullptr, "With nval<0 we should have nptr!=NULL");
719 numElemInTheFile = *nptr;
723 numElemInTheFile = vector->size();
727 /* Read/write the vector element count */
728 res = xdr_int(xd, &numElemInTheFile);
733 /* Read/write the element data type */
734 constexpr int xdrTypeInTheCode = xdr_type<T>::value;
735 int xdrTypeInTheFile = xdrTypeInTheCode;
736 res = xdr_int(xd, &xdrTypeInTheFile);
742 if (list == nullptr && (sflags & (1 << ecpt)))
746 if (numElemInTheFile != nval)
749 "Count mismatch for state entry %s, code count is %d, file count is %d\n",
750 entryName(part, ecpt),
755 else if (nptr != nullptr)
757 *nptr = numElemInTheFile;
760 bool typesMatch = (xdrTypeInTheFile == xdrTypeInTheCode);
765 "mismatch for state entry %s, code precision is %s, file precision is %s",
766 entryName(part, ecpt),
767 xdr_datatype_names[xdrTypeInTheCode],
768 xdr_datatype_names[xdrTypeInTheFile]);
770 /* Matching int and real should never occur, but check anyhow */
771 if (xdrTypeInTheFile == xdr_datatype_int || xdrTypeInTheCode == xdr_datatype_int)
774 "Type %s: incompatible checkpoint formats or corrupted checkpoint file.",
784 snew(*v, numElemInTheFile);
790 /* This conditional ensures that we don't resize on write.
791 * In particular in the state where this code was written
792 * vector has a size of numElemInThefile and we
793 * don't want to lose that padding here.
795 if (vector->size() < static_cast<unsigned int>(numElemInTheFile))
797 vector->resize(numElemInTheFile);
805 vChar = reinterpret_cast<char*>(vp);
809 snew(vChar, numElemInTheFile * sizeOfXdrType(xdrTypeInTheFile));
812 xd, vChar, numElemInTheFile, sizeOfXdrType(xdrTypeInTheFile), xdrProc(xdrTypeInTheFile));
820 /* In the old code float-double conversion came for free.
821 * In the new code we still support it, mainly because
822 * the tip4p_continue regression test makes use of this.
823 * It's an open question if we do or don't want to allow this.
825 convertArrayRealPrecision(vChar, vp, numElemInTheFile);
831 res = listXdrVector(xd, part, ecpt, numElemInTheFile, xdrTypeInTheFile, list, cptElementType);
837 //! \brief Read/Write a std::vector, on read checks the number of elements matches \p numElements, if specified.
840 doVector(XDR* xd, StatePart part, int ecpt, int sflags, std::vector<T>* vector, FILE* list, int numElements = -1)
842 return doVectorLow<T>(
843 xd, part, ecpt, sflags, numElements, nullptr, nullptr, vector, list, CptElementType::real);
846 //! \brief Read/Write an ArrayRef<real>.
847 static int doRealArrayRef(XDR* xd, StatePart part, int ecpt, int sflags, gmx::ArrayRef<real> vector, FILE* list)
849 real* v_real = vector.data();
850 return doVectorLow<real, std::allocator<real>>(
851 xd, part, ecpt, sflags, vector.size(), nullptr, &v_real, nullptr, list, CptElementType::real);
854 //! Convert from view of RVec to view of real.
855 static gmx::ArrayRef<real> realArrayRefFromRVecArrayRef(gmx::ArrayRef<gmx::RVec> ofRVecs)
857 return gmx::arrayRefFromArray<real>(reinterpret_cast<real*>(ofRVecs.data()), ofRVecs.size() * DIM);
860 //! \brief Read/Write a PaddedVector whose value_type is RVec.
861 template<typename PaddedVectorOfRVecType>
863 doRvecVector(XDR* xd, StatePart part, int ecpt, int sflags, PaddedVectorOfRVecType* v, int numAtoms, FILE* list)
865 const int numReals = numAtoms * DIM;
870 sflags & (1 << ecpt),
871 "When not listing, the flag for the entry should be set when requesting i/o");
872 GMX_RELEASE_ASSERT(v->size() == numAtoms, "v should have sufficient size for numAtoms");
874 return doRealArrayRef(xd, part, ecpt, sflags, realArrayRefFromRVecArrayRef(makeArrayRef(*v)), list);
878 // Use the rebind facility to change the value_type of the
879 // allocator from RVec to real.
880 using realAllocator =
881 typename std::allocator_traits<typename PaddedVectorOfRVecType::allocator_type>::template rebind_alloc<real>;
882 return doVectorLow<real, realAllocator>(
883 xd, part, ecpt, sflags, numReals, nullptr, nullptr, nullptr, list, CptElementType::real);
887 /* This function stores n along with the reals for reading,
888 * but on reading it assumes that n matches the value in the checkpoint file,
889 * a fatal error is generated when this is not the case.
891 static int do_cpte_reals(XDR* xd, StatePart part, int ecpt, int sflags, int n, real** v, FILE* list)
893 return doVectorLow<real, std::allocator<real>>(
894 xd, part, ecpt, sflags, n, nullptr, v, nullptr, list, CptElementType::real);
897 /* This function does the same as do_cpte_reals,
898 * except that on reading it ignores the passed value of *n
899 * and stores the value read from the checkpoint file in *n.
901 static int do_cpte_n_reals(XDR* xd, StatePart part, int ecpt, int sflags, int* n, real** v, FILE* list)
903 return doVectorLow<real, std::allocator<real>>(
904 xd, part, ecpt, sflags, -1, n, v, nullptr, list, CptElementType::real);
907 static int do_cpte_real(XDR* xd, StatePart part, int ecpt, int sflags, real* r, FILE* list)
909 return doVectorLow<real, std::allocator<real>>(
910 xd, part, ecpt, sflags, 1, nullptr, &r, nullptr, list, CptElementType::real);
913 static int do_cpte_ints(XDR* xd, StatePart part, int ecpt, int sflags, int n, int** v, FILE* list)
915 return doVectorLow<int, std::allocator<int>>(
916 xd, part, ecpt, sflags, n, nullptr, v, nullptr, list, CptElementType::integer);
919 static int do_cpte_int(XDR* xd, StatePart part, int ecpt, int sflags, int* i, FILE* list)
921 return do_cpte_ints(xd, part, ecpt, sflags, 1, &i, list);
924 static int do_cpte_bool(XDR* xd, StatePart part, int ecpt, int sflags, bool* b, FILE* list)
926 int i = static_cast<int>(*b);
927 int ret = do_cpte_int(xd, part, ecpt, sflags, &i, list);
932 static int do_cpte_doubles(XDR* xd, StatePart part, int ecpt, int sflags, int n, double** v, FILE* list)
934 return doVectorLow<double, std::allocator<double>>(
935 xd, part, ecpt, sflags, n, nullptr, v, nullptr, list, CptElementType::real);
938 static int do_cpte_double(XDR* xd, StatePart part, int ecpt, int sflags, double* r, FILE* list)
940 return do_cpte_doubles(xd, part, ecpt, sflags, 1, &r, list);
943 static int do_cpte_matrix(XDR* xd, StatePart part, int ecpt, int sflags, matrix v, FILE* list)
949 ret = doVectorLow<real, std::allocator<real>>(
950 xd, part, ecpt, sflags, DIM * DIM, nullptr, &vr, nullptr, nullptr, CptElementType::matrix3x3);
952 if (list && ret == 0)
954 pr_rvecs(list, 0, entryName(part, ecpt), v, DIM);
961 static int do_cpte_nmatrix(XDR* xd, StatePart part, int ecpt, int sflags, int n, real** v, FILE* list)
965 char name[CPTSTRLEN];
972 for (i = 0; i < n; i++)
974 reti = doVectorLow<real, std::allocator<real>>(
975 xd, part, ecpt, sflags, n, nullptr, &(v[i]), nullptr, nullptr, CptElementType::matrix3x3);
976 if (list && reti == 0)
978 sprintf(name, "%s[%d]", entryName(part, ecpt), i);
979 pr_reals(list, 0, name, v[i], n);
989 static int do_cpte_matrices(XDR* xd, StatePart part, int ecpt, int sflags, int n, matrix** v, FILE* list)
992 matrix *vp, *va = nullptr;
998 res = xdr_int(xd, &nf);
1003 if (list == nullptr && nf != n)
1006 "Count mismatch for state entry %s, code count is %d, file count is %d\n",
1007 entryName(part, ecpt),
1011 if (list || !(sflags & (1 << ecpt)))
1024 snew(vr, nf * DIM * DIM);
1025 for (i = 0; i < nf; i++)
1027 for (j = 0; j < DIM; j++)
1029 for (k = 0; k < DIM; k++)
1031 vr[(i * DIM + j) * DIM + k] = vp[i][j][k];
1035 ret = doVectorLow<real, std::allocator<real>>(
1036 xd, part, ecpt, sflags, nf * DIM * DIM, nullptr, &vr, nullptr, nullptr, CptElementType::matrix3x3);
1037 for (i = 0; i < nf; i++)
1039 for (j = 0; j < DIM; j++)
1041 for (k = 0; k < DIM; k++)
1043 vp[i][j][k] = vr[(i * DIM + j) * DIM + k];
1049 if (list && ret == 0)
1051 for (i = 0; i < nf; i++)
1053 pr_rvecs(list, 0, entryName(part, ecpt), vp[i], DIM);
1064 static void do_cpt_header(XDR* xd, gmx_bool bRead, FILE* list, CheckpointHeaderContents* contents)
1077 res = xdr_int(xd, &magic);
1081 "The checkpoint file is empty/corrupted, or maybe you are out of disk space?");
1083 if (magic != CPT_MAGIC1)
1086 "Start of file magic number mismatch, checkpoint file has %d, should be %d\n"
1087 "The checkpoint file is corrupted or not a checkpoint file",
1094 gmx_gethostname(fhost, 255);
1096 do_cpt_string_err(xd, "GROMACS version", contents->version, list);
1097 // The following fields are no longer ever written with meaningful
1098 // content, but because they precede the file version, there is no
1099 // good way for new code to read the old and new formats, nor a
1100 // good way for old code to avoid giving an error while reading a
1101 // new format. So we read and write a field that no longer has a
1103 do_cpt_string_err(xd, "GROMACS build time UNUSED", contents->btime_UNUSED, list);
1104 do_cpt_string_err(xd, "GROMACS build user UNUSED", contents->buser_UNUSED, list);
1105 do_cpt_string_err(xd, "GROMACS build host UNUSED", contents->bhost_UNUSED, list);
1106 do_cpt_string_err(xd, "generating program", contents->fprog, list);
1107 do_cpt_string_err(xd, "generation time", contents->ftime, list);
1108 contents->file_version = cpt_version;
1109 do_cpt_int_err(xd, "checkpoint file version", &contents->file_version, list);
1110 if (contents->file_version > cpt_version)
1113 "Attempting to read a checkpoint file of version %d with code of version %d\n",
1114 contents->file_version,
1117 if (contents->file_version >= 13)
1119 do_cpt_int_err(xd, "GROMACS double precision", &contents->double_prec, list);
1123 contents->double_prec = -1;
1125 if (contents->file_version >= 12)
1127 do_cpt_string_err(xd, "generating host", fhost, list);
1129 do_cpt_int_err(xd, "#atoms", &contents->natoms, list);
1130 do_cpt_int_err(xd, "#T-coupling groups", &contents->ngtc, list);
1131 if (contents->file_version >= 10)
1133 do_cpt_int_err(xd, "#Nose-Hoover T-chains", &contents->nhchainlength, list);
1137 contents->nhchainlength = 1;
1139 if (contents->file_version >= 11)
1141 do_cpt_int_err(xd, "#Nose-Hoover T-chains for barostat ", &contents->nnhpres, list);
1145 contents->nnhpres = 0;
1147 if (contents->file_version >= 14)
1149 do_cpt_int_err(xd, "# of total lambda states ", &contents->nlambda, list);
1153 contents->nlambda = 0;
1155 do_cpt_int_err(xd, "integrator", &contents->eIntegrator, list);
1156 if (contents->file_version >= 3)
1158 do_cpt_int_err(xd, "simulation part #", &contents->simulation_part, list);
1162 contents->simulation_part = 1;
1164 if (contents->file_version >= 5)
1166 do_cpt_step_err(xd, "step", &contents->step, list);
1171 do_cpt_int_err(xd, "step", &idum, list);
1172 contents->step = static_cast<int64_t>(idum);
1174 do_cpt_double_err(xd, "t", &contents->t, list);
1175 do_cpt_int_err(xd, "#PP-ranks", &contents->nnodes, list);
1176 do_cpt_int_err(xd, "dd_nc[x]", &contents->dd_nc[XX], list);
1177 do_cpt_int_err(xd, "dd_nc[y]", &contents->dd_nc[YY], list);
1178 do_cpt_int_err(xd, "dd_nc[z]", &contents->dd_nc[ZZ], list);
1179 do_cpt_int_err(xd, "#PME-only ranks", &contents->npme, list);
1180 do_cpt_int_err(xd, "state flags", &contents->flags_state, list);
1181 if (contents->file_version >= 4)
1183 do_cpt_int_err(xd, "ekin data flags", &contents->flags_eks, list);
1184 do_cpt_int_err(xd, "energy history flags", &contents->flags_enh, list);
1188 contents->flags_eks = 0;
1189 contents->flags_enh = (contents->flags_state >> (estORIRE_DTAV + 1));
1190 contents->flags_state = (contents->flags_state
1191 & ~((1 << (estORIRE_DTAV + 1)) | (1 << (estORIRE_DTAV + 2))
1192 | (1 << (estORIRE_DTAV + 3))));
1194 if (contents->file_version >= 14)
1196 do_cpt_int_err(xd, "df history flags", &contents->flags_dfh, list);
1200 contents->flags_dfh = 0;
1203 if (contents->file_version >= 15)
1205 do_cpt_int_err(xd, "ED data sets", &contents->nED, list);
1212 if (contents->file_version >= 16)
1214 do_cpt_int_err(xd, "swap", &contents->eSwapCoords, list);
1218 contents->eSwapCoords = eswapNO;
1221 if (contents->file_version >= 17)
1223 do_cpt_int_err(xd, "AWH history flags", &contents->flags_awhh, list);
1227 contents->flags_awhh = 0;
1230 if (contents->file_version >= 18)
1232 do_cpt_int_err(xd, "pull history flags", &contents->flagsPullHistory, list);
1236 contents->flagsPullHistory = 0;
1239 if (contents->file_version >= cptv_ModularSimulator)
1242 xd, "Is modular simulator checkpoint", &contents->isModularSimulatorCheckpoint, list);
1246 contents->isModularSimulatorCheckpoint = false;
1250 static int do_cpt_footer(XDR* xd, int file_version)
1255 if (file_version >= 2)
1258 res = xdr_int(xd, &magic);
1263 if (magic != CPT_MAGIC2)
1272 static int do_cpt_state(XDR* xd, int fflags, t_state* state, FILE* list)
1275 const StatePart part = StatePart::microState;
1276 const int sflags = state->flags;
1277 // If reading, state->natoms was probably just read, so
1278 // allocations need to be managed. If writing, this won't change
1279 // anything that matters.
1280 state_change_natoms(state, state->natoms);
1281 for (int i = 0; (i < estNR && ret == 0); i++)
1283 if (fflags & (1 << i))
1288 ret = doRealArrayRef(
1293 gmx::arrayRefFromArray<real>(state->lambda.data(), state->lambda.size()),
1297 ret = do_cpte_int(xd, part, i, sflags, &state->fep_state, list);
1299 case estBOX: ret = do_cpte_matrix(xd, part, i, sflags, state->box, list); break;
1301 ret = do_cpte_matrix(xd, part, i, sflags, state->box_rel, list);
1303 case estBOXV: ret = do_cpte_matrix(xd, part, i, sflags, state->boxv, list); break;
1305 ret = do_cpte_matrix(xd, part, i, sflags, state->pres_prev, list);
1308 ret = do_cpte_matrix(xd, part, i, sflags, state->svir_prev, list);
1311 ret = do_cpte_matrix(xd, part, i, sflags, state->fvir_prev, list);
1314 ret = doVector<double>(xd, part, i, sflags, &state->nosehoover_xi, list);
1317 ret = doVector<double>(xd, part, i, sflags, &state->nosehoover_vxi, list);
1320 ret = doVector<double>(xd, part, i, sflags, &state->nhpres_xi, list);
1323 ret = doVector<double>(xd, part, i, sflags, &state->nhpres_vxi, list);
1326 ret = doVector<double>(xd, part, i, sflags, &state->therm_integral, list);
1329 ret = do_cpte_double(xd, part, i, sflags, &state->baros_integral, list);
1331 case estVETA: ret = do_cpte_real(xd, part, i, sflags, &state->veta, list); break;
1332 case estVOL0: ret = do_cpte_real(xd, part, i, sflags, &state->vol0, list); break;
1334 ret = doRvecVector(xd, part, i, sflags, &state->x, state->natoms, list);
1337 ret = doRvecVector(xd, part, i, sflags, &state->v, state->natoms, list);
1339 /* The RNG entries are no longer written,
1340 * the next 4 lines are only for reading old files.
1341 * It's OK that three case statements fall through.
1343 case estLD_RNG_NOTSUPPORTED:
1344 case estLD_RNGI_NOTSUPPORTED:
1345 case estMC_RNG_NOTSUPPORTED:
1346 case estMC_RNGI_NOTSUPPORTED:
1347 ret = do_cpte_ints(xd, part, i, sflags, 0, nullptr, list);
1349 case estDISRE_INITF:
1350 ret = do_cpte_real(xd, part, i, sflags, &state->hist.disre_initf, list);
1352 case estDISRE_RM3TAV:
1353 ret = do_cpte_n_reals(
1354 xd, part, i, sflags, &state->hist.ndisrepairs, &state->hist.disre_rm3tav, list);
1356 case estORIRE_INITF:
1357 ret = do_cpte_real(xd, part, i, sflags, &state->hist.orire_initf, list);
1360 ret = do_cpte_n_reals(
1361 xd, part, i, sflags, &state->hist.norire_Dtav, &state->hist.orire_Dtav, list);
1363 case estPULLCOMPREVSTEP:
1364 ret = doVector<double>(xd, part, i, sflags, &state->pull_com_prev_step, list);
1368 "Unknown state entry %d\n"
1369 "You are reading a checkpoint file written by different code, which "
1378 static int do_cpt_ekinstate(XDR* xd, int fflags, ekinstate_t* ekins, FILE* list)
1382 const StatePart part = StatePart::kineticEnergy;
1383 for (int i = 0; (i < eeksNR && ret == 0); i++)
1385 if (fflags & (1 << i))
1391 ret = do_cpte_int(xd, part, i, fflags, &ekins->ekin_n, list);
1394 ret = do_cpte_matrices(xd, part, i, fflags, ekins->ekin_n, &ekins->ekinh, list);
1397 ret = do_cpte_matrices(xd, part, i, fflags, ekins->ekin_n, &ekins->ekinf, list);
1400 ret = do_cpte_matrices(xd, part, i, fflags, ekins->ekin_n, &ekins->ekinh_old, list);
1403 ret = do_cpte_matrix(xd, part, i, fflags, ekins->ekin_total, list);
1405 case eeksEKINSCALEF:
1406 ret = doVector<double>(xd, part, i, fflags, &ekins->ekinscalef_nhc, list);
1409 ret = doVector<double>(xd, part, i, fflags, &ekins->vscale_nhc, list);
1411 case eeksEKINSCALEH:
1412 ret = doVector<double>(xd, part, i, fflags, &ekins->ekinscaleh_nhc, list);
1415 ret = do_cpte_real(xd, part, i, fflags, &ekins->dekindl, list);
1417 case eeksMVCOS: ret = do_cpte_real(xd, part, i, fflags, &ekins->mvcos, list); break;
1420 "Unknown ekin data state entry %d\n"
1421 "You are probably reading a new checkpoint file with old code",
1431 static int do_cpt_swapstate(XDR* xd, gmx_bool bRead, int eSwapCoords, swaphistory_t* swapstate, FILE* list)
1433 int swap_cpt_version = 2;
1435 if (eSwapCoords == eswapNO)
1440 swapstate->bFromCpt = bRead;
1441 swapstate->eSwapCoords = eSwapCoords;
1443 do_cpt_int_err(xd, "swap checkpoint version", &swap_cpt_version, list);
1444 if (bRead && swap_cpt_version < 2)
1447 "Cannot read checkpoint files that were written with old versions"
1448 "of the ion/water position swapping protocol.\n");
1451 do_cpt_int_err(xd, "swap coupling steps", &swapstate->nAverage, list);
1453 /* When reading, init_swapcoords has not been called yet,
1454 * so we have to allocate memory first. */
1455 do_cpt_int_err(xd, "number of ion types", &swapstate->nIonTypes, list);
1458 snew(swapstate->ionType, swapstate->nIonTypes);
1461 for (int ic = 0; ic < eCompNR; ic++)
1463 for (int ii = 0; ii < swapstate->nIonTypes; ii++)
1465 swapstateIons_t* gs = &swapstate->ionType[ii];
1469 do_cpt_int_err(xd, "swap requested atoms", &gs->nMolReq[ic], list);
1473 do_cpt_int_err(xd, "swap requested atoms p", gs->nMolReq_p[ic], list);
1478 do_cpt_int_err(xd, "swap influx net", &gs->inflow_net[ic], list);
1482 do_cpt_int_err(xd, "swap influx net p", gs->inflow_net_p[ic], list);
1485 if (bRead && (nullptr == gs->nMolPast[ic]))
1487 snew(gs->nMolPast[ic], swapstate->nAverage);
1490 for (int j = 0; j < swapstate->nAverage; j++)
1494 do_cpt_int_err(xd, "swap past atom counts", &gs->nMolPast[ic][j], list);
1498 do_cpt_int_err(xd, "swap past atom counts p", &gs->nMolPast_p[ic][j], list);
1504 /* Ion flux per channel */
1505 for (int ic = 0; ic < eChanNR; ic++)
1507 for (int ii = 0; ii < swapstate->nIonTypes; ii++)
1509 swapstateIons_t* gs = &swapstate->ionType[ii];
1513 do_cpt_int_err(xd, "channel flux A->B", &gs->fluxfromAtoB[ic], list);
1517 do_cpt_int_err(xd, "channel flux A->B p", gs->fluxfromAtoB_p[ic], list);
1522 /* Ion flux leakage */
1525 do_cpt_int_err(xd, "flux leakage", &swapstate->fluxleak, list);
1529 do_cpt_int_err(xd, "flux leakage", swapstate->fluxleak_p, list);
1533 for (int ii = 0; ii < swapstate->nIonTypes; ii++)
1535 swapstateIons_t* gs = &swapstate->ionType[ii];
1537 do_cpt_int_err(xd, "number of ions", &gs->nMol, list);
1541 snew(gs->channel_label, gs->nMol);
1542 snew(gs->comp_from, gs->nMol);
1545 do_cpt_u_chars(xd, "channel history", gs->nMol, gs->channel_label, list);
1546 do_cpt_u_chars(xd, "domain history", gs->nMol, gs->comp_from, list);
1549 /* Save the last known whole positions to checkpoint
1550 * file to be able to also make multimeric channels whole in PBC */
1551 do_cpt_int_err(xd, "Ch0 atoms", &swapstate->nat[eChan0], list);
1552 do_cpt_int_err(xd, "Ch1 atoms", &swapstate->nat[eChan1], list);
1555 snew(swapstate->xc_old_whole[eChan0], swapstate->nat[eChan0]);
1556 snew(swapstate->xc_old_whole[eChan1], swapstate->nat[eChan1]);
1557 do_cpt_n_rvecs_err(xd, "Ch0 whole x", swapstate->nat[eChan0], swapstate->xc_old_whole[eChan0], list);
1558 do_cpt_n_rvecs_err(xd, "Ch1 whole x", swapstate->nat[eChan1], swapstate->xc_old_whole[eChan1], list);
1563 xd, "Ch0 whole x", swapstate->nat[eChan0], *swapstate->xc_old_whole_p[eChan0], list);
1565 xd, "Ch1 whole x", swapstate->nat[eChan1], *swapstate->xc_old_whole_p[eChan1], list);
1572 static int do_cpt_enerhist(XDR* xd, gmx_bool bRead, int fflags, energyhistory_t* enerhist, FILE* list)
1581 GMX_RELEASE_ASSERT(enerhist != nullptr, "With energy history, we need a valid enerhist pointer");
1583 /* This is stored/read for backward compatibility */
1584 int energyHistoryNumEnergies = 0;
1587 enerhist->nsteps = 0;
1589 enerhist->nsteps_sim = 0;
1590 enerhist->nsum_sim = 0;
1592 else if (enerhist != nullptr)
1594 energyHistoryNumEnergies = enerhist->ener_sum_sim.size();
1597 delta_h_history_t* deltaH = enerhist->deltaHForeignLambdas.get();
1598 const StatePart part = StatePart::energyHistory;
1599 for (int i = 0; (i < eenhNR && ret == 0); i++)
1601 if (fflags & (1 << i))
1606 ret = do_cpte_int(xd, part, i, fflags, &energyHistoryNumEnergies, list);
1608 case eenhENERGY_AVER:
1609 ret = doVector<double>(xd, part, i, fflags, &enerhist->ener_ave, list);
1611 case eenhENERGY_SUM:
1612 ret = doVector<double>(xd, part, i, fflags, &enerhist->ener_sum, list);
1614 case eenhENERGY_NSUM:
1615 do_cpt_step_err(xd, eenh_names[i], &enerhist->nsum, list);
1617 case eenhENERGY_SUM_SIM:
1618 ret = doVector<double>(xd, part, i, fflags, &enerhist->ener_sum_sim, list);
1620 case eenhENERGY_NSUM_SIM:
1621 do_cpt_step_err(xd, eenh_names[i], &enerhist->nsum_sim, list);
1623 case eenhENERGY_NSTEPS:
1624 do_cpt_step_err(xd, eenh_names[i], &enerhist->nsteps, list);
1626 case eenhENERGY_NSTEPS_SIM:
1627 do_cpt_step_err(xd, eenh_names[i], &enerhist->nsteps_sim, list);
1629 case eenhENERGY_DELTA_H_NN:
1632 if (!bRead && deltaH != nullptr)
1634 numDeltaH = deltaH->dh.size();
1636 do_cpt_int_err(xd, eenh_names[i], &numDeltaH, list);
1639 if (deltaH == nullptr)
1641 enerhist->deltaHForeignLambdas = std::make_unique<delta_h_history_t>();
1642 deltaH = enerhist->deltaHForeignLambdas.get();
1644 deltaH->dh.resize(numDeltaH);
1645 deltaH->start_lambda_set = FALSE;
1649 case eenhENERGY_DELTA_H_LIST:
1650 for (auto dh : deltaH->dh)
1652 ret = doVector<real>(xd, part, i, fflags, &dh, list);
1655 case eenhENERGY_DELTA_H_STARTTIME:
1656 ret = do_cpte_double(xd, part, i, fflags, &(deltaH->start_time), list);
1658 case eenhENERGY_DELTA_H_STARTLAMBDA:
1659 ret = do_cpte_double(xd, part, i, fflags, &(deltaH->start_lambda), list);
1663 "Unknown energy history entry %d\n"
1664 "You are probably reading a new checkpoint file with old code",
1670 if ((fflags & (1 << eenhENERGY_SUM)) && !(fflags & (1 << eenhENERGY_SUM_SIM)))
1672 /* Assume we have an old file format and copy sum to sum_sim */
1673 enerhist->ener_sum_sim = enerhist->ener_sum;
1676 if ((fflags & (1 << eenhENERGY_NSUM)) && !(fflags & (1 << eenhENERGY_NSTEPS)))
1678 /* Assume we have an old file format and copy nsum to nsteps */
1679 enerhist->nsteps = enerhist->nsum;
1681 if ((fflags & (1 << eenhENERGY_NSUM_SIM)) && !(fflags & (1 << eenhENERGY_NSTEPS_SIM)))
1683 /* Assume we have an old file format and copy nsum to nsteps */
1684 enerhist->nsteps_sim = enerhist->nsum_sim;
1690 static int doCptPullCoordHist(XDR* xd, PullCoordinateHistory* pullCoordHist, const StatePart part, FILE* list)
1695 flags |= ((1 << epullcoordh_VALUE_REF_SUM) | (1 << epullcoordh_VALUE_SUM)
1696 | (1 << epullcoordh_DR01_SUM) | (1 << epullcoordh_DR23_SUM)
1697 | (1 << epullcoordh_DR45_SUM) | (1 << epullcoordh_FSCAL_SUM));
1699 for (int i = 0; i < epullcoordh_NR && ret == 0; i++)
1703 case epullcoordh_VALUE_REF_SUM:
1704 ret = do_cpte_double(xd, part, i, flags, &(pullCoordHist->valueRef), list);
1706 case epullcoordh_VALUE_SUM:
1707 ret = do_cpte_double(xd, part, i, flags, &(pullCoordHist->value), list);
1709 case epullcoordh_DR01_SUM:
1710 for (int j = 0; j < DIM && ret == 0; j++)
1712 ret = do_cpte_double(xd, part, i, flags, &(pullCoordHist->dr01[j]), list);
1715 case epullcoordh_DR23_SUM:
1716 for (int j = 0; j < DIM && ret == 0; j++)
1718 ret = do_cpte_double(xd, part, i, flags, &(pullCoordHist->dr23[j]), list);
1721 case epullcoordh_DR45_SUM:
1722 for (int j = 0; j < DIM && ret == 0; j++)
1724 ret = do_cpte_double(xd, part, i, flags, &(pullCoordHist->dr45[j]), list);
1727 case epullcoordh_FSCAL_SUM:
1728 ret = do_cpte_double(xd, part, i, flags, &(pullCoordHist->scalarForce), list);
1730 case epullcoordh_DYNAX_SUM:
1731 for (int j = 0; j < DIM && ret == 0; j++)
1733 ret = do_cpte_double(xd, part, i, flags, &(pullCoordHist->dynaX[j]), list);
1742 static int doCptPullGroupHist(XDR* xd, PullGroupHistory* pullGroupHist, const StatePart part, FILE* list)
1747 flags |= ((1 << epullgrouph_X_SUM));
1749 for (int i = 0; i < epullgrouph_NR; i++)
1753 case epullgrouph_X_SUM:
1754 for (int j = 0; j < DIM && ret == 0; j++)
1756 ret = do_cpte_double(xd, part, i, flags, &(pullGroupHist->x[j]), list);
1766 static int doCptPullHist(XDR* xd, gmx_bool bRead, int fflags, PullHistory* pullHist, const StatePart part, FILE* list)
1769 int pullHistoryNumCoordinates = 0;
1770 int pullHistoryNumGroups = 0;
1772 /* Retain the number of terms in the sum and the number of coordinates (used for writing
1773 * average pull forces and coordinates) in the pull history, in temporary variables,
1774 * in case they cannot be read from the checkpoint, in order to have backward compatibility */
1777 pullHist->numValuesInXSum = 0;
1778 pullHist->numValuesInFSum = 0;
1780 else if (pullHist != nullptr)
1782 pullHistoryNumCoordinates = pullHist->pullCoordinateSums.size();
1783 pullHistoryNumGroups = pullHist->pullGroupSums.size();
1787 GMX_RELEASE_ASSERT(fflags == 0, "Without pull history, all flags should be off");
1790 for (int i = 0; (i < epullhNR && ret == 0); i++)
1792 if (fflags & (1 << i))
1796 case epullhPULL_NUMCOORDINATES:
1797 ret = do_cpte_int(xd, part, i, fflags, &pullHistoryNumCoordinates, list);
1799 case epullhPULL_NUMGROUPS:
1800 do_cpt_int_err(xd, eenh_names[i], &pullHistoryNumGroups, list);
1802 case epullhPULL_NUMVALUESINXSUM:
1803 do_cpt_int_err(xd, eenh_names[i], &pullHist->numValuesInXSum, list);
1805 case epullhPULL_NUMVALUESINFSUM:
1806 do_cpt_int_err(xd, eenh_names[i], &pullHist->numValuesInFSum, list);
1810 "Unknown pull history entry %d\n"
1811 "You are probably reading a new checkpoint file with old code",
1818 pullHist->pullCoordinateSums.resize(pullHistoryNumCoordinates);
1819 pullHist->pullGroupSums.resize(pullHistoryNumGroups);
1821 if (pullHist->numValuesInXSum > 0 || pullHist->numValuesInFSum > 0)
1823 for (size_t i = 0; i < pullHist->pullCoordinateSums.size() && ret == 0; i++)
1825 ret = doCptPullCoordHist(xd, &(pullHist->pullCoordinateSums[i]), part, list);
1827 for (size_t i = 0; i < pullHist->pullGroupSums.size() && ret == 0; i++)
1829 ret = doCptPullGroupHist(xd, &(pullHist->pullGroupSums[i]), part, list);
1836 static int do_cpt_df_hist(XDR* xd, int fflags, int nlambda, df_history_t** dfhistPtr, FILE* list)
1845 if (*dfhistPtr == nullptr)
1847 snew(*dfhistPtr, 1);
1848 (*dfhistPtr)->nlambda = nlambda;
1849 init_df_history(*dfhistPtr, nlambda);
1851 df_history_t* dfhist = *dfhistPtr;
1853 const StatePart part = StatePart::freeEnergyHistory;
1854 for (int i = 0; (i < edfhNR && ret == 0); i++)
1856 if (fflags & (1 << i))
1861 ret = do_cpte_bool(xd, part, i, fflags, &dfhist->bEquil, list);
1864 ret = do_cpte_ints(xd, part, i, fflags, nlambda, &dfhist->n_at_lam, list);
1867 ret = do_cpte_reals(xd, part, i, fflags, nlambda, &dfhist->wl_histo, list);
1870 ret = do_cpte_real(xd, part, i, fflags, &dfhist->wl_delta, list);
1872 case edfhSUMWEIGHTS:
1873 ret = do_cpte_reals(xd, part, i, fflags, nlambda, &dfhist->sum_weights, list);
1876 ret = do_cpte_reals(xd, part, i, fflags, nlambda, &dfhist->sum_dg, list);
1879 ret = do_cpte_reals(xd, part, i, fflags, nlambda, &dfhist->sum_minvar, list);
1882 ret = do_cpte_reals(xd, part, i, fflags, nlambda, &dfhist->sum_variance, list);
1885 ret = do_cpte_nmatrix(xd, part, i, fflags, nlambda, dfhist->accum_p, list);
1888 ret = do_cpte_nmatrix(xd, part, i, fflags, nlambda, dfhist->accum_m, list);
1891 ret = do_cpte_nmatrix(xd, part, i, fflags, nlambda, dfhist->accum_p2, list);
1894 ret = do_cpte_nmatrix(xd, part, i, fflags, nlambda, dfhist->accum_m2, list);
1897 ret = do_cpte_nmatrix(xd, part, i, fflags, nlambda, dfhist->Tij, list);
1900 ret = do_cpte_nmatrix(xd, part, i, fflags, nlambda, dfhist->Tij_empirical, list);
1905 "Unknown df history entry %d\n"
1906 "You are probably reading a new checkpoint file with old code",
1916 /* This function stores the last whole configuration of the reference and
1917 * average structure in the .cpt file
1919 static int do_cpt_EDstate(XDR* xd, gmx_bool bRead, int nED, edsamhistory_t* EDstate, FILE* list)
1926 EDstate->bFromCpt = bRead;
1929 /* When reading, init_edsam has not been called yet,
1930 * so we have to allocate memory first. */
1933 snew(EDstate->nref, EDstate->nED);
1934 snew(EDstate->old_sref, EDstate->nED);
1935 snew(EDstate->nav, EDstate->nED);
1936 snew(EDstate->old_sav, EDstate->nED);
1939 /* Read/write the last whole conformation of SREF and SAV for each ED dataset (usually only one) */
1940 for (int i = 0; i < EDstate->nED; i++)
1944 /* Reference structure SREF */
1945 sprintf(buf, "ED%d # of atoms in reference structure", i + 1);
1946 do_cpt_int_err(xd, buf, &EDstate->nref[i], list);
1947 sprintf(buf, "ED%d x_ref", i + 1);
1950 snew(EDstate->old_sref[i], EDstate->nref[i]);
1951 do_cpt_n_rvecs_err(xd, buf, EDstate->nref[i], EDstate->old_sref[i], list);
1955 do_cpt_n_rvecs_err(xd, buf, EDstate->nref[i], EDstate->old_sref_p[i], list);
1958 /* Average structure SAV */
1959 sprintf(buf, "ED%d # of atoms in average structure", i + 1);
1960 do_cpt_int_err(xd, buf, &EDstate->nav[i], list);
1961 sprintf(buf, "ED%d x_av", i + 1);
1964 snew(EDstate->old_sav[i], EDstate->nav[i]);
1965 do_cpt_n_rvecs_err(xd, buf, EDstate->nav[i], EDstate->old_sav[i], list);
1969 do_cpt_n_rvecs_err(xd, buf, EDstate->nav[i], EDstate->old_sav_p[i], list);
1976 static int do_cpt_correlation_grid(XDR* xd,
1978 gmx_unused int fflags,
1979 gmx::CorrelationGridHistory* corrGrid,
1985 do_cpt_int_err(xd, eawhh_names[eawhh], &(corrGrid->numCorrelationTensors), list);
1986 do_cpt_int_err(xd, eawhh_names[eawhh], &(corrGrid->tensorSize), list);
1987 do_cpt_int_err(xd, eawhh_names[eawhh], &(corrGrid->blockDataListSize), list);
1991 initCorrelationGridHistory(
1992 corrGrid, corrGrid->numCorrelationTensors, corrGrid->tensorSize, corrGrid->blockDataListSize);
1995 for (gmx::CorrelationBlockDataHistory& blockData : corrGrid->blockDataBuffer)
1997 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.blockSumWeight), list);
1998 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.blockSumSquareWeight), list);
1999 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.blockSumWeightX), list);
2000 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.blockSumWeightY), list);
2001 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.sumOverBlocksSquareBlockWeight), list);
2002 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.sumOverBlocksBlockSquareWeight), list);
2003 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.sumOverBlocksBlockWeightBlockWeightX), list);
2004 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.sumOverBlocksBlockWeightBlockWeightY), list);
2005 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.blockLength), list);
2006 do_cpt_int_err(xd, eawhh_names[eawhh], &(blockData.previousBlockIndex), list);
2007 do_cpt_double_err(xd, eawhh_names[eawhh], &(blockData.correlationIntegral), list);
2013 static int do_cpt_awh_bias(XDR* xd, gmx_bool bRead, int fflags, gmx::AwhBiasHistory* biasHistory, FILE* list)
2017 gmx::AwhBiasStateHistory* state = &biasHistory->state;
2018 for (int i = 0; (i < eawhhNR && ret == 0); i++)
2020 if (fflags & (1 << i))
2024 case eawhhIN_INITIAL:
2025 do_cpt_bool_err(xd, eawhh_names[i], &state->in_initial, list);
2027 case eawhhEQUILIBRATEHISTOGRAM:
2028 do_cpt_bool_err(xd, eawhh_names[i], &state->equilibrateHistogram, list);
2031 do_cpt_double_err(xd, eawhh_names[i], &state->histSize, list);
2038 numPoints = biasHistory->pointState.size();
2040 do_cpt_int_err(xd, eawhh_names[i], &numPoints, list);
2043 biasHistory->pointState.resize(numPoints);
2047 case eawhhCOORDPOINT:
2048 for (auto& psh : biasHistory->pointState)
2050 do_cpt_double_err(xd, eawhh_names[i], &psh.target, list);
2051 do_cpt_double_err(xd, eawhh_names[i], &psh.free_energy, list);
2052 do_cpt_double_err(xd, eawhh_names[i], &psh.bias, list);
2053 do_cpt_double_err(xd, eawhh_names[i], &psh.weightsum_iteration, list);
2054 do_cpt_double_err(xd, eawhh_names[i], &psh.weightsum_covering, list);
2055 do_cpt_double_err(xd, eawhh_names[i], &psh.weightsum_tot, list);
2056 do_cpt_double_err(xd, eawhh_names[i], &psh.weightsum_ref, list);
2057 do_cpt_step_err(xd, eawhh_names[i], &psh.last_update_index, list);
2058 do_cpt_double_err(xd, eawhh_names[i], &psh.log_pmfsum, list);
2059 do_cpt_double_err(xd, eawhh_names[i], &psh.visits_iteration, list);
2060 do_cpt_double_err(xd, eawhh_names[i], &psh.visits_tot, list);
2063 case eawhhUMBRELLAGRIDPOINT:
2064 do_cpt_int_err(xd, eawhh_names[i], &(state->umbrellaGridpoint), list);
2066 case eawhhUPDATELIST:
2067 do_cpt_int_err(xd, eawhh_names[i], &(state->origin_index_updatelist), list);
2068 do_cpt_int_err(xd, eawhh_names[i], &(state->end_index_updatelist), list);
2070 case eawhhLOGSCALEDSAMPLEWEIGHT:
2071 do_cpt_double_err(xd, eawhh_names[i], &(state->logScaledSampleWeight), list);
2072 do_cpt_double_err(xd, eawhh_names[i], &(state->maxLogScaledSampleWeight), list);
2074 case eawhhNUMUPDATES:
2075 do_cpt_step_err(xd, eawhh_names[i], &(state->numUpdates), list);
2077 case eawhhFORCECORRELATIONGRID:
2078 ret = do_cpt_correlation_grid(
2079 xd, bRead, fflags, &biasHistory->forceCorrelationGrid, list, i);
2081 default: gmx_fatal(FARGS, "Unknown awh history entry %d\n", i);
2089 static int do_cpt_awh(XDR* xd, gmx_bool bRead, int fflags, gmx::AwhHistory* awhHistory, FILE* list)
2095 std::shared_ptr<gmx::AwhHistory> awhHistoryLocal;
2097 if (awhHistory == nullptr)
2099 GMX_RELEASE_ASSERT(bRead,
2100 "do_cpt_awh should not be called for writing without an AwhHistory");
2102 awhHistoryLocal = std::make_shared<gmx::AwhHistory>();
2103 awhHistory = awhHistoryLocal.get();
2106 /* To be able to read and write the AWH data several parameters determining the layout of the AWH structs need to be known
2107 (nbias, npoints, etc.). The best thing (?) would be to have these passed to this function. When writing to a checkpoint
2108 these parameters are available in awh_history (after calling init_awh_history). When reading from a checkpoint though, there
2109 is no initialized awh_history (it is initialized and set in this function). The AWH parameters have not always been read
2110 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
2111 when writing a checkpoint, also storing parameters needed for future reading of the checkpoint.
2113 Another issue is that some variables that AWH checkpoints don't have a registered enum and string (e.g. nbias below).
2114 One difficulty is the multilevel structure of the data which would need to be represented somehow. */
2119 numBias = awhHistory->bias.size();
2121 do_cpt_int_err(xd, "awh_nbias", &numBias, list);
2125 awhHistory->bias.resize(numBias);
2127 for (auto& bias : awhHistory->bias)
2129 ret = do_cpt_awh_bias(xd, bRead, fflags, &bias, list);
2135 do_cpt_double_err(xd, "awh_potential_offset", &awhHistory->potentialOffset, list);
2140 static void do_cpt_mdmodules(int fileVersion,
2141 t_fileio* checkpointFileHandle,
2142 const gmx::MdModulesNotifier& mdModulesNotifier,
2145 if (fileVersion >= cptv_MdModules)
2147 gmx::FileIOXdrSerializer serializer(checkpointFileHandle);
2148 gmx::KeyValueTreeObject mdModuleCheckpointParameterTree =
2149 gmx::deserializeKeyValueTree(&serializer);
2152 gmx::TextWriter textWriter(outputFile);
2153 gmx::dumpKeyValueTree(&textWriter, mdModuleCheckpointParameterTree);
2155 gmx::MdModulesCheckpointReadingDataOnMaster mdModuleCheckpointReadingDataOnMaster = {
2156 mdModuleCheckpointParameterTree, fileVersion
2158 mdModulesNotifier.checkpointingNotifications_.notify(mdModuleCheckpointReadingDataOnMaster);
2162 static int do_cpt_files(XDR* xd, gmx_bool bRead, std::vector<gmx_file_position_t>* outputfiles, FILE* list, int file_version)
2165 gmx_off_t mask = 0xFFFFFFFFL;
2166 int offset_high, offset_low;
2167 std::array<char, CPTSTRLEN> buf;
2168 GMX_RELEASE_ASSERT(outputfiles, "Must have valid outputfiles");
2170 // Ensure that reading pre-allocates outputfiles, while writing
2171 // writes what is already there.
2172 int nfiles = outputfiles->size();
2173 if (do_cpt_int(xd, "number of output files", &nfiles, list) != 0)
2179 outputfiles->resize(nfiles);
2182 for (auto& outputfile : *outputfiles)
2184 /* 64-bit XDR numbers are not portable, so it is stored as separate high/low fractions */
2187 do_cpt_string_err(xd, "output filename", buf, list);
2188 std::copy(std::begin(buf), std::end(buf), std::begin(outputfile.filename));
2190 if (do_cpt_int(xd, "file_offset_high", &offset_high, list) != 0)
2194 if (do_cpt_int(xd, "file_offset_low", &offset_low, list) != 0)
2198 outputfile.offset = (static_cast<gmx_off_t>(offset_high) << 32)
2199 | (static_cast<gmx_off_t>(offset_low) & mask);
2203 do_cpt_string_err(xd, "output filename", outputfile.filename, list);
2205 offset = outputfile.offset;
2213 offset_low = static_cast<int>(offset & mask);
2214 offset_high = static_cast<int>((offset >> 32) & mask);
2216 if (do_cpt_int(xd, "file_offset_high", &offset_high, list) != 0)
2220 if (do_cpt_int(xd, "file_offset_low", &offset_low, list) != 0)
2225 if (file_version >= 8)
2227 if (do_cpt_int(xd, "file_checksum_size", &outputfile.checksumSize, list) != 0)
2231 if (do_cpt_u_chars(xd, "file_checksum", outputfile.checksum.size(), outputfile.checksum.data(), list)
2239 outputfile.checksumSize = -1;
2245 void write_checkpoint_data(t_fileio* fp,
2246 CheckpointHeaderContents headerContents,
2250 ObservablesHistory* observablesHistory,
2251 const gmx::MdModulesNotifier& mdModulesNotifier,
2252 std::vector<gmx_file_position_t>* outputfiles,
2253 gmx::WriteCheckpointDataHolder* modularSimulatorCheckpointData)
2255 headerContents.flags_eks = 0;
2256 if (state->ekinstate.bUpToDate)
2258 headerContents.flags_eks = ((1 << eeksEKIN_N) | (1 << eeksEKINH) | (1 << eeksEKINF)
2259 | (1 << eeksEKINO) | (1 << eeksEKINSCALEF) | (1 << eeksEKINSCALEH)
2260 | (1 << eeksVSCALE) | (1 << eeksDEKINDL) | (1 << eeksMVCOS));
2262 headerContents.isModularSimulatorCheckpoint = !modularSimulatorCheckpointData->empty();
2264 energyhistory_t* enerhist = observablesHistory->energyHistory.get();
2265 headerContents.flags_enh = 0;
2266 if (enerhist != nullptr && (enerhist->nsum > 0 || enerhist->nsum_sim > 0))
2268 headerContents.flags_enh |=
2269 (1 << eenhENERGY_N) | (1 << eenhENERGY_NSTEPS) | (1 << eenhENERGY_NSTEPS_SIM);
2270 if (enerhist->nsum > 0)
2272 headerContents.flags_enh |=
2273 ((1 << eenhENERGY_AVER) | (1 << eenhENERGY_SUM) | (1 << eenhENERGY_NSUM));
2275 if (enerhist->nsum_sim > 0)
2277 headerContents.flags_enh |= ((1 << eenhENERGY_SUM_SIM) | (1 << eenhENERGY_NSUM_SIM));
2279 if (enerhist->deltaHForeignLambdas != nullptr)
2281 headerContents.flags_enh |=
2282 ((1 << eenhENERGY_DELTA_H_NN) | (1 << eenhENERGY_DELTA_H_LIST)
2283 | (1 << eenhENERGY_DELTA_H_STARTTIME) | (1 << eenhENERGY_DELTA_H_STARTLAMBDA));
2287 PullHistory* pullHist = observablesHistory->pullHistory.get();
2288 headerContents.flagsPullHistory = 0;
2289 if (pullHist != nullptr && (pullHist->numValuesInXSum > 0 || pullHist->numValuesInFSum > 0))
2291 headerContents.flagsPullHistory |= (1 << epullhPULL_NUMCOORDINATES);
2292 headerContents.flagsPullHistory |= ((1 << epullhPULL_NUMGROUPS) | (1 << epullhPULL_NUMVALUESINXSUM)
2293 | (1 << epullhPULL_NUMVALUESINFSUM));
2296 headerContents.flags_dfh = 0;
2299 headerContents.flags_dfh = ((1 << edfhBEQUIL) | (1 << edfhNATLAMBDA) | (1 << edfhSUMWEIGHTS)
2300 | (1 << edfhSUMDG) | (1 << edfhTIJ) | (1 << edfhTIJEMP));
2303 headerContents.flags_dfh |= ((1 << edfhWLDELTA) | (1 << edfhWLHISTO));
2305 if ((elamstats == elamstatsMINVAR) || (elamstats == elamstatsBARKER)
2306 || (elamstats == elamstatsMETROPOLIS))
2308 headerContents.flags_dfh |= ((1 << edfhACCUMP) | (1 << edfhACCUMM) | (1 << edfhACCUMP2)
2309 | (1 << edfhACCUMM2) | (1 << edfhSUMMINVAR) | (1 << edfhSUMVAR));
2313 headerContents.flags_awhh = 0;
2314 if (state->awhHistory != nullptr && !state->awhHistory->bias.empty())
2316 headerContents.flags_awhh |=
2317 ((1 << eawhhIN_INITIAL) | (1 << eawhhEQUILIBRATEHISTOGRAM) | (1 << eawhhHISTSIZE)
2318 | (1 << eawhhNPOINTS) | (1 << eawhhCOORDPOINT) | (1 << eawhhUMBRELLAGRIDPOINT)
2319 | (1 << eawhhUPDATELIST) | (1 << eawhhLOGSCALEDSAMPLEWEIGHT)
2320 | (1 << eawhhNUMUPDATES) | (1 << eawhhFORCECORRELATIONGRID));
2323 do_cpt_header(gmx_fio_getxdr(fp), FALSE, nullptr, &headerContents);
2325 if ((do_cpt_state(gmx_fio_getxdr(fp), state->flags, state, nullptr) < 0)
2326 || (do_cpt_ekinstate(gmx_fio_getxdr(fp), headerContents.flags_eks, &state->ekinstate, nullptr) < 0)
2327 || (do_cpt_enerhist(gmx_fio_getxdr(fp), FALSE, headerContents.flags_enh, enerhist, nullptr) < 0)
2328 || (doCptPullHist(gmx_fio_getxdr(fp), FALSE, headerContents.flagsPullHistory, pullHist, StatePart::pullHistory, nullptr)
2330 || (do_cpt_df_hist(gmx_fio_getxdr(fp), headerContents.flags_dfh, headerContents.nlambda, &state->dfhist, nullptr)
2333 gmx_fio_getxdr(fp), FALSE, headerContents.nED, observablesHistory->edsamHistory.get(), nullptr)
2335 || (do_cpt_awh(gmx_fio_getxdr(fp), FALSE, headerContents.flags_awhh, state->awhHistory.get(), nullptr) < 0)
2336 || (do_cpt_swapstate(gmx_fio_getxdr(fp),
2338 headerContents.eSwapCoords,
2339 observablesHistory->swapHistory.get(),
2342 || (do_cpt_files(gmx_fio_getxdr(fp), FALSE, outputfiles, nullptr, headerContents.file_version) < 0))
2344 gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
2347 // Checkpointing MdModules
2349 gmx::KeyValueTreeBuilder builder;
2350 gmx::MdModulesWriteCheckpointData mdModulesWriteCheckpoint = { builder.rootObject(),
2351 headerContents.file_version };
2352 mdModulesNotifier.checkpointingNotifications_.notify(mdModulesWriteCheckpoint);
2353 auto tree = builder.build();
2354 gmx::FileIOXdrSerializer serializer(fp);
2355 gmx::serializeKeyValueTree(tree, &serializer);
2358 // Checkpointing modular simulator
2360 gmx::FileIOXdrSerializer serializer(fp);
2361 modularSimulatorCheckpointData->serialize(&serializer);
2364 do_cpt_footer(gmx_fio_getxdr(fp), headerContents.file_version);
2366 /* Always FAH checkpoint immediately after a Gromacs checkpoint.
2368 * Note that it is critical that we save a FAH checkpoint directly
2369 * after writing a Gromacs checkpoint. If the program dies, either
2370 * by the machine powering off suddenly or the process being,
2371 * killed, FAH can recover files that have only appended data by
2372 * truncating them to the last recorded length. The Gromacs
2373 * checkpoint does not just append data, it is fully rewritten each
2374 * time so a crash between moving the new Gromacs checkpoint file in
2375 * to place and writing a FAH checkpoint is not recoverable. Thus
2376 * the time between these operations must be kept as short a
2383 static void check_int(FILE* fplog, const char* type, int p, int f, gmx_bool* mm)
2385 bool foundMismatch = (p != f);
2393 fprintf(fplog, " %s mismatch,\n", type);
2394 fprintf(fplog, " current program: %d\n", p);
2395 fprintf(fplog, " checkpoint file: %d\n", f);
2396 fprintf(fplog, "\n");
2400 static void check_string(FILE* fplog, const char* type, const char* p, const char* f, gmx_bool* mm)
2402 bool foundMismatch = (std::strcmp(p, f) != 0);
2410 fprintf(fplog, " %s mismatch,\n", type);
2411 fprintf(fplog, " current program: %s\n", p);
2412 fprintf(fplog, " checkpoint file: %s\n", f);
2413 fprintf(fplog, "\n");
2417 static void check_match(FILE* fplog,
2418 const t_commrec* cr,
2420 const CheckpointHeaderContents& headerContents,
2421 gmx_bool reproducibilityRequested)
2423 /* Note that this check_string on the version will also print a message
2424 * when only the minor version differs. But we only print a warning
2425 * message further down with reproducibilityRequested=TRUE.
2427 gmx_bool versionDiffers = FALSE;
2428 check_string(fplog, "Version", gmx_version(), headerContents.version, &versionDiffers);
2430 gmx_bool precisionDiffers = FALSE;
2431 check_int(fplog, "Double prec.", GMX_DOUBLE, headerContents.double_prec, &precisionDiffers);
2432 if (precisionDiffers)
2434 const char msg_precision_difference[] =
2435 "You are continuing a simulation with a different precision. Not matching\n"
2436 "mixed/double precision will lead to precision or performance loss.\n";
2439 fprintf(fplog, "%s\n", msg_precision_difference);
2443 gmx_bool mm = (versionDiffers || precisionDiffers);
2445 if (reproducibilityRequested)
2448 fplog, "Program name", gmx::getProgramContext().fullBinaryPath(), headerContents.fprog, &mm);
2450 check_int(fplog, "#ranks", cr->nnodes, headerContents.nnodes, &mm);
2453 if (cr->sizeOfDefaultCommunicator > 1 && reproducibilityRequested)
2455 // TODO: These checks are incorrect (see redmine #3309)
2456 check_int(fplog, "#PME-ranks", cr->npmenodes, headerContents.npme, &mm);
2458 int npp = cr->sizeOfDefaultCommunicator;
2459 if (cr->npmenodes >= 0)
2461 npp -= cr->npmenodes;
2463 int npp_f = headerContents.nnodes;
2464 if (headerContents.npme >= 0)
2466 npp_f -= headerContents.npme;
2470 check_int(fplog, "#DD-cells[x]", dd_nc[XX], headerContents.dd_nc[XX], &mm);
2471 check_int(fplog, "#DD-cells[y]", dd_nc[YY], headerContents.dd_nc[YY], &mm);
2472 check_int(fplog, "#DD-cells[z]", dd_nc[ZZ], headerContents.dd_nc[ZZ], &mm);
2478 /* Gromacs should be able to continue from checkpoints between
2479 * different patch level versions, but we do not guarantee
2480 * compatibility between different major/minor versions - check this.
2484 sscanf(gmx_version(), "%5d", &gmx_major);
2485 int ret = sscanf(headerContents.version, "%5d", &cpt_major);
2486 gmx_bool majorVersionDiffers = (ret < 1 || gmx_major != cpt_major);
2488 const char msg_major_version_difference[] =
2489 "The current GROMACS major version is not identical to the one that\n"
2490 "generated the checkpoint file. In principle GROMACS does not support\n"
2491 "continuation from checkpoints between different versions, so we advise\n"
2492 "against this. If you still want to try your luck we recommend that you use\n"
2493 "the -noappend flag to keep your output files from the two versions separate.\n"
2494 "This might also work around errors where the output fields in the energy\n"
2495 "file have changed between the different versions.\n";
2497 const char msg_mismatch_notice[] =
2498 "GROMACS patchlevel, binary or parallel settings differ from previous run.\n"
2499 "Continuation is exact, but not guaranteed to be binary identical.\n";
2501 if (majorVersionDiffers)
2505 fprintf(fplog, "%s\n", msg_major_version_difference);
2508 else if (reproducibilityRequested)
2510 /* Major & minor versions match at least, but something is different. */
2513 fprintf(fplog, "%s\n", msg_mismatch_notice);
2519 static void read_checkpoint(const char* fn,
2521 const t_commrec* cr,
2524 int* init_fep_state,
2525 CheckpointHeaderContents* headerContents,
2527 ObservablesHistory* observablesHistory,
2528 gmx_bool reproducibilityRequested,
2529 const gmx::MdModulesNotifier& mdModulesNotifier,
2530 gmx::ReadCheckpointDataHolder* modularSimulatorCheckpointData,
2531 bool useModularSimulator)
2534 char buf[STEPSTRSIZE];
2537 fp = gmx_fio_open(fn, "r");
2538 do_cpt_header(gmx_fio_getxdr(fp), TRUE, nullptr, headerContents);
2540 // If we are appending, then we don't want write to the open log
2541 // file because we still need to compute a checksum for it. In
2542 // that case, the filehandle will be nullptr. Otherwise, we report
2543 // to the new log file about the checkpoint file that we are
2545 FILE* fplog = gmx_fio_getfp(logfio);
2548 fprintf(fplog, "\n");
2549 fprintf(fplog, "Reading checkpoint file %s\n", fn);
2550 fprintf(fplog, " file generated by: %s\n", headerContents->fprog);
2551 fprintf(fplog, " file generated at: %s\n", headerContents->ftime);
2552 fprintf(fplog, " GROMACS double prec.: %d\n", headerContents->double_prec);
2553 fprintf(fplog, " simulation part #: %d\n", headerContents->simulation_part);
2554 fprintf(fplog, " step: %s\n", gmx_step_str(headerContents->step, buf));
2555 fprintf(fplog, " time: %f\n", headerContents->t);
2556 fprintf(fplog, "\n");
2559 if (headerContents->natoms != state->natoms)
2562 "Checkpoint file is for a system of %d atoms, while the current system consists "
2564 headerContents->natoms,
2567 if (headerContents->ngtc != state->ngtc)
2570 "Checkpoint file is for a system of %d T-coupling groups, while the current "
2571 "system consists of %d T-coupling groups",
2572 headerContents->ngtc,
2575 if (headerContents->nnhpres != state->nnhpres)
2578 "Checkpoint file is for a system of %d NH-pressure-coupling variables, while the "
2579 "current system consists of %d NH-pressure-coupling variables",
2580 headerContents->nnhpres,
2584 int nlambdaHistory = (state->dfhist ? state->dfhist->nlambda : 0);
2585 if (headerContents->nlambda != nlambdaHistory)
2588 "Checkpoint file is for a system with %d lambda states, while the current system "
2589 "consists of %d lambda states",
2590 headerContents->nlambda,
2594 init_gtc_state(state,
2597 headerContents->nhchainlength); /* need to keep this here to keep the tpr format working */
2598 /* write over whatever was read; we use the number of Nose-Hoover chains from the checkpoint */
2600 if (headerContents->eIntegrator != eIntegrator)
2603 "Cannot change integrator during a checkpoint restart. Perhaps you should make a "
2604 "new .tpr with grompp -f new.mdp -t %s",
2608 // For modular simulator, no state object is populated, so we cannot do this check here!
2609 if (headerContents->flags_state != state->flags && !useModularSimulator)
2612 "Cannot change a simulation algorithm during a checkpoint restart. Perhaps you "
2613 "should make a new .tpr with grompp -f new.mdp -t %s",
2617 GMX_RELEASE_ASSERT(!(headerContents->isModularSimulatorCheckpoint && !useModularSimulator),
2618 "Checkpoint file was written by modular simulator, but the current "
2619 "simulation uses the legacy simulator.\n\n"
2620 "Try the following steps:\n"
2621 "1. Make sure the GMX_DISABLE_MODULAR_SIMULATOR environment variable is not "
2622 "set to return to the default behavior. Retry running the simulation.\n"
2623 "2. If the problem persists, set the environment variable "
2624 "GMX_USE_MODULAR_SIMULATOR=ON to overwrite the default behavior and use "
2625 "modular simulator for all implemented use cases.");
2626 GMX_RELEASE_ASSERT(!(!headerContents->isModularSimulatorCheckpoint && useModularSimulator),
2627 "Checkpoint file was written by legacy simulator, but the current "
2628 "simulation uses the modular simulator.\n\n"
2629 "Try the following steps:\n"
2630 "1. Make sure the GMX_USE_MODULAR_SIMULATOR environment variable is not set "
2631 "to return to the default behavior. Retry running the simulation.\n"
2632 "2. If the problem persists, set the environment variable "
2633 "GMX_DISABLE_MODULAR_SIMULATOR=ON to overwrite the default behavior and use "
2634 "legacy simulator for all implemented use cases.");
2638 check_match(fplog, cr, dd_nc, *headerContents, reproducibilityRequested);
2641 ret = do_cpt_state(gmx_fio_getxdr(fp), headerContents->flags_state, state, nullptr);
2642 *init_fep_state = state->fep_state; /* there should be a better way to do this than setting it
2643 here. Investigate for 5.0. */
2648 ret = do_cpt_ekinstate(gmx_fio_getxdr(fp), headerContents->flags_eks, &state->ekinstate, nullptr);
2653 state->ekinstate.hasReadEkinState = (((headerContents->flags_eks & (1 << eeksEKINH)) != 0)
2654 || ((headerContents->flags_eks & (1 << eeksEKINF)) != 0)
2655 || ((headerContents->flags_eks & (1 << eeksEKINO)) != 0)
2656 || (((headerContents->flags_eks & (1 << eeksEKINSCALEF))
2657 | (headerContents->flags_eks & (1 << eeksEKINSCALEH))
2658 | (headerContents->flags_eks & (1 << eeksVSCALE)))
2661 if (headerContents->flags_enh && observablesHistory->energyHistory == nullptr)
2663 observablesHistory->energyHistory = std::make_unique<energyhistory_t>();
2665 ret = do_cpt_enerhist(
2666 gmx_fio_getxdr(fp), TRUE, headerContents->flags_enh, observablesHistory->energyHistory.get(), nullptr);
2672 if (headerContents->flagsPullHistory)
2674 if (observablesHistory->pullHistory == nullptr)
2676 observablesHistory->pullHistory = std::make_unique<PullHistory>();
2678 ret = doCptPullHist(gmx_fio_getxdr(fp),
2680 headerContents->flagsPullHistory,
2681 observablesHistory->pullHistory.get(),
2682 StatePart::pullHistory,
2690 if (headerContents->file_version < 6)
2693 "Continuing from checkpoint files written before GROMACS 4.5 is not supported");
2696 ret = do_cpt_df_hist(
2697 gmx_fio_getxdr(fp), headerContents->flags_dfh, headerContents->nlambda, &state->dfhist, nullptr);
2703 if (headerContents->nED > 0 && observablesHistory->edsamHistory == nullptr)
2705 observablesHistory->edsamHistory = std::make_unique<edsamhistory_t>(edsamhistory_t{});
2707 ret = do_cpt_EDstate(
2708 gmx_fio_getxdr(fp), TRUE, headerContents->nED, observablesHistory->edsamHistory.get(), nullptr);
2714 if (headerContents->flags_awhh != 0 && state->awhHistory == nullptr)
2716 state->awhHistory = std::make_shared<gmx::AwhHistory>();
2718 ret = do_cpt_awh(gmx_fio_getxdr(fp), TRUE, headerContents->flags_awhh, state->awhHistory.get(), nullptr);
2724 if (headerContents->eSwapCoords != eswapNO && observablesHistory->swapHistory == nullptr)
2726 observablesHistory->swapHistory = std::make_unique<swaphistory_t>(swaphistory_t{});
2728 ret = do_cpt_swapstate(
2729 gmx_fio_getxdr(fp), TRUE, headerContents->eSwapCoords, observablesHistory->swapHistory.get(), nullptr);
2735 std::vector<gmx_file_position_t> outputfiles;
2736 ret = do_cpt_files(gmx_fio_getxdr(fp), TRUE, &outputfiles, nullptr, headerContents->file_version);
2741 do_cpt_mdmodules(headerContents->file_version, fp, mdModulesNotifier, nullptr);
2742 if (headerContents->file_version >= cptv_ModularSimulator)
2744 gmx::FileIOXdrSerializer serializer(fp);
2745 modularSimulatorCheckpointData->deserialize(&serializer);
2747 ret = do_cpt_footer(gmx_fio_getxdr(fp), headerContents->file_version);
2752 if (gmx_fio_close(fp) != 0)
2754 gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
2759 void load_checkpoint(const char* fn,
2761 const t_commrec* cr,
2765 ObservablesHistory* observablesHistory,
2766 gmx_bool reproducibilityRequested,
2767 const gmx::MdModulesNotifier& mdModulesNotifier,
2768 gmx::ReadCheckpointDataHolder* modularSimulatorCheckpointData,
2769 bool useModularSimulator)
2771 CheckpointHeaderContents headerContents;
2774 /* Read the state from the checkpoint file */
2780 &(ir->fepvals->init_fep_state),
2784 reproducibilityRequested,
2786 modularSimulatorCheckpointData,
2787 useModularSimulator);
2791 gmx_bcast(sizeof(headerContents.step), &headerContents.step, cr->mpiDefaultCommunicator);
2792 gmx::MdModulesCheckpointReadingBroadcast broadcastCheckPointData = {
2793 cr->mpiDefaultCommunicator, PAR(cr), headerContents.file_version
2795 mdModulesNotifier.checkpointingNotifications_.notify(broadcastCheckPointData);
2797 ir->bContinuation = TRUE;
2798 if (ir->nsteps >= 0)
2800 // TODO Should the following condition be <=? Currently if you
2801 // pass a checkpoint written by an normal completion to a restart,
2802 // mdrun will read all input, does some work but no steps, and
2803 // write successful output. But perhaps that is not desirable.
2804 // Note that we do not intend to support the use of mdrun
2805 // -nsteps to circumvent this condition.
2806 if (ir->nsteps + ir->init_step < headerContents.step)
2808 char buf[STEPSTRSIZE];
2809 std::string message =
2810 gmx::formatString("The input requested %s steps, ", gmx_step_str(ir->nsteps, buf));
2811 if (ir->init_step > 0)
2813 message += gmx::formatString("starting from step %s, ", gmx_step_str(ir->init_step, buf));
2815 message += gmx::formatString(
2816 "however the checkpoint "
2817 "file has already reached step %s. The simulation will not "
2818 "proceed, because either your simulation is already complete, "
2819 "or your combination of input files don't match.",
2820 gmx_step_str(headerContents.step, buf));
2821 gmx_fatal(FARGS, "%s", message.c_str());
2823 ir->nsteps += ir->init_step - headerContents.step;
2825 ir->init_step = headerContents.step;
2826 ir->simulation_part = headerContents.simulation_part + 1;
2829 void read_checkpoint_part_and_step(const char* filename, int* simulation_part, int64_t* step)
2833 if (filename == nullptr || !gmx_fexist(filename) || ((fp = gmx_fio_open(filename, "r")) == nullptr))
2835 *simulation_part = 0;
2840 CheckpointHeaderContents headerContents;
2841 do_cpt_header(gmx_fio_getxdr(fp), TRUE, nullptr, &headerContents);
2843 *simulation_part = headerContents.simulation_part;
2844 *step = headerContents.step;
2847 static CheckpointHeaderContents read_checkpoint_data(t_fileio* fp,
2849 std::vector<gmx_file_position_t>* outputfiles,
2850 gmx::ReadCheckpointDataHolder* modularSimulatorCheckpointData)
2852 CheckpointHeaderContents headerContents;
2853 do_cpt_header(gmx_fio_getxdr(fp), TRUE, nullptr, &headerContents);
2854 state->natoms = headerContents.natoms;
2855 state->ngtc = headerContents.ngtc;
2856 state->nnhpres = headerContents.nnhpres;
2857 state->nhchainlength = headerContents.nhchainlength;
2858 state->flags = headerContents.flags_state;
2859 int ret = do_cpt_state(gmx_fio_getxdr(fp), state->flags, state, nullptr);
2864 ret = do_cpt_ekinstate(gmx_fio_getxdr(fp), headerContents.flags_eks, &state->ekinstate, nullptr);
2870 energyhistory_t enerhist;
2871 ret = do_cpt_enerhist(gmx_fio_getxdr(fp), TRUE, headerContents.flags_enh, &enerhist, nullptr);
2876 PullHistory pullHist = {};
2877 ret = doCptPullHist(
2878 gmx_fio_getxdr(fp), TRUE, headerContents.flagsPullHistory, &pullHist, StatePart::pullHistory, nullptr);
2884 ret = do_cpt_df_hist(
2885 gmx_fio_getxdr(fp), headerContents.flags_dfh, headerContents.nlambda, &state->dfhist, nullptr);
2891 edsamhistory_t edsamhist = {};
2892 ret = do_cpt_EDstate(gmx_fio_getxdr(fp), TRUE, headerContents.nED, &edsamhist, nullptr);
2898 ret = do_cpt_awh(gmx_fio_getxdr(fp), TRUE, headerContents.flags_awhh, state->awhHistory.get(), nullptr);
2904 swaphistory_t swaphist = {};
2905 ret = do_cpt_swapstate(gmx_fio_getxdr(fp), TRUE, headerContents.eSwapCoords, &swaphist, nullptr);
2911 ret = do_cpt_files(gmx_fio_getxdr(fp), TRUE, outputfiles, nullptr, headerContents.file_version);
2917 gmx::MdModulesNotifier mdModuleNotifier;
2918 do_cpt_mdmodules(headerContents.file_version, fp, mdModuleNotifier, nullptr);
2919 if (headerContents.file_version >= cptv_ModularSimulator)
2921 // Store modular checkpoint data into modularSimulatorCheckpointData
2922 gmx::FileIOXdrSerializer serializer(fp);
2923 modularSimulatorCheckpointData->deserialize(&serializer);
2925 ret = do_cpt_footer(gmx_fio_getxdr(fp), headerContents.file_version);
2930 return headerContents;
2933 void read_checkpoint_trxframe(t_fileio* fp, t_trxframe* fr)
2936 std::vector<gmx_file_position_t> outputfiles;
2937 gmx::ReadCheckpointDataHolder modularSimulatorCheckpointData;
2938 CheckpointHeaderContents headerContents =
2939 read_checkpoint_data(fp, &state, &outputfiles, &modularSimulatorCheckpointData);
2940 if (headerContents.isModularSimulatorCheckpoint)
2942 gmx::ModularSimulator::readCheckpointToTrxFrame(fr, &modularSimulatorCheckpointData, headerContents);
2946 fr->natoms = state.natoms;
2948 fr->step = int64_to_int(headerContents.step, "conversion of checkpoint to trajectory");
2950 fr->time = headerContents.t;
2952 fr->lambda = state.lambda[efptFEP];
2953 fr->fep_state = state.fep_state;
2955 fr->bX = ((state.flags & (1 << estX)) != 0);
2958 fr->x = makeRvecArray(state.x, state.natoms);
2960 fr->bV = ((state.flags & (1 << estV)) != 0);
2963 fr->v = makeRvecArray(state.v, state.natoms);
2966 fr->bBox = ((state.flags & (1 << estBOX)) != 0);
2969 copy_mat(state.box, fr->box);
2973 void list_checkpoint(const char* fn, FILE* out)
2980 fp = gmx_fio_open(fn, "r");
2981 CheckpointHeaderContents headerContents;
2982 do_cpt_header(gmx_fio_getxdr(fp), TRUE, out, &headerContents);
2983 state.natoms = headerContents.natoms;
2984 state.ngtc = headerContents.ngtc;
2985 state.nnhpres = headerContents.nnhpres;
2986 state.nhchainlength = headerContents.nhchainlength;
2987 state.flags = headerContents.flags_state;
2988 ret = do_cpt_state(gmx_fio_getxdr(fp), state.flags, &state, out);
2993 ret = do_cpt_ekinstate(gmx_fio_getxdr(fp), headerContents.flags_eks, &state.ekinstate, out);
2999 energyhistory_t enerhist;
3000 ret = do_cpt_enerhist(gmx_fio_getxdr(fp), TRUE, headerContents.flags_enh, &enerhist, out);
3004 PullHistory pullHist = {};
3005 ret = doCptPullHist(
3006 gmx_fio_getxdr(fp), TRUE, headerContents.flagsPullHistory, &pullHist, StatePart::pullHistory, out);
3011 ret = do_cpt_df_hist(
3012 gmx_fio_getxdr(fp), headerContents.flags_dfh, headerContents.nlambda, &state.dfhist, out);
3017 edsamhistory_t edsamhist = {};
3018 ret = do_cpt_EDstate(gmx_fio_getxdr(fp), TRUE, headerContents.nED, &edsamhist, out);
3023 ret = do_cpt_awh(gmx_fio_getxdr(fp), TRUE, headerContents.flags_awhh, state.awhHistory.get(), out);
3028 swaphistory_t swaphist = {};
3029 ret = do_cpt_swapstate(gmx_fio_getxdr(fp), TRUE, headerContents.eSwapCoords, &swaphist, out);
3034 std::vector<gmx_file_position_t> outputfiles;
3035 ret = do_cpt_files(gmx_fio_getxdr(fp), TRUE, &outputfiles, out, headerContents.file_version);
3037 gmx::MdModulesNotifier mdModuleNotifier;
3038 do_cpt_mdmodules(headerContents.file_version, fp, mdModuleNotifier, out);
3039 if (headerContents.file_version >= cptv_ModularSimulator)
3041 gmx::FileIOXdrSerializer serializer(fp);
3042 gmx::ReadCheckpointDataHolder modularSimulatorCheckpointData;
3043 modularSimulatorCheckpointData.deserialize(&serializer);
3044 modularSimulatorCheckpointData.dump(out);
3049 ret = do_cpt_footer(gmx_fio_getxdr(fp), headerContents.file_version);
3056 if (gmx_fio_close(fp) != 0)
3058 gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
3062 /* This routine cannot print tons of data, since it is called before the log file is opened. */
3063 CheckpointHeaderContents read_checkpoint_simulation_part_and_filenames(t_fileio* fp,
3064 std::vector<gmx_file_position_t>* outputfiles)
3067 gmx::ReadCheckpointDataHolder modularSimulatorCheckpointData;
3068 CheckpointHeaderContents headerContents =
3069 read_checkpoint_data(fp, &state, outputfiles, &modularSimulatorCheckpointData);
3070 if (gmx_fio_close(fp) != 0)
3072 gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
3074 return headerContents;