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/enumerationhelpers.h"
81 #include "gromacs/utility/fatalerror.h"
82 #include "gromacs/utility/futil.h"
83 #include "gromacs/utility/gmxassert.h"
84 #include "gromacs/utility/int64_to_int.h"
85 #include "gromacs/utility/keyvaluetree.h"
86 #include "gromacs/utility/keyvaluetreebuilder.h"
87 #include "gromacs/utility/keyvaluetreeserializer.h"
88 #include "gromacs/utility/mdmodulenotification.h"
89 #include "gromacs/utility/programcontext.h"
90 #include "gromacs/utility/smalloc.h"
91 #include "gromacs/utility/sysinfo.h"
92 #include "gromacs/utility/textwriter.h"
93 #include "gromacs/utility/txtdump.h"
95 #define CPT_MAGIC1 171817
96 #define CPT_MAGIC2 171819
101 template<typename ValueType>
102 void readKvtCheckpointValue(compat::not_null<ValueType*> value,
103 const std::string& name,
104 const std::string& identifier,
105 const KeyValueTreeObject& kvt)
107 const std::string key = identifier + "-" + name;
108 if (!kvt.keyExists(key))
110 std::string errorMessage = "Cannot read requested checkpoint value " + key + " .";
111 GMX_THROW(InternalError(errorMessage));
113 *value = kvt[key].cast<ValueType>();
116 template void readKvtCheckpointValue(compat::not_null<std::int64_t*> value,
117 const std::string& name,
118 const std::string& identifier,
119 const KeyValueTreeObject& kvt);
120 template void readKvtCheckpointValue(compat::not_null<real*> value,
121 const std::string& name,
122 const std::string& identifier,
123 const KeyValueTreeObject& kvt);
125 template<typename ValueType>
126 void writeKvtCheckpointValue(const ValueType& value,
127 const std::string& name,
128 const std::string& identifier,
129 KeyValueTreeObjectBuilder kvtBuilder)
131 kvtBuilder.addValue<ValueType>(identifier + "-" + name, value);
134 template void writeKvtCheckpointValue(const std::int64_t& value,
135 const std::string& name,
136 const std::string& identifier,
137 KeyValueTreeObjectBuilder kvtBuilder);
138 template void writeKvtCheckpointValue(const real& value,
139 const std::string& name,
140 const std::string& identifier,
141 KeyValueTreeObjectBuilder kvtBuilder);
146 /*! \brief Enum of values that describe the contents of a cpt file
147 * whose format matches a version number
149 * The enum helps the code be more self-documenting and ensure merges
150 * do not silently resolve when two patches make the same bump. When
151 * adding new functionality, add a new element just above cptv_Count
152 * in this enumeration, and write code below that does the right thing
153 * according to the value of file_version.
157 cptv_Unknown = 17, /**< Version before numbering scheme */
158 cptv_RemoveBuildMachineInformation, /**< remove functionality that makes mdrun builds non-reproducible */
159 cptv_ComPrevStepAsPullGroupReference, /**< Allow using COM of previous step as pull group PBC reference */
160 cptv_PullAverage, /**< Added possibility to output average pull force and position */
161 cptv_MdModules, /**< Added checkpointing for MdModules */
162 cptv_ModularSimulator, /**< Added checkpointing for modular simulator */
163 cptv_Count /**< the total number of cptv versions */
166 /*! \brief Version number of the file format written to checkpoint
167 * files by this version of the code.
169 * cpt_version should normally only be changed, via adding a new field
170 * to cptv enumeration, when the header or footer format changes.
172 * The state data format itself is backward and forward compatible.
173 * But old code can not read a new entry that is present in the file
174 * (but can read a new format when new entries are not present).
176 * The cpt_version increases whenever the file format in the main
177 * development branch changes, due to an extension of the cptv enum above.
178 * Backward compatibility for reading old run input files is maintained
179 * by checking this version number against that of the file and then using
180 * the correct code path. */
181 static const int cpt_version = cptv_Count - 1;
183 const char* enumValueToString(StateEntry enumValue)
185 static constexpr gmx::EnumerationArray<StateEntry, const char*> stateEntryNames = {
192 "thermostat-integral",
197 "LD-rng-unsupported",
198 "LD-rng-i-unsupported",
211 "MC-rng-unsupported",
212 "MC-rng-i-unsupported",
215 return stateEntryNames[enumValue];
218 enum class StateKineticEntry : int
226 EkinNoseHooverScaleFullStep,
227 EkinNoseHooverScaleHalfStep,
233 static const char* enumValueToString(StateKineticEntry enumValue)
235 static constexpr gmx::EnumerationArray<StateKineticEntry, const char*> stateKineticEntryNames = {
236 "Ekin_n", "Ekinh", "dEkindlambda", "mv_cos", "Ekinf",
237 "Ekinh_old", "EkinScaleF_NHC", "EkinScaleH_NHC", "Vscale_NHC", "Ekin_Total"
239 return stateKineticEntryNames[enumValue];
242 enum class StateEnergyEntry : int
259 enum class StatePullEntry : int
268 enum class StatePullCoordEntry : int
280 static const char* enumValueToString(StatePullCoordEntry enumValue)
282 static constexpr gmx::EnumerationArray<StatePullCoordEntry, const char*> statePullCoordEntryNames = {
283 "reference-sum", "sum", "dr01-sum", "dr23-sum", "dr45-sum", "fscal-sum", "dynax-sum"
285 return statePullCoordEntryNames[enumValue];
288 enum class StatePullGroupEntry : int
294 static const char* enumValueToString(StatePullGroupEntry enumValue)
296 static constexpr gmx::EnumerationArray<StatePullGroupEntry, const char*> statePullGroupEntryNames = {
299 return statePullGroupEntryNames[enumValue];
302 static const char* enumValueToString(StateEnergyEntry enumValue)
304 static constexpr gmx::EnumerationArray<StateEnergyEntry, const char*> stateEnergyEntryNames = {
314 "energy_delta_h_list",
315 "energy_delta_h_start_time",
316 "energy_delta_h_start_lambda"
318 return stateEnergyEntryNames[enumValue];
321 static const char* enumValueToString(StatePullEntry enumValue)
323 static constexpr gmx::EnumerationArray<StatePullEntry, const char*> statePullEntryNames = {
324 "pullhistory_numcoordinates",
325 "pullhistory_numgroups",
326 "pullhistory_numvaluesinxsum",
327 "pullhistory_numvaluesinfsum"
329 return statePullEntryNames[enumValue];
332 /* free energy history variables -- need to be preserved over checkpoint */
333 enum class StateFepEntry : int
352 //! free energy history names
353 static const char* enumValueToString(StateFepEntry enumValue)
355 static constexpr gmx::EnumerationArray<StateFepEntry, const char*> stateFepEntryNames = {
358 "Wang-Landau Histogram",
366 "accumulated_plus_2",
367 "accumulated_minus_2",
371 return stateFepEntryNames[enumValue];
374 //! AWH biasing history variables
375 enum class StateAwhEntry : int
378 EquilibrateHistogram,
384 LogScaledSampleWeight,
386 ForceCorrelationGrid,
390 static const char* enumValueToString(StateAwhEntry enumValue)
392 static constexpr gmx::EnumerationArray<StateAwhEntry, const char*> stateAwhEntryNames = {
393 "awh_in_initial", "awh_equilibrateHistogram", "awh_histsize", "awh_npoints",
394 "awh_coordpoint", "awh_umbrellaGridpoint", "awh_updatelist", "awh_logScaledSampleWeight",
395 "awh_numupdates", "awh_forceCorrelationGrid"
397 return stateAwhEntryNames[enumValue];
400 enum class StatePullCommunicationEntry : int
406 //! Higher level vector element type, only used for formatting checkpoint dumps
407 enum class CptElementType
409 integer, //!< integer
410 real, //!< float or double, not linked to precision of type real
411 real3, //!< float[3] or double[3], not linked to precision of type real
412 matrix3x3 //!< float[3][3] or double[3][3], not linked to precision of type real
415 static void cp_warning(FILE* fp)
417 fprintf(fp, "\nWARNING: Checkpoint file is corrupted or truncated\n\n");
420 [[noreturn]] static void cp_error()
422 gmx_fatal(FARGS, "Checkpoint file corrupted/truncated, or maybe you are out of disk space?");
425 static void do_cpt_string_err(XDR* xd, const char* desc, gmx::ArrayRef<char> s, FILE* list)
427 char* data = s.data();
428 if (xdr_string(xd, &data, s.size()) == 0)
434 fprintf(list, "%s = %s\n", desc, data);
438 static int do_cpt_int(XDR* xd, const char* desc, int* i, FILE* list)
440 if (xdr_int(xd, i) == 0)
446 fprintf(list, "%s = %d\n", desc, *i);
451 static int do_cpt_u_chars(XDR* xd, const char* desc, int n, unsigned char* i, FILE* list)
455 fprintf(list, "%s = ", desc);
458 for (int j = 0; j < n && res; j++)
460 res &= xdr_u_char(xd, &i[j]);
463 fprintf(list, "%02x", i[j]);
478 static void do_cpt_int_err(XDR* xd, const char* desc, int* i, FILE* list)
480 if (do_cpt_int(xd, desc, i, list) < 0)
486 static void do_cpt_bool_err(XDR* xd, const char* desc, bool* b, FILE* list)
488 int i = static_cast<int>(*b);
490 if (do_cpt_int(xd, desc, &i, list) < 0)
498 static void do_cpt_step_err(XDR* xd, const char* desc, int64_t* i, FILE* list)
500 char buf[STEPSTRSIZE];
502 if (xdr_int64(xd, i) == 0)
508 fprintf(list, "%s = %s\n", desc, gmx_step_str(*i, buf));
512 static void do_cpt_double_err(XDR* xd, const char* desc, double* f, FILE* list)
514 if (xdr_double(xd, f) == 0)
520 fprintf(list, "%s = %f\n", desc, *f);
524 static void do_cpt_real_err(XDR* xd, real* f)
527 bool_t res = xdr_double(xd, f);
529 bool_t res = xdr_float(xd, f);
537 static void do_cpt_n_rvecs_err(XDR* xd, const char* desc, int n, rvec f[], FILE* list)
539 for (int i = 0; i < n; i++)
541 for (int j = 0; j < DIM; j++)
543 do_cpt_real_err(xd, &f[i][j]);
549 pr_rvecs(list, 0, desc, f, n);
561 static const int value = xdr_datatype_int;
565 struct xdr_type<float>
567 static const int value = xdr_datatype_float;
571 struct xdr_type<double>
573 static const int value = xdr_datatype_double;
576 //! \brief Returns size in byte of an xdr_datatype
577 static inline unsigned int sizeOfXdrType(int xdrType)
581 case xdr_datatype_int: return sizeof(int);
582 case xdr_datatype_float: return sizeof(float);
583 case xdr_datatype_double: return sizeof(double);
584 default: GMX_RELEASE_ASSERT(false, "XDR data type not implemented");
590 //! \brief Returns the XDR process function for i/o of an XDR type
591 static inline xdrproc_t xdrProc(int xdrType)
595 case xdr_datatype_int: return reinterpret_cast<xdrproc_t>(xdr_int);
596 case xdr_datatype_float: return reinterpret_cast<xdrproc_t>(xdr_float);
597 case xdr_datatype_double: return reinterpret_cast<xdrproc_t>(xdr_double);
598 default: GMX_RELEASE_ASSERT(false, "XDR data type not implemented");
604 /*! \brief Lists or only reads an xdr vector from checkpoint file
606 * When list!=NULL reads and lists the \p nf vector elements of type \p xdrType.
607 * The header for the print is set by \p part and \p ecpt.
608 * The formatting of the printing is set by \p cptElementType.
609 * When list==NULL only reads the elements.
611 template<typename Enum>
612 static bool_t listXdrVector(XDR* xd, Enum ecpt, int nf, int xdrType, FILE* list, CptElementType cptElementType)
616 const unsigned int elemSize = sizeOfXdrType(xdrType);
617 std::vector<char> data(nf * elemSize);
618 res = xdr_vector(xd, data.data(), nf, elemSize, xdrProc(xdrType));
624 case xdr_datatype_int:
625 pr_ivec(list, 0, enumValueToString(ecpt), reinterpret_cast<const int*>(data.data()), nf, TRUE);
627 case xdr_datatype_float:
629 if (cptElementType == CptElementType::real3)
631 pr_rvecs(list, 0, enumValueToString(ecpt), reinterpret_cast<const rvec*>(data.data()), nf / 3);
636 /* Note: With double precision code dumping a single precision rvec will produce float iso rvec print, but that's a minor annoyance */
637 pr_fvec(list, 0, enumValueToString(ecpt), reinterpret_cast<const float*>(data.data()), nf, TRUE);
640 case xdr_datatype_double:
642 if (cptElementType == CptElementType::real3)
644 pr_rvecs(list, 0, enumValueToString(ecpt), reinterpret_cast<const rvec*>(data.data()), nf / 3);
649 /* Note: With single precision code dumping a double precision rvec will produce float iso rvec print, but that's a minor annoyance */
650 pr_dvec(list, 0, enumValueToString(ecpt), reinterpret_cast<const double*>(data.data()), nf, TRUE);
653 default: GMX_RELEASE_ASSERT(false, "Data type not implemented for listing");
660 //! \brief Convert a double array, typed char*, to float
661 gmx_unused static void convertArrayRealPrecision(const char* c, float* v, int n)
663 const double* d = reinterpret_cast<const double*>(c);
664 for (int i = 0; i < n; i++)
666 v[i] = static_cast<float>(d[i]);
670 //! \brief Convert a float array, typed char*, to double
671 static void convertArrayRealPrecision(const char* c, double* v, int n)
673 const float* f = reinterpret_cast<const float*>(c);
674 for (int i = 0; i < n; i++)
676 v[i] = static_cast<double>(f[i]);
680 //! \brief Generate an error for trying to convert to integer
681 static void convertArrayRealPrecision(const char gmx_unused* c, int gmx_unused* v, int gmx_unused n)
683 GMX_RELEASE_ASSERT(false,
684 "We only expect type mismatches between float and double, not integer");
687 /*! \brief Low-level routine for reading/writing a vector of reals from/to file.
689 * This is the only routine that does the actually i/o of real vector,
690 * all other routines are intermediate level routines for specific real
691 * data types, calling this routine.
692 * Currently this routine is (too) complex, since it handles both real *
693 * and std::vector<real>. Using real * is deprecated and this routine
694 * will simplify a lot when only std::vector needs to be supported.
696 * The routine is generic to vectors with different allocators,
697 * because as part of reading a checkpoint there are vectors whose
698 * size is not known until reading has progressed far enough, so a
699 * resize method must be called.
701 * When not listing, we use either v or vector, depending on which is !=NULL.
702 * If nval >= 0, nval is used; on read this should match the passed value.
703 * If nval n<0, *nptr (with v) or vector->size() is used. On read using v,
704 * the value is stored in nptr
706 template<typename T, typename AllocatorType, typename Enum>
707 static int doVectorLow(XDR* xd,
713 std::vector<T, AllocatorType>* vector,
715 CptElementType cptElementType)
717 GMX_RELEASE_ASSERT(list != nullptr || (v != nullptr && vector == nullptr)
718 || (v == nullptr && vector != nullptr),
719 "Without list, we should have exactly one of v and vector != NULL");
723 int numElemInTheFile;
728 GMX_RELEASE_ASSERT(nptr == nullptr, "With nval>=0 we should have nptr==NULL");
729 numElemInTheFile = nval;
735 GMX_RELEASE_ASSERT(nptr != nullptr, "With nval<0 we should have nptr!=NULL");
736 numElemInTheFile = *nptr;
740 numElemInTheFile = vector->size();
744 /* Read/write the vector element count */
745 res = xdr_int(xd, &numElemInTheFile);
750 /* Read/write the element data type */
751 constexpr int xdrTypeInTheCode = xdr_type<T>::value;
752 int xdrTypeInTheFile = xdrTypeInTheCode;
753 res = xdr_int(xd, &xdrTypeInTheFile);
759 if (list == nullptr && (sflags & enumValueToBitMask(ecpt)))
763 if (numElemInTheFile != nval)
766 "Count mismatch for state entry %s, code count is %d, file count is %d\n",
767 enumValueToString(ecpt),
772 else if (nptr != nullptr)
774 *nptr = numElemInTheFile;
777 bool typesMatch = (xdrTypeInTheFile == xdrTypeInTheCode);
782 "mismatch for state entry %s, code precision is %s, file precision is %s",
783 enumValueToString(ecpt),
784 xdr_datatype_names[xdrTypeInTheCode],
785 xdr_datatype_names[xdrTypeInTheFile]);
787 /* Matching int and real should never occur, but check anyhow */
788 if (xdrTypeInTheFile == xdr_datatype_int || xdrTypeInTheCode == xdr_datatype_int)
791 "Type %s: incompatible checkpoint formats or corrupted checkpoint file.",
801 snew(*v, numElemInTheFile);
807 /* This conditional ensures that we don't resize on write.
808 * In particular in the state where this code was written
809 * vector has a size of numElemInThefile and we
810 * don't want to lose that padding here.
812 if (vector->size() < static_cast<unsigned int>(numElemInTheFile))
814 vector->resize(numElemInTheFile);
822 vChar = reinterpret_cast<char*>(vp);
826 snew(vChar, numElemInTheFile * sizeOfXdrType(xdrTypeInTheFile));
829 xd, vChar, numElemInTheFile, sizeOfXdrType(xdrTypeInTheFile), xdrProc(xdrTypeInTheFile));
837 /* In the old code float-double conversion came for free.
838 * In the new code we still support it, mainly because
839 * the tip4p_continue regression test makes use of this.
840 * It's an open question if we do or don't want to allow this.
842 convertArrayRealPrecision(vChar, vp, numElemInTheFile);
848 res = listXdrVector(xd, ecpt, numElemInTheFile, xdrTypeInTheFile, list, cptElementType);
854 //! \brief Read/Write a std::vector, on read checks the number of elements matches \p numElements, if specified.
855 template<typename T, typename Enum>
856 static int doVector(XDR* xd, Enum ecpt, int sflags, std::vector<T>* vector, FILE* list, int numElements = -1)
858 return doVectorLow<T>(
859 xd, ecpt, sflags, numElements, nullptr, nullptr, vector, list, CptElementType::real);
862 //! \brief Read/Write an ArrayRef<real>.
863 template<typename Enum>
864 static int doRealArrayRef(XDR* xd, Enum ecpt, int sflags, gmx::ArrayRef<real> vector, FILE* list)
866 real* v_real = vector.data();
867 return doVectorLow<real, std::allocator<real>>(
868 xd, ecpt, sflags, vector.size(), nullptr, &v_real, nullptr, list, CptElementType::real);
871 //! Convert from view of RVec to view of real.
872 static gmx::ArrayRef<real> realArrayRefFromRVecArrayRef(gmx::ArrayRef<gmx::RVec> ofRVecs)
874 return gmx::arrayRefFromArray<real>(reinterpret_cast<real*>(ofRVecs.data()), ofRVecs.size() * DIM);
877 //! \brief Read/Write a PaddedVector whose value_type is RVec.
878 template<typename PaddedVectorOfRVecType, typename Enum>
879 static int doRvecVector(XDR* xd, Enum ecpt, int sflags, PaddedVectorOfRVecType* v, int numAtoms, FILE* list)
881 const int numReals = numAtoms * DIM;
886 sflags & enumValueToBitMask(ecpt),
887 "When not listing, the flag for the entry should be set when requesting i/o");
888 GMX_RELEASE_ASSERT(v->size() == numAtoms, "v should have sufficient size for numAtoms");
890 return doRealArrayRef(xd, ecpt, sflags, realArrayRefFromRVecArrayRef(makeArrayRef(*v)), list);
894 // Use the rebind facility to change the value_type of the
895 // allocator from RVec to real.
896 using realAllocator =
897 typename std::allocator_traits<typename PaddedVectorOfRVecType::allocator_type>::template rebind_alloc<real>;
898 return doVectorLow<real, realAllocator>(
899 xd, ecpt, sflags, numReals, nullptr, nullptr, nullptr, list, CptElementType::real);
903 /* This function stores n along with the reals for reading,
904 * but on reading it assumes that n matches the value in the checkpoint file,
905 * a fatal error is generated when this is not the case.
907 template<typename Enum>
908 static int do_cpte_reals(XDR* xd, Enum ecpt, int sflags, int n, real** v, FILE* list)
910 return doVectorLow<real, std::allocator<real>>(
911 xd, ecpt, sflags, n, nullptr, v, nullptr, list, CptElementType::real);
914 /* This function does the same as do_cpte_reals,
915 * except that on reading it ignores the passed value of *n
916 * and stores the value read from the checkpoint file in *n.
918 template<typename Enum>
919 static int do_cpte_n_reals(XDR* xd, Enum ecpt, int sflags, int* n, real** v, FILE* list)
921 return doVectorLow<real, std::allocator<real>>(
922 xd, ecpt, sflags, -1, n, v, nullptr, list, CptElementType::real);
925 template<typename Enum>
926 static int do_cpte_real(XDR* xd, Enum ecpt, int sflags, real* r, FILE* list)
928 return doVectorLow<real, std::allocator<real>>(
929 xd, ecpt, sflags, 1, nullptr, &r, nullptr, list, CptElementType::real);
932 template<typename Enum>
933 static int do_cpte_ints(XDR* xd, Enum ecpt, int sflags, int n, int** v, FILE* list)
935 return doVectorLow<int, std::allocator<int>>(
936 xd, ecpt, sflags, n, nullptr, v, nullptr, list, CptElementType::integer);
939 template<typename Enum>
940 static int do_cpte_int(XDR* xd, Enum ecpt, int sflags, int* i, FILE* list)
942 return do_cpte_ints(xd, ecpt, sflags, 1, &i, list);
945 template<typename Enum>
946 static int do_cpte_bool(XDR* xd, Enum ecpt, int sflags, bool* b, FILE* list)
948 int i = static_cast<int>(*b);
949 int ret = do_cpte_int(xd, ecpt, sflags, &i, list);
954 template<typename Enum>
955 static int do_cpte_doubles(XDR* xd, Enum ecpt, int sflags, int n, double** v, FILE* list)
957 return doVectorLow<double, std::allocator<double>>(
958 xd, ecpt, sflags, n, nullptr, v, nullptr, list, CptElementType::real);
961 template<typename Enum>
962 static int do_cpte_double(XDR* xd, Enum ecpt, int sflags, double* r, FILE* list)
964 return do_cpte_doubles(xd, ecpt, sflags, 1, &r, list);
967 template<typename Enum>
968 static int do_cpte_matrix(XDR* xd, Enum ecpt, int sflags, matrix v, FILE* list)
974 ret = doVectorLow<real, std::allocator<real>>(
975 xd, ecpt, sflags, DIM * DIM, nullptr, &vr, nullptr, nullptr, CptElementType::matrix3x3);
977 if (list && ret == 0)
979 pr_rvecs(list, 0, enumValueToString(ecpt), v, DIM);
985 template<typename Enum>
986 static int do_cpte_nmatrix(XDR* xd, Enum ecpt, int sflags, int n, real** v, FILE* list)
990 char name[CPTSTRLEN];
997 for (i = 0; i < n; i++)
999 reti = doVectorLow<real, std::allocator<real>>(
1000 xd, ecpt, sflags, n, nullptr, &(v[i]), nullptr, nullptr, CptElementType::matrix3x3);
1001 if (list && reti == 0)
1003 sprintf(name, "%s[%d]", enumValueToString(ecpt), i);
1004 pr_reals(list, 0, name, v[i], n);
1014 template<typename Enum>
1015 static int do_cpte_matrices(XDR* xd, Enum ecpt, int sflags, int n, matrix** v, FILE* list)
1018 matrix *vp, *va = nullptr;
1024 res = xdr_int(xd, &nf);
1029 if (list == nullptr && nf != n)
1032 "Count mismatch for state entry %s, code count is %d, file count is %d\n",
1033 enumValueToString(ecpt),
1037 if (list || !(sflags & enumValueToBitMask(ecpt)))
1050 snew(vr, nf * DIM * DIM);
1051 for (i = 0; i < nf; i++)
1053 for (j = 0; j < DIM; j++)
1055 for (k = 0; k < DIM; k++)
1057 vr[(i * DIM + j) * DIM + k] = vp[i][j][k];
1061 ret = doVectorLow<real, std::allocator<real>>(
1062 xd, ecpt, sflags, nf * DIM * DIM, nullptr, &vr, nullptr, nullptr, CptElementType::matrix3x3);
1063 for (i = 0; i < nf; i++)
1065 for (j = 0; j < DIM; j++)
1067 for (k = 0; k < DIM; k++)
1069 vp[i][j][k] = vr[(i * DIM + j) * DIM + k];
1075 if (list && ret == 0)
1077 for (i = 0; i < nf; i++)
1079 pr_rvecs(list, 0, enumValueToString(ecpt), vp[i], DIM);
1090 static void do_cpt_header(XDR* xd, gmx_bool bRead, FILE* list, CheckpointHeaderContents* contents)
1103 res = xdr_int(xd, &magic);
1107 "The checkpoint file is empty/corrupted, or maybe you are out of disk space?");
1109 if (magic != CPT_MAGIC1)
1112 "Start of file magic number mismatch, checkpoint file has %d, should be %d\n"
1113 "The checkpoint file is corrupted or not a checkpoint file",
1120 gmx_gethostname(fhost, 255);
1122 do_cpt_string_err(xd, "GROMACS version", contents->version, list);
1123 // The following fields are no longer ever written with meaningful
1124 // content, but because they precede the file version, there is no
1125 // good way for new code to read the old and new formats, nor a
1126 // good way for old code to avoid giving an error while reading a
1127 // new format. So we read and write a field that no longer has a
1129 do_cpt_string_err(xd, "GROMACS build time UNUSED", contents->btime_UNUSED, list);
1130 do_cpt_string_err(xd, "GROMACS build user UNUSED", contents->buser_UNUSED, list);
1131 do_cpt_string_err(xd, "GROMACS build host UNUSED", contents->bhost_UNUSED, list);
1132 do_cpt_string_err(xd, "generating program", contents->fprog, list);
1133 do_cpt_string_err(xd, "generation time", contents->ftime, list);
1134 contents->file_version = cpt_version;
1135 do_cpt_int_err(xd, "checkpoint file version", &contents->file_version, list);
1136 if (contents->file_version > cpt_version)
1139 "Attempting to read a checkpoint file of version %d with code of version %d\n",
1140 contents->file_version,
1143 if (contents->file_version >= 13)
1145 do_cpt_int_err(xd, "GROMACS double precision", &contents->double_prec, list);
1149 contents->double_prec = -1;
1151 if (contents->file_version >= 12)
1153 do_cpt_string_err(xd, "generating host", fhost, list);
1155 do_cpt_int_err(xd, "#atoms", &contents->natoms, list);
1156 do_cpt_int_err(xd, "#T-coupling groups", &contents->ngtc, list);
1157 if (contents->file_version >= 10)
1159 do_cpt_int_err(xd, "#Nose-Hoover T-chains", &contents->nhchainlength, list);
1163 contents->nhchainlength = 1;
1165 if (contents->file_version >= 11)
1167 do_cpt_int_err(xd, "#Nose-Hoover T-chains for barostat ", &contents->nnhpres, list);
1171 contents->nnhpres = 0;
1173 if (contents->file_version >= 14)
1175 do_cpt_int_err(xd, "# of total lambda states ", &contents->nlambda, list);
1179 contents->nlambda = 0;
1182 int integrator = static_cast<int>(contents->eIntegrator);
1183 do_cpt_int_err(xd, "integrator", &integrator, list);
1186 contents->eIntegrator = static_cast<IntegrationAlgorithm>(integrator);
1189 if (contents->file_version >= 3)
1191 do_cpt_int_err(xd, "simulation part #", &contents->simulation_part, list);
1195 contents->simulation_part = 1;
1197 if (contents->file_version >= 5)
1199 do_cpt_step_err(xd, "step", &contents->step, list);
1204 do_cpt_int_err(xd, "step", &idum, list);
1205 contents->step = static_cast<int64_t>(idum);
1207 do_cpt_double_err(xd, "t", &contents->t, list);
1208 do_cpt_int_err(xd, "#PP-ranks", &contents->nnodes, list);
1209 do_cpt_int_err(xd, "dd_nc[x]", &contents->dd_nc[XX], list);
1210 do_cpt_int_err(xd, "dd_nc[y]", &contents->dd_nc[YY], list);
1211 do_cpt_int_err(xd, "dd_nc[z]", &contents->dd_nc[ZZ], list);
1212 do_cpt_int_err(xd, "#PME-only ranks", &contents->npme, list);
1213 do_cpt_int_err(xd, "state flags", &contents->flags_state, list);
1214 if (contents->file_version >= 4)
1216 do_cpt_int_err(xd, "ekin data flags", &contents->flags_eks, list);
1217 do_cpt_int_err(xd, "energy history flags", &contents->flags_enh, list);
1221 contents->flags_eks = 0;
1222 contents->flags_enh = (contents->flags_state >> (static_cast<int>(StateEntry::OrireDtav) + 1));
1223 contents->flags_state = (contents->flags_state
1224 & ~((1 << (static_cast<int>(StateEntry::OrireDtav) + 1))
1225 | (1 << (static_cast<int>(StateEntry::OrireDtav) + 2))
1226 | (1 << (static_cast<int>(StateEntry::OrireDtav) + 3))));
1228 if (contents->file_version >= 14)
1230 do_cpt_int_err(xd, "df history flags", &contents->flags_dfh, list);
1234 contents->flags_dfh = 0;
1237 if (contents->file_version >= 15)
1239 do_cpt_int_err(xd, "ED data sets", &contents->nED, list);
1246 if (contents->file_version >= 16)
1248 int swapState = static_cast<int>(contents->eSwapCoords);
1249 do_cpt_int_err(xd, "swap", &swapState, list);
1252 contents->eSwapCoords = static_cast<SwapType>(swapState);
1257 contents->eSwapCoords = SwapType::No;
1260 if (contents->file_version >= 17)
1262 do_cpt_int_err(xd, "AWH history flags", &contents->flags_awhh, list);
1266 contents->flags_awhh = 0;
1269 if (contents->file_version >= 18)
1271 do_cpt_int_err(xd, "pull history flags", &contents->flagsPullHistory, list);
1275 contents->flagsPullHistory = 0;
1278 if (contents->file_version >= cptv_ModularSimulator)
1281 xd, "Is modular simulator checkpoint", &contents->isModularSimulatorCheckpoint, list);
1285 contents->isModularSimulatorCheckpoint = false;
1289 static int do_cpt_footer(XDR* xd, int file_version)
1294 if (file_version >= 2)
1297 res = xdr_int(xd, &magic);
1302 if (magic != CPT_MAGIC2)
1311 static int do_cpt_state(XDR* xd, int fflags, t_state* state, FILE* list)
1314 const int sflags = state->flags;
1315 // If reading, state->natoms was probably just read, so
1316 // allocations need to be managed. If writing, this won't change
1317 // anything that matters.
1318 using StateFlags = gmx::EnumerationArray<StateEntry, bool>;
1319 state_change_natoms(state, state->natoms);
1320 for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
1322 if (fflags & enumValueToBitMask(*i))
1326 case StateEntry::Lambda:
1327 ret = doRealArrayRef(
1331 gmx::arrayRefFromArray<real>(
1332 state->lambda.data(),
1333 gmx::EnumerationArray<FreeEnergyPerturbationCouplingType, real>::size()),
1336 case StateEntry::FepState:
1337 ret = do_cpte_int(xd, *i, sflags, &state->fep_state, list);
1339 case StateEntry::Box: ret = do_cpte_matrix(xd, *i, sflags, state->box, list); break;
1340 case StateEntry::BoxRel:
1341 ret = do_cpte_matrix(xd, *i, sflags, state->box_rel, list);
1343 case StateEntry::BoxV:
1344 ret = do_cpte_matrix(xd, *i, sflags, state->boxv, list);
1346 case StateEntry::PressurePrevious:
1347 ret = do_cpte_matrix(xd, *i, sflags, state->pres_prev, list);
1349 case StateEntry::SVirPrev:
1350 ret = do_cpte_matrix(xd, *i, sflags, state->svir_prev, list);
1352 case StateEntry::FVirPrev:
1353 ret = do_cpte_matrix(xd, *i, sflags, state->fvir_prev, list);
1355 case StateEntry::Nhxi:
1356 ret = doVector<double>(xd, *i, sflags, &state->nosehoover_xi, list);
1358 case StateEntry::Nhvxi:
1359 ret = doVector<double>(xd, *i, sflags, &state->nosehoover_vxi, list);
1361 case StateEntry::Nhpresxi:
1362 ret = doVector<double>(xd, *i, sflags, &state->nhpres_xi, list);
1364 case StateEntry::Nhpresvxi:
1365 ret = doVector<double>(xd, *i, sflags, &state->nhpres_vxi, list);
1367 case StateEntry::ThermInt:
1368 ret = doVector<double>(xd, *i, sflags, &state->therm_integral, list);
1370 case StateEntry::BarosInt:
1371 ret = do_cpte_double(xd, *i, sflags, &state->baros_integral, list);
1373 case StateEntry::Veta:
1374 ret = do_cpte_real(xd, *i, sflags, &state->veta, list);
1376 case StateEntry::Vol0:
1377 ret = do_cpte_real(xd, *i, sflags, &state->vol0, list);
1380 ret = doRvecVector(xd, *i, sflags, &state->x, state->natoms, list);
1383 ret = doRvecVector(xd, *i, sflags, &state->v, state->natoms, list);
1385 /* The RNG entries are no longer written,
1386 * the next 4 lines are only for reading old files.
1387 * It's OK that three case statements fall through.
1389 case StateEntry::LDRngNotSupported:
1390 case StateEntry::LDRngINotSupported:
1391 case StateEntry::MCRngNotSupported:
1392 case StateEntry::MCRngINotSupported:
1393 ret = do_cpte_ints(xd, *i, sflags, 0, nullptr, list);
1395 case StateEntry::DisreInitF:
1396 ret = do_cpte_real(xd, *i, sflags, &state->hist.disre_initf, list);
1398 case StateEntry::DisreRm3Tav:
1399 ret = do_cpte_n_reals(
1400 xd, *i, sflags, &state->hist.ndisrepairs, &state->hist.disre_rm3tav, list);
1402 case StateEntry::OrireInitF:
1403 ret = do_cpte_real(xd, *i, sflags, &state->hist.orire_initf, list);
1405 case StateEntry::OrireDtav:
1406 ret = do_cpte_n_reals(
1407 xd, *i, sflags, &state->hist.norire_Dtav, &state->hist.orire_Dtav, list);
1409 case StateEntry::PullComPrevStep:
1410 ret = doVector<double>(xd, *i, sflags, &state->pull_com_prev_step, list);
1414 "Unknown state entry %d\n"
1415 "You are reading a checkpoint file written by different code, which "
1417 enumValueToBitMask(*i));
1424 static int do_cpt_ekinstate(XDR* xd, int fflags, ekinstate_t* ekins, FILE* list)
1428 using StateFlags = gmx::EnumerationArray<StateKineticEntry, bool>;
1429 for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
1431 if (fflags & enumValueToBitMask(*i))
1436 case StateKineticEntry::EkinNumber:
1437 ret = do_cpte_int(xd, *i, fflags, &ekins->ekin_n, list);
1439 case StateKineticEntry::EkinHalfStep:
1440 ret = do_cpte_matrices(xd, *i, fflags, ekins->ekin_n, &ekins->ekinh, list);
1442 case StateKineticEntry::EkinFullStep:
1443 ret = do_cpte_matrices(xd, *i, fflags, ekins->ekin_n, &ekins->ekinf, list);
1445 case StateKineticEntry::EkinHalfStepOld:
1446 ret = do_cpte_matrices(xd, *i, fflags, ekins->ekin_n, &ekins->ekinh_old, list);
1448 case StateKineticEntry::EkinTotal:
1449 ret = do_cpte_matrix(xd, *i, fflags, ekins->ekin_total, list);
1451 case StateKineticEntry::EkinNoseHooverScaleFullStep:
1452 ret = doVector<double>(xd, *i, fflags, &ekins->ekinscalef_nhc, list);
1454 case StateKineticEntry::VelocityScale:
1455 ret = doVector<double>(xd, *i, fflags, &ekins->vscale_nhc, list);
1457 case StateKineticEntry::EkinNoseHooverScaleHalfStep:
1458 ret = doVector<double>(xd, *i, fflags, &ekins->ekinscaleh_nhc, list);
1460 case StateKineticEntry::DEkinDLambda:
1461 ret = do_cpte_real(xd, *i, fflags, &ekins->dekindl, list);
1463 case StateKineticEntry::Mvcos:
1464 ret = do_cpte_real(xd, *i, fflags, &ekins->mvcos, list);
1468 "Unknown ekin data state entry %d\n"
1469 "You are probably reading a new checkpoint file with old code",
1470 enumValueToBitMask(*i));
1479 static int do_cpt_swapstate(XDR* xd, gmx_bool bRead, SwapType eSwapCoords, swaphistory_t* swapstate, FILE* list)
1481 int swap_cpt_version = 2;
1483 if (eSwapCoords == SwapType::No)
1488 swapstate->bFromCpt = bRead;
1489 swapstate->eSwapCoords = eSwapCoords;
1491 do_cpt_int_err(xd, "swap checkpoint version", &swap_cpt_version, list);
1492 if (bRead && swap_cpt_version < 2)
1495 "Cannot read checkpoint files that were written with old versions"
1496 "of the ion/water position swapping protocol.\n");
1499 do_cpt_int_err(xd, "swap coupling steps", &swapstate->nAverage, list);
1501 /* When reading, init_swapcoords has not been called yet,
1502 * so we have to allocate memory first. */
1503 do_cpt_int_err(xd, "number of ion types", &swapstate->nIonTypes, list);
1506 snew(swapstate->ionType, swapstate->nIonTypes);
1509 for (int ic = 0; ic < eCompNR; ic++)
1511 for (int ii = 0; ii < swapstate->nIonTypes; ii++)
1513 swapstateIons_t* gs = &swapstate->ionType[ii];
1517 do_cpt_int_err(xd, "swap requested atoms", &gs->nMolReq[ic], list);
1521 do_cpt_int_err(xd, "swap requested atoms p", gs->nMolReq_p[ic], list);
1526 do_cpt_int_err(xd, "swap influx net", &gs->inflow_net[ic], list);
1530 do_cpt_int_err(xd, "swap influx net p", gs->inflow_net_p[ic], list);
1533 if (bRead && (nullptr == gs->nMolPast[ic]))
1535 snew(gs->nMolPast[ic], swapstate->nAverage);
1538 for (int j = 0; j < swapstate->nAverage; j++)
1542 do_cpt_int_err(xd, "swap past atom counts", &gs->nMolPast[ic][j], list);
1546 do_cpt_int_err(xd, "swap past atom counts p", &gs->nMolPast_p[ic][j], list);
1552 /* Ion flux per channel */
1553 for (int ic = 0; ic < eChanNR; ic++)
1555 for (int ii = 0; ii < swapstate->nIonTypes; ii++)
1557 swapstateIons_t* gs = &swapstate->ionType[ii];
1561 do_cpt_int_err(xd, "channel flux A->B", &gs->fluxfromAtoB[ic], list);
1565 do_cpt_int_err(xd, "channel flux A->B p", gs->fluxfromAtoB_p[ic], list);
1570 /* Ion flux leakage */
1573 do_cpt_int_err(xd, "flux leakage", &swapstate->fluxleak, list);
1577 do_cpt_int_err(xd, "flux leakage", swapstate->fluxleak_p, list);
1581 for (int ii = 0; ii < swapstate->nIonTypes; ii++)
1583 swapstateIons_t* gs = &swapstate->ionType[ii];
1585 do_cpt_int_err(xd, "number of ions", &gs->nMol, list);
1589 snew(gs->channel_label, gs->nMol);
1590 snew(gs->comp_from, gs->nMol);
1593 do_cpt_u_chars(xd, "channel history", gs->nMol, gs->channel_label, list);
1594 do_cpt_u_chars(xd, "domain history", gs->nMol, gs->comp_from, list);
1597 /* Save the last known whole positions to checkpoint
1598 * file to be able to also make multimeric channels whole in PBC */
1599 do_cpt_int_err(xd, "Ch0 atoms", &swapstate->nat[eChan0], list);
1600 do_cpt_int_err(xd, "Ch1 atoms", &swapstate->nat[eChan1], list);
1603 snew(swapstate->xc_old_whole[eChan0], swapstate->nat[eChan0]);
1604 snew(swapstate->xc_old_whole[eChan1], swapstate->nat[eChan1]);
1605 do_cpt_n_rvecs_err(xd, "Ch0 whole x", swapstate->nat[eChan0], swapstate->xc_old_whole[eChan0], list);
1606 do_cpt_n_rvecs_err(xd, "Ch1 whole x", swapstate->nat[eChan1], swapstate->xc_old_whole[eChan1], list);
1611 xd, "Ch0 whole x", swapstate->nat[eChan0], *swapstate->xc_old_whole_p[eChan0], list);
1613 xd, "Ch1 whole x", swapstate->nat[eChan1], *swapstate->xc_old_whole_p[eChan1], list);
1620 static int do_cpt_enerhist(XDR* xd, gmx_bool bRead, int fflags, energyhistory_t* enerhist, FILE* list)
1629 GMX_RELEASE_ASSERT(enerhist != nullptr, "With energy history, we need a valid enerhist pointer");
1631 /* This is stored/read for backward compatibility */
1632 int energyHistoryNumEnergies = 0;
1635 enerhist->nsteps = 0;
1637 enerhist->nsteps_sim = 0;
1638 enerhist->nsum_sim = 0;
1640 else if (enerhist != nullptr)
1642 energyHistoryNumEnergies = enerhist->ener_sum_sim.size();
1645 delta_h_history_t* deltaH = enerhist->deltaHForeignLambdas.get();
1646 using StateFlags = gmx::EnumerationArray<StateEnergyEntry, bool>;
1647 for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
1649 if (fflags & enumValueToBitMask(*i))
1653 case StateEnergyEntry::N:
1654 ret = do_cpte_int(xd, *i, fflags, &energyHistoryNumEnergies, list);
1656 case StateEnergyEntry::Aver:
1657 ret = doVector<double>(xd, *i, fflags, &enerhist->ener_ave, list);
1659 case StateEnergyEntry::Sum:
1660 ret = doVector<double>(xd, *i, fflags, &enerhist->ener_sum, list);
1662 case StateEnergyEntry::NumSum:
1663 do_cpt_step_err(xd, enumValueToString(*i), &enerhist->nsum, list);
1665 case StateEnergyEntry::SumSim:
1666 ret = doVector<double>(xd, *i, fflags, &enerhist->ener_sum_sim, list);
1668 case StateEnergyEntry::NumSumSim:
1669 do_cpt_step_err(xd, enumValueToString(*i), &enerhist->nsum_sim, list);
1671 case StateEnergyEntry::NumSteps:
1672 do_cpt_step_err(xd, enumValueToString(*i), &enerhist->nsteps, list);
1674 case StateEnergyEntry::NumStepsSim:
1675 do_cpt_step_err(xd, enumValueToString(*i), &enerhist->nsteps_sim, list);
1677 case StateEnergyEntry::DeltaHNN:
1680 if (!bRead && deltaH != nullptr)
1682 numDeltaH = deltaH->dh.size();
1684 do_cpt_int_err(xd, enumValueToString(*i), &numDeltaH, list);
1687 if (deltaH == nullptr)
1689 enerhist->deltaHForeignLambdas = std::make_unique<delta_h_history_t>();
1690 deltaH = enerhist->deltaHForeignLambdas.get();
1692 deltaH->dh.resize(numDeltaH);
1693 deltaH->start_lambda_set = FALSE;
1697 case StateEnergyEntry::DeltaHList:
1698 for (auto dh : deltaH->dh)
1700 ret = doVector<real>(xd, *i, fflags, &dh, list);
1703 case StateEnergyEntry::DeltaHStartTime:
1704 ret = do_cpte_double(xd, *i, fflags, &(deltaH->start_time), list);
1706 case StateEnergyEntry::DeltaHStartLambda:
1707 ret = do_cpte_double(xd, *i, fflags, &(deltaH->start_lambda), list);
1711 "Unknown energy history entry %d\n"
1712 "You are probably reading a new checkpoint file with old code",
1713 enumValueToBitMask(*i));
1718 if ((fflags & enumValueToBitMask(StateEnergyEntry::Sum))
1719 && !(fflags & enumValueToBitMask(StateEnergyEntry::SumSim)))
1721 /* Assume we have an old file format and copy sum to sum_sim */
1722 enerhist->ener_sum_sim = enerhist->ener_sum;
1725 if ((fflags & enumValueToBitMask(StateEnergyEntry::NumSum))
1726 && !(fflags & enumValueToBitMask(StateEnergyEntry::NumSteps)))
1728 /* Assume we have an old file format and copy nsum to nsteps */
1729 enerhist->nsteps = enerhist->nsum;
1731 if ((fflags & enumValueToBitMask(StateEnergyEntry::NumSumSim))
1732 && !(fflags & enumValueToBitMask(StateEnergyEntry::NumStepsSim)))
1734 /* Assume we have an old file format and copy nsum to nsteps */
1735 enerhist->nsteps_sim = enerhist->nsum_sim;
1741 static int doCptPullCoordHist(XDR* xd, PullCoordinateHistory* pullCoordHist, FILE* list)
1746 flags |= (enumValueToBitMask(StatePullCoordEntry::ValueReferenceSum)
1747 | enumValueToBitMask(StatePullCoordEntry::ValueSum)
1748 | enumValueToBitMask(StatePullCoordEntry::DR01Sum)
1749 | enumValueToBitMask(StatePullCoordEntry::DR23Sum)
1750 | enumValueToBitMask(StatePullCoordEntry::DR45Sum)
1751 | enumValueToBitMask(StatePullCoordEntry::FScalarSum));
1753 using StateFlags = gmx::EnumerationArray<StatePullCoordEntry, bool>;
1754 for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
1758 case StatePullCoordEntry::ValueReferenceSum:
1759 ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->valueRef), list);
1761 case StatePullCoordEntry::ValueSum:
1762 ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->value), list);
1764 case StatePullCoordEntry::DR01Sum:
1765 for (int j = 0; j < DIM && ret == 0; j++)
1767 ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->dr01[j]), list);
1770 case StatePullCoordEntry::DR23Sum:
1771 for (int j = 0; j < DIM && ret == 0; j++)
1773 ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->dr23[j]), list);
1776 case StatePullCoordEntry::DR45Sum:
1777 for (int j = 0; j < DIM && ret == 0; j++)
1779 ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->dr45[j]), list);
1782 case StatePullCoordEntry::FScalarSum:
1783 ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->scalarForce), list);
1785 case StatePullCoordEntry::DynaxSum:
1786 for (int j = 0; j < DIM && ret == 0; j++)
1788 ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->dynaX[j]), list);
1792 gmx_fatal(FARGS, "Unhandled StatePullCoordEntry enum value: %d", enumValueToBitMask(*i));
1799 static int doCptPullGroupHist(XDR* xd, PullGroupHistory* pullGroupHist, FILE* list)
1804 flags |= (enumValueToBitMask(StatePullGroupEntry::XSum));
1806 using StateFlags = gmx::EnumerationArray<StatePullGroupEntry, bool>;
1807 for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
1811 case StatePullGroupEntry::XSum:
1812 for (int j = 0; j < DIM && ret == 0; j++)
1814 ret = do_cpte_double(xd, *i, flags, &(pullGroupHist->x[j]), list);
1817 default: gmx_fatal(FARGS, "Unhandled pull group state entry");
1825 static int doCptPullHist(XDR* xd, gmx_bool bRead, int fflags, PullHistory* pullHist, FILE* list)
1828 int pullHistoryNumCoordinates = 0;
1829 int pullHistoryNumGroups = 0;
1831 /* Retain the number of terms in the sum and the number of coordinates (used for writing
1832 * average pull forces and coordinates) in the pull history, in temporary variables,
1833 * in case they cannot be read from the checkpoint, in order to have backward compatibility */
1836 pullHist->numValuesInXSum = 0;
1837 pullHist->numValuesInFSum = 0;
1839 else if (pullHist != nullptr)
1841 pullHistoryNumCoordinates = pullHist->pullCoordinateSums.size();
1842 pullHistoryNumGroups = pullHist->pullGroupSums.size();
1846 GMX_RELEASE_ASSERT(fflags == 0, "Without pull history, all flags should be off");
1849 using StateFlags = gmx::EnumerationArray<StatePullEntry, bool>;
1850 for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
1852 if (fflags & (1 << enumValueToBitMask(*i)))
1856 case StatePullEntry::NumCoordinates:
1857 ret = do_cpte_int(xd, *i, fflags, &pullHistoryNumCoordinates, list);
1859 case StatePullEntry::NumGroups:
1860 do_cpt_int_err(xd, enumValueToString(*i), &pullHistoryNumGroups, list);
1862 case StatePullEntry::NumValuesInXSum:
1863 do_cpt_int_err(xd, enumValueToString(*i), &pullHist->numValuesInXSum, list);
1865 case StatePullEntry::NumValuesInFSum:
1866 do_cpt_int_err(xd, enumValueToString(*i), &pullHist->numValuesInFSum, list);
1870 "Unknown pull history entry %d\n"
1871 "You are probably reading a new checkpoint file with old code",
1872 enumValueToBitMask(*i));
1878 pullHist->pullCoordinateSums.resize(pullHistoryNumCoordinates);
1879 pullHist->pullGroupSums.resize(pullHistoryNumGroups);
1881 if (pullHist->numValuesInXSum > 0 || pullHist->numValuesInFSum > 0)
1883 for (size_t i = 0; i < pullHist->pullCoordinateSums.size() && ret == 0; i++)
1885 ret = doCptPullCoordHist(xd, &(pullHist->pullCoordinateSums[i]), list);
1887 for (size_t i = 0; i < pullHist->pullGroupSums.size() && ret == 0; i++)
1889 ret = doCptPullGroupHist(xd, &(pullHist->pullGroupSums[i]), list);
1896 static int do_cpt_df_hist(XDR* xd, int fflags, int nlambda, df_history_t** dfhistPtr, FILE* list)
1905 if (*dfhistPtr == nullptr)
1907 snew(*dfhistPtr, 1);
1908 (*dfhistPtr)->nlambda = nlambda;
1909 init_df_history(*dfhistPtr, nlambda);
1911 df_history_t* dfhist = *dfhistPtr;
1913 using StateFlags = gmx::EnumerationArray<StateFepEntry, bool>;
1914 for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
1916 if (fflags & enumValueToBitMask(*i))
1920 case StateFepEntry::IsEquilibrated:
1921 ret = do_cpte_bool(xd, *i, fflags, &dfhist->bEquil, list);
1923 case StateFepEntry::NumAtLambda:
1924 ret = do_cpte_ints(xd, *i, fflags, nlambda, &dfhist->n_at_lam, list);
1926 case StateFepEntry::WangLandauHistogram:
1927 ret = do_cpte_reals(xd, *i, fflags, nlambda, &dfhist->wl_histo, list);
1929 case StateFepEntry::WangLandauDelta:
1930 ret = do_cpte_real(xd, *i, fflags, &dfhist->wl_delta, list);
1932 case StateFepEntry::SumWeights:
1933 ret = do_cpte_reals(xd, *i, fflags, nlambda, &dfhist->sum_weights, list);
1935 case StateFepEntry::SumDG:
1936 ret = do_cpte_reals(xd, *i, fflags, nlambda, &dfhist->sum_dg, list);
1938 case StateFepEntry::SumMinVar:
1939 ret = do_cpte_reals(xd, *i, fflags, nlambda, &dfhist->sum_minvar, list);
1941 case StateFepEntry::SumVar:
1942 ret = do_cpte_reals(xd, *i, fflags, nlambda, &dfhist->sum_variance, list);
1944 case StateFepEntry::Accump:
1945 ret = do_cpte_nmatrix(xd, *i, fflags, nlambda, dfhist->accum_p, list);
1947 case StateFepEntry::Accumm:
1948 ret = do_cpte_nmatrix(xd, *i, fflags, nlambda, dfhist->accum_m, list);
1950 case StateFepEntry::Accump2:
1951 ret = do_cpte_nmatrix(xd, *i, fflags, nlambda, dfhist->accum_p2, list);
1953 case StateFepEntry::Accumm2:
1954 ret = do_cpte_nmatrix(xd, *i, fflags, nlambda, dfhist->accum_m2, list);
1956 case StateFepEntry::Tij:
1957 ret = do_cpte_nmatrix(xd, *i, fflags, nlambda, dfhist->Tij, list);
1959 case StateFepEntry::TijEmp:
1960 ret = do_cpte_nmatrix(xd, *i, fflags, nlambda, dfhist->Tij_empirical, list);
1965 "Unknown df history entry %d\n"
1966 "You are probably reading a new checkpoint file with old code",
1967 enumValueToBitMask(*i));
1976 /* This function stores the last whole configuration of the reference and
1977 * average structure in the .cpt file
1979 static int do_cpt_EDstate(XDR* xd, gmx_bool bRead, int nED, edsamhistory_t* EDstate, FILE* list)
1986 EDstate->bFromCpt = bRead;
1989 /* When reading, init_edsam has not been called yet,
1990 * so we have to allocate memory first. */
1993 snew(EDstate->nref, EDstate->nED);
1994 snew(EDstate->old_sref, EDstate->nED);
1995 snew(EDstate->nav, EDstate->nED);
1996 snew(EDstate->old_sav, EDstate->nED);
1999 /* Read/write the last whole conformation of SREF and SAV for each ED dataset (usually only one) */
2000 for (int i = 0; i < EDstate->nED; i++)
2004 /* Reference structure SREF */
2005 sprintf(buf, "ED%d # of atoms in reference structure", i + 1);
2006 do_cpt_int_err(xd, buf, &EDstate->nref[i], list);
2007 sprintf(buf, "ED%d x_ref", i + 1);
2010 snew(EDstate->old_sref[i], EDstate->nref[i]);
2011 do_cpt_n_rvecs_err(xd, buf, EDstate->nref[i], EDstate->old_sref[i], list);
2015 do_cpt_n_rvecs_err(xd, buf, EDstate->nref[i], EDstate->old_sref_p[i], list);
2018 /* Average structure SAV */
2019 sprintf(buf, "ED%d # of atoms in average structure", i + 1);
2020 do_cpt_int_err(xd, buf, &EDstate->nav[i], list);
2021 sprintf(buf, "ED%d x_av", i + 1);
2024 snew(EDstate->old_sav[i], EDstate->nav[i]);
2025 do_cpt_n_rvecs_err(xd, buf, EDstate->nav[i], EDstate->old_sav[i], list);
2029 do_cpt_n_rvecs_err(xd, buf, EDstate->nav[i], EDstate->old_sav_p[i], list);
2036 static int do_cpt_correlation_grid(XDR* xd,
2038 gmx_unused int fflags,
2039 gmx::CorrelationGridHistory* corrGrid,
2041 StateAwhEntry eawhh)
2045 do_cpt_int_err(xd, enumValueToString(eawhh), &(corrGrid->numCorrelationTensors), list);
2046 do_cpt_int_err(xd, enumValueToString(eawhh), &(corrGrid->tensorSize), list);
2047 do_cpt_int_err(xd, enumValueToString(eawhh), &(corrGrid->blockDataListSize), list);
2051 initCorrelationGridHistory(
2052 corrGrid, corrGrid->numCorrelationTensors, corrGrid->tensorSize, corrGrid->blockDataListSize);
2055 for (gmx::CorrelationBlockDataHistory& blockData : corrGrid->blockDataBuffer)
2057 do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.blockSumWeight), list);
2058 do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.blockSumSquareWeight), list);
2059 do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.blockSumWeightX), list);
2060 do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.blockSumWeightY), list);
2061 do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.sumOverBlocksSquareBlockWeight), list);
2062 do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.sumOverBlocksBlockSquareWeight), list);
2064 xd, enumValueToString(eawhh), &(blockData.sumOverBlocksBlockWeightBlockWeightX), list);
2066 xd, enumValueToString(eawhh), &(blockData.sumOverBlocksBlockWeightBlockWeightY), list);
2067 do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.blockLength), list);
2068 do_cpt_int_err(xd, enumValueToString(eawhh), &(blockData.previousBlockIndex), list);
2069 do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.correlationIntegral), list);
2075 static int do_cpt_awh_bias(XDR* xd, gmx_bool bRead, int fflags, gmx::AwhBiasHistory* biasHistory, FILE* list)
2079 gmx::AwhBiasStateHistory* state = &biasHistory->state;
2080 using StateFlags = gmx::EnumerationArray<StateAwhEntry, bool>;
2081 for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
2083 if (fflags & enumValueToBitMask(*i))
2087 case StateAwhEntry::InInitial:
2088 do_cpt_bool_err(xd, enumValueToString(*i), &state->in_initial, list);
2090 case StateAwhEntry::EquilibrateHistogram:
2091 do_cpt_bool_err(xd, enumValueToString(*i), &state->equilibrateHistogram, list);
2093 case StateAwhEntry::HistogramSize:
2094 do_cpt_double_err(xd, enumValueToString(*i), &state->histSize, list);
2096 case StateAwhEntry::NumPoints:
2101 numPoints = biasHistory->pointState.size();
2103 do_cpt_int_err(xd, enumValueToString(*i), &numPoints, list);
2106 biasHistory->pointState.resize(numPoints);
2110 case StateAwhEntry::CoordPoint:
2111 for (auto& psh : biasHistory->pointState)
2113 do_cpt_double_err(xd, enumValueToString(*i), &psh.target, list);
2114 do_cpt_double_err(xd, enumValueToString(*i), &psh.free_energy, list);
2115 do_cpt_double_err(xd, enumValueToString(*i), &psh.bias, list);
2116 do_cpt_double_err(xd, enumValueToString(*i), &psh.weightsum_iteration, list);
2117 do_cpt_double_err(xd, enumValueToString(*i), &psh.weightsum_covering, list);
2118 do_cpt_double_err(xd, enumValueToString(*i), &psh.weightsum_tot, list);
2119 do_cpt_double_err(xd, enumValueToString(*i), &psh.weightsum_ref, list);
2120 do_cpt_step_err(xd, enumValueToString(*i), &psh.last_update_index, list);
2121 do_cpt_double_err(xd, enumValueToString(*i), &psh.log_pmfsum, list);
2122 do_cpt_double_err(xd, enumValueToString(*i), &psh.visits_iteration, list);
2123 do_cpt_double_err(xd, enumValueToString(*i), &psh.visits_tot, list);
2126 case StateAwhEntry::UmbrellaGridPoint:
2127 do_cpt_int_err(xd, enumValueToString(*i), &(state->umbrellaGridpoint), list);
2129 case StateAwhEntry::UpdateList:
2130 do_cpt_int_err(xd, enumValueToString(*i), &(state->origin_index_updatelist), list);
2131 do_cpt_int_err(xd, enumValueToString(*i), &(state->end_index_updatelist), list);
2133 case StateAwhEntry::LogScaledSampleWeight:
2134 do_cpt_double_err(xd, enumValueToString(*i), &(state->logScaledSampleWeight), list);
2135 do_cpt_double_err(xd, enumValueToString(*i), &(state->maxLogScaledSampleWeight), list);
2137 case StateAwhEntry::NumUpdates:
2138 do_cpt_step_err(xd, enumValueToString(*i), &(state->numUpdates), list);
2140 case StateAwhEntry::ForceCorrelationGrid:
2141 ret = do_cpt_correlation_grid(
2142 xd, bRead, fflags, &biasHistory->forceCorrelationGrid, list, *i);
2144 default: gmx_fatal(FARGS, "Unknown awh history entry %d\n", enumValueToBitMask(*i));
2152 static int do_cpt_awh(XDR* xd, gmx_bool bRead, int fflags, gmx::AwhHistory* awhHistory, FILE* list)
2158 std::shared_ptr<gmx::AwhHistory> awhHistoryLocal;
2160 if (awhHistory == nullptr)
2162 GMX_RELEASE_ASSERT(bRead,
2163 "do_cpt_awh should not be called for writing without an AwhHistory");
2165 awhHistoryLocal = std::make_shared<gmx::AwhHistory>();
2166 awhHistory = awhHistoryLocal.get();
2169 /* To be able to read and write the AWH data several parameters determining the layout of the AWH structs need to be known
2170 (nbias, npoints, etc.). The best thing (?) would be to have these passed to this function. When writing to a checkpoint
2171 these parameters are available in awh_history (after calling init_awh_history). When reading from a checkpoint though, there
2172 is no initialized awh_history (it is initialized and set in this function). The AWH parameters have not always been read
2173 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
2174 when writing a checkpoint, also storing parameters needed for future reading of the checkpoint.
2176 Another issue is that some variables that AWH checkpoints don't have a registered enum and string (e.g. nbias below).
2177 One difficulty is the multilevel structure of the data which would need to be represented somehow. */
2182 numBias = awhHistory->bias.size();
2184 do_cpt_int_err(xd, "awh_nbias", &numBias, list);
2188 awhHistory->bias.resize(numBias);
2190 for (auto& bias : awhHistory->bias)
2192 ret = do_cpt_awh_bias(xd, bRead, fflags, &bias, list);
2198 do_cpt_double_err(xd, "awh_potential_offset", &awhHistory->potentialOffset, list);
2203 static void do_cpt_mdmodules(int fileVersion,
2204 t_fileio* checkpointFileHandle,
2205 const gmx::MdModulesNotifier& mdModulesNotifier,
2208 if (fileVersion >= cptv_MdModules)
2210 gmx::FileIOXdrSerializer serializer(checkpointFileHandle);
2211 gmx::KeyValueTreeObject mdModuleCheckpointParameterTree =
2212 gmx::deserializeKeyValueTree(&serializer);
2215 gmx::TextWriter textWriter(outputFile);
2216 gmx::dumpKeyValueTree(&textWriter, mdModuleCheckpointParameterTree);
2218 gmx::MdModulesCheckpointReadingDataOnMaster mdModuleCheckpointReadingDataOnMaster = {
2219 mdModuleCheckpointParameterTree, fileVersion
2221 mdModulesNotifier.checkpointingNotifications_.notify(mdModuleCheckpointReadingDataOnMaster);
2225 static int do_cpt_files(XDR* xd, gmx_bool bRead, std::vector<gmx_file_position_t>* outputfiles, FILE* list, int file_version)
2228 gmx_off_t mask = 0xFFFFFFFFL;
2229 int offset_high, offset_low;
2230 std::array<char, CPTSTRLEN> buf;
2231 GMX_RELEASE_ASSERT(outputfiles, "Must have valid outputfiles");
2233 // Ensure that reading pre-allocates outputfiles, while writing
2234 // writes what is already there.
2235 int nfiles = outputfiles->size();
2236 if (do_cpt_int(xd, "number of output files", &nfiles, list) != 0)
2242 outputfiles->resize(nfiles);
2245 for (auto& outputfile : *outputfiles)
2247 /* 64-bit XDR numbers are not portable, so it is stored as separate high/low fractions */
2250 do_cpt_string_err(xd, "output filename", buf, list);
2251 std::copy(std::begin(buf), std::end(buf), std::begin(outputfile.filename));
2253 if (do_cpt_int(xd, "file_offset_high", &offset_high, list) != 0)
2257 if (do_cpt_int(xd, "file_offset_low", &offset_low, list) != 0)
2261 outputfile.offset = (static_cast<gmx_off_t>(offset_high) << 32)
2262 | (static_cast<gmx_off_t>(offset_low) & mask);
2266 do_cpt_string_err(xd, "output filename", outputfile.filename, list);
2268 offset = outputfile.offset;
2276 offset_low = static_cast<int>(offset & mask);
2277 offset_high = static_cast<int>((offset >> 32) & mask);
2279 if (do_cpt_int(xd, "file_offset_high", &offset_high, list) != 0)
2283 if (do_cpt_int(xd, "file_offset_low", &offset_low, list) != 0)
2288 if (file_version >= 8)
2290 if (do_cpt_int(xd, "file_checksum_size", &outputfile.checksumSize, list) != 0)
2294 if (do_cpt_u_chars(xd, "file_checksum", outputfile.checksum.size(), outputfile.checksum.data(), list)
2302 outputfile.checksumSize = -1;
2308 void write_checkpoint_data(t_fileio* fp,
2309 CheckpointHeaderContents headerContents,
2311 LambdaWeightCalculation elamstats,
2313 ObservablesHistory* observablesHistory,
2314 const gmx::MdModulesNotifier& mdModulesNotifier,
2315 std::vector<gmx_file_position_t>* outputfiles,
2316 gmx::WriteCheckpointDataHolder* modularSimulatorCheckpointData)
2318 headerContents.flags_eks = 0;
2319 if (state->ekinstate.bUpToDate)
2321 headerContents.flags_eks = (enumValueToBitMask(StateKineticEntry::EkinNumber)
2322 | enumValueToBitMask(StateKineticEntry::EkinHalfStep)
2323 | enumValueToBitMask(StateKineticEntry::EkinFullStep)
2324 | enumValueToBitMask(StateKineticEntry::EkinHalfStepOld)
2325 | enumValueToBitMask(StateKineticEntry::EkinNoseHooverScaleFullStep)
2326 | enumValueToBitMask(StateKineticEntry::EkinNoseHooverScaleHalfStep)
2327 | enumValueToBitMask(StateKineticEntry::VelocityScale)
2328 | enumValueToBitMask(StateKineticEntry::DEkinDLambda)
2329 | enumValueToBitMask(StateKineticEntry::Mvcos));
2331 headerContents.isModularSimulatorCheckpoint = !modularSimulatorCheckpointData->empty();
2333 energyhistory_t* enerhist = observablesHistory->energyHistory.get();
2334 headerContents.flags_enh = 0;
2335 if (enerhist != nullptr && (enerhist->nsum > 0 || enerhist->nsum_sim > 0))
2337 headerContents.flags_enh |= enumValueToBitMask(StateEnergyEntry::N)
2338 | enumValueToBitMask(StateEnergyEntry::NumSteps)
2339 | enumValueToBitMask(StateEnergyEntry::NumStepsSim);
2340 if (enerhist->nsum > 0)
2342 headerContents.flags_enh |= (enumValueToBitMask(StateEnergyEntry::Aver)
2343 | enumValueToBitMask(StateEnergyEntry::Sum)
2344 | enumValueToBitMask(StateEnergyEntry::NumSum));
2346 if (enerhist->nsum_sim > 0)
2348 headerContents.flags_enh |= (enumValueToBitMask(StateEnergyEntry::SumSim)
2349 | enumValueToBitMask(StateEnergyEntry::NumSumSim));
2351 if (enerhist->deltaHForeignLambdas != nullptr)
2353 headerContents.flags_enh |= (enumValueToBitMask(StateEnergyEntry::DeltaHNN)
2354 | enumValueToBitMask(StateEnergyEntry::DeltaHList)
2355 | enumValueToBitMask(StateEnergyEntry::DeltaHStartTime)
2356 | enumValueToBitMask(StateEnergyEntry::DeltaHStartLambda));
2360 PullHistory* pullHist = observablesHistory->pullHistory.get();
2361 headerContents.flagsPullHistory = 0;
2362 if (pullHist != nullptr && (pullHist->numValuesInXSum > 0 || pullHist->numValuesInFSum > 0))
2364 headerContents.flagsPullHistory |= enumValueToBitMask(StatePullEntry::NumCoordinates);
2365 headerContents.flagsPullHistory |= (enumValueToBitMask(StatePullEntry::NumGroups)
2366 | enumValueToBitMask(StatePullEntry::NumValuesInXSum)
2367 | enumValueToBitMask(StatePullEntry::NumValuesInFSum));
2370 headerContents.flags_dfh = 0;
2373 headerContents.flags_dfh =
2374 (enumValueToBitMask(StateFepEntry::IsEquilibrated)
2375 | enumValueToBitMask(StateFepEntry::NumAtLambda)
2376 | enumValueToBitMask(StateFepEntry::SumWeights) | enumValueToBitMask(StateFepEntry::SumDG)
2377 | enumValueToBitMask(StateFepEntry::Tij) | enumValueToBitMask(StateFepEntry::TijEmp));
2380 headerContents.flags_dfh |= (enumValueToBitMask(StateFepEntry::WangLandauDelta)
2381 | enumValueToBitMask(StateFepEntry::WangLandauHistogram));
2383 if ((elamstats == LambdaWeightCalculation::Minvar) || (elamstats == LambdaWeightCalculation::Barker)
2384 || (elamstats == LambdaWeightCalculation::Metropolis))
2386 headerContents.flags_dfh |= (enumValueToBitMask(StateFepEntry::Accump)
2387 | enumValueToBitMask(StateFepEntry::Accumm)
2388 | enumValueToBitMask(StateFepEntry::Accump2)
2389 | enumValueToBitMask(StateFepEntry::Accumm2)
2390 | enumValueToBitMask(StateFepEntry::SumMinVar)
2391 | enumValueToBitMask(StateFepEntry::SumVar));
2395 headerContents.flags_awhh = 0;
2396 if (state->awhHistory != nullptr && !state->awhHistory->bias.empty())
2398 headerContents.flags_awhh |= (enumValueToBitMask(StateAwhEntry::InInitial)
2399 | enumValueToBitMask(StateAwhEntry::EquilibrateHistogram)
2400 | enumValueToBitMask(StateAwhEntry::HistogramSize)
2401 | enumValueToBitMask(StateAwhEntry::NumPoints)
2402 | enumValueToBitMask(StateAwhEntry::CoordPoint)
2403 | enumValueToBitMask(StateAwhEntry::UmbrellaGridPoint)
2404 | enumValueToBitMask(StateAwhEntry::UpdateList)
2405 | enumValueToBitMask(StateAwhEntry::LogScaledSampleWeight)
2406 | enumValueToBitMask(StateAwhEntry::NumUpdates)
2407 | enumValueToBitMask(StateAwhEntry::ForceCorrelationGrid));
2410 do_cpt_header(gmx_fio_getxdr(fp), FALSE, nullptr, &headerContents);
2412 if ((do_cpt_state(gmx_fio_getxdr(fp), state->flags, state, nullptr) < 0)
2413 || (do_cpt_ekinstate(gmx_fio_getxdr(fp), headerContents.flags_eks, &state->ekinstate, nullptr) < 0)
2414 || (do_cpt_enerhist(gmx_fio_getxdr(fp), FALSE, headerContents.flags_enh, enerhist, nullptr) < 0)
2415 || (doCptPullHist(gmx_fio_getxdr(fp), FALSE, headerContents.flagsPullHistory, pullHist, nullptr) < 0)
2416 || (do_cpt_df_hist(gmx_fio_getxdr(fp), headerContents.flags_dfh, headerContents.nlambda, &state->dfhist, nullptr)
2419 gmx_fio_getxdr(fp), FALSE, headerContents.nED, observablesHistory->edsamHistory.get(), nullptr)
2421 || (do_cpt_awh(gmx_fio_getxdr(fp), FALSE, headerContents.flags_awhh, state->awhHistory.get(), nullptr) < 0)
2422 || (do_cpt_swapstate(gmx_fio_getxdr(fp),
2424 headerContents.eSwapCoords,
2425 observablesHistory->swapHistory.get(),
2428 || (do_cpt_files(gmx_fio_getxdr(fp), FALSE, outputfiles, nullptr, headerContents.file_version) < 0))
2430 gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
2433 // Checkpointing MdModules
2435 gmx::KeyValueTreeBuilder builder;
2436 gmx::MdModulesWriteCheckpointData mdModulesWriteCheckpoint = { builder.rootObject(),
2437 headerContents.file_version };
2438 mdModulesNotifier.checkpointingNotifications_.notify(mdModulesWriteCheckpoint);
2439 auto tree = builder.build();
2440 gmx::FileIOXdrSerializer serializer(fp);
2441 gmx::serializeKeyValueTree(tree, &serializer);
2444 // Checkpointing modular simulator
2446 gmx::FileIOXdrSerializer serializer(fp);
2447 modularSimulatorCheckpointData->serialize(&serializer);
2450 do_cpt_footer(gmx_fio_getxdr(fp), headerContents.file_version);
2452 /* Always FAH checkpoint immediately after a Gromacs checkpoint.
2454 * Note that it is critical that we save a FAH checkpoint directly
2455 * after writing a Gromacs checkpoint. If the program dies, either
2456 * by the machine powering off suddenly or the process being,
2457 * killed, FAH can recover files that have only appended data by
2458 * truncating them to the last recorded length. The Gromacs
2459 * checkpoint does not just append data, it is fully rewritten each
2460 * time so a crash between moving the new Gromacs checkpoint file in
2461 * to place and writing a FAH checkpoint is not recoverable. Thus
2462 * the time between these operations must be kept as short a
2469 static void check_int(FILE* fplog, const char* type, int p, int f, gmx_bool* mm)
2471 bool foundMismatch = (p != f);
2479 fprintf(fplog, " %s mismatch,\n", type);
2480 fprintf(fplog, " current program: %d\n", p);
2481 fprintf(fplog, " checkpoint file: %d\n", f);
2482 fprintf(fplog, "\n");
2486 static void check_string(FILE* fplog, const char* type, const char* p, const char* f, gmx_bool* mm)
2488 bool foundMismatch = (std::strcmp(p, f) != 0);
2496 fprintf(fplog, " %s mismatch,\n", type);
2497 fprintf(fplog, " current program: %s\n", p);
2498 fprintf(fplog, " checkpoint file: %s\n", f);
2499 fprintf(fplog, "\n");
2503 static void check_match(FILE* fplog,
2504 const t_commrec* cr,
2506 const CheckpointHeaderContents& headerContents,
2507 gmx_bool reproducibilityRequested)
2509 /* Note that this check_string on the version will also print a message
2510 * when only the minor version differs. But we only print a warning
2511 * message further down with reproducibilityRequested=TRUE.
2513 gmx_bool versionDiffers = FALSE;
2514 check_string(fplog, "Version", gmx_version(), headerContents.version, &versionDiffers);
2516 gmx_bool precisionDiffers = FALSE;
2517 check_int(fplog, "Double prec.", GMX_DOUBLE, headerContents.double_prec, &precisionDiffers);
2518 if (precisionDiffers)
2520 const char msg_precision_difference[] =
2521 "You are continuing a simulation with a different precision. Not matching\n"
2522 "mixed/double precision will lead to precision or performance loss.\n";
2525 fprintf(fplog, "%s\n", msg_precision_difference);
2529 gmx_bool mm = (versionDiffers || precisionDiffers);
2531 if (reproducibilityRequested)
2534 fplog, "Program name", gmx::getProgramContext().fullBinaryPath(), headerContents.fprog, &mm);
2536 check_int(fplog, "#ranks", cr->nnodes, headerContents.nnodes, &mm);
2539 if (cr->sizeOfDefaultCommunicator > 1 && reproducibilityRequested)
2541 // TODO: These checks are incorrect (see redmine #3309)
2542 check_int(fplog, "#PME-ranks", cr->npmenodes, headerContents.npme, &mm);
2544 int npp = cr->sizeOfDefaultCommunicator;
2545 if (cr->npmenodes >= 0)
2547 npp -= cr->npmenodes;
2549 int npp_f = headerContents.nnodes;
2550 if (headerContents.npme >= 0)
2552 npp_f -= headerContents.npme;
2556 check_int(fplog, "#DD-cells[x]", dd_nc[XX], headerContents.dd_nc[XX], &mm);
2557 check_int(fplog, "#DD-cells[y]", dd_nc[YY], headerContents.dd_nc[YY], &mm);
2558 check_int(fplog, "#DD-cells[z]", dd_nc[ZZ], headerContents.dd_nc[ZZ], &mm);
2564 /* Gromacs should be able to continue from checkpoints between
2565 * different patch level versions, but we do not guarantee
2566 * compatibility between different major/minor versions - check this.
2570 sscanf(gmx_version(), "%5d", &gmx_major);
2571 int ret = sscanf(headerContents.version, "%5d", &cpt_major);
2572 gmx_bool majorVersionDiffers = (ret < 1 || gmx_major != cpt_major);
2574 const char msg_major_version_difference[] =
2575 "The current GROMACS major version is not identical to the one that\n"
2576 "generated the checkpoint file. In principle GROMACS does not support\n"
2577 "continuation from checkpoints between different versions, so we advise\n"
2578 "against this. If you still want to try your luck we recommend that you use\n"
2579 "the -noappend flag to keep your output files from the two versions separate.\n"
2580 "This might also work around errors where the output fields in the energy\n"
2581 "file have changed between the different versions.\n";
2583 const char msg_mismatch_notice[] =
2584 "GROMACS patchlevel, binary or parallel settings differ from previous run.\n"
2585 "Continuation is exact, but not guaranteed to be binary identical.\n";
2587 if (majorVersionDiffers)
2591 fprintf(fplog, "%s\n", msg_major_version_difference);
2594 else if (reproducibilityRequested)
2596 /* Major & minor versions match at least, but something is different. */
2599 fprintf(fplog, "%s\n", msg_mismatch_notice);
2605 static void read_checkpoint(const char* fn,
2607 const t_commrec* cr,
2609 IntegrationAlgorithm eIntegrator,
2610 int* init_fep_state,
2611 CheckpointHeaderContents* headerContents,
2613 ObservablesHistory* observablesHistory,
2614 gmx_bool reproducibilityRequested,
2615 const gmx::MdModulesNotifier& mdModulesNotifier,
2616 gmx::ReadCheckpointDataHolder* modularSimulatorCheckpointData,
2617 bool useModularSimulator)
2620 char buf[STEPSTRSIZE];
2623 fp = gmx_fio_open(fn, "r");
2624 do_cpt_header(gmx_fio_getxdr(fp), TRUE, nullptr, headerContents);
2626 // If we are appending, then we don't want write to the open log
2627 // file because we still need to compute a checksum for it. In
2628 // that case, the filehandle will be nullptr. Otherwise, we report
2629 // to the new log file about the checkpoint file that we are
2631 FILE* fplog = gmx_fio_getfp(logfio);
2634 fprintf(fplog, "\n");
2635 fprintf(fplog, "Reading checkpoint file %s\n", fn);
2636 fprintf(fplog, " file generated by: %s\n", headerContents->fprog);
2637 fprintf(fplog, " file generated at: %s\n", headerContents->ftime);
2638 fprintf(fplog, " GROMACS double prec.: %d\n", headerContents->double_prec);
2639 fprintf(fplog, " simulation part #: %d\n", headerContents->simulation_part);
2640 fprintf(fplog, " step: %s\n", gmx_step_str(headerContents->step, buf));
2641 fprintf(fplog, " time: %f\n", headerContents->t);
2642 fprintf(fplog, "\n");
2645 if (headerContents->natoms != state->natoms)
2648 "Checkpoint file is for a system of %d atoms, while the current system consists "
2650 headerContents->natoms,
2653 if (headerContents->ngtc != state->ngtc)
2656 "Checkpoint file is for a system of %d T-coupling groups, while the current "
2657 "system consists of %d T-coupling groups",
2658 headerContents->ngtc,
2661 if (headerContents->nnhpres != state->nnhpres)
2664 "Checkpoint file is for a system of %d NH-pressure-coupling variables, while the "
2665 "current system consists of %d NH-pressure-coupling variables",
2666 headerContents->nnhpres,
2670 int nlambdaHistory = (state->dfhist ? state->dfhist->nlambda : 0);
2671 if (headerContents->nlambda != nlambdaHistory)
2674 "Checkpoint file is for a system with %d lambda states, while the current system "
2675 "consists of %d lambda states",
2676 headerContents->nlambda,
2680 init_gtc_state(state,
2683 headerContents->nhchainlength); /* need to keep this here to keep the tpr format working */
2684 /* write over whatever was read; we use the number of Nose-Hoover chains from the checkpoint */
2686 if (headerContents->eIntegrator != eIntegrator)
2689 "Cannot change integrator during a checkpoint restart. Perhaps you should make a "
2690 "new .tpr with grompp -f new.mdp -t %s",
2694 // For modular simulator, no state object is populated, so we cannot do this check here!
2695 if (headerContents->flags_state != state->flags && !useModularSimulator)
2698 "Cannot change a simulation algorithm during a checkpoint restart. Perhaps you "
2699 "should make a new .tpr with grompp -f new.mdp -t %s",
2703 GMX_RELEASE_ASSERT(!(headerContents->isModularSimulatorCheckpoint && !useModularSimulator),
2704 "Checkpoint file was written by modular simulator, but the current "
2705 "simulation uses the legacy simulator.\n\n"
2706 "Try the following steps:\n"
2707 "1. Make sure the GMX_DISABLE_MODULAR_SIMULATOR environment variable is not "
2708 "set to return to the default behavior. Retry running the simulation.\n"
2709 "2. If the problem persists, set the environment variable "
2710 "GMX_USE_MODULAR_SIMULATOR=ON to overwrite the default behavior and use "
2711 "modular simulator for all implemented use cases.");
2712 GMX_RELEASE_ASSERT(!(!headerContents->isModularSimulatorCheckpoint && useModularSimulator),
2713 "Checkpoint file was written by legacy simulator, but the current "
2714 "simulation uses the modular simulator.\n\n"
2715 "Try the following steps:\n"
2716 "1. Make sure the GMX_USE_MODULAR_SIMULATOR environment variable is not set "
2717 "to return to the default behavior. Retry running the simulation.\n"
2718 "2. If the problem persists, set the environment variable "
2719 "GMX_DISABLE_MODULAR_SIMULATOR=ON to overwrite the default behavior and use "
2720 "legacy simulator for all implemented use cases.");
2724 check_match(fplog, cr, dd_nc, *headerContents, reproducibilityRequested);
2727 ret = do_cpt_state(gmx_fio_getxdr(fp), headerContents->flags_state, state, nullptr);
2728 *init_fep_state = state->fep_state; /* there should be a better way to do this than setting it
2729 here. Investigate for 5.0. */
2734 ret = do_cpt_ekinstate(gmx_fio_getxdr(fp), headerContents->flags_eks, &state->ekinstate, nullptr);
2739 state->ekinstate.hasReadEkinState =
2740 (((headerContents->flags_eks & enumValueToBitMask(StateKineticEntry::EkinHalfStep)) != 0)
2741 || ((headerContents->flags_eks & enumValueToBitMask(StateKineticEntry::EkinFullStep)) != 0)
2742 || ((headerContents->flags_eks & enumValueToBitMask(StateKineticEntry::EkinHalfStepOld)) != 0)
2743 || (((headerContents->flags_eks & enumValueToBitMask(StateKineticEntry::EkinNoseHooverScaleFullStep))
2744 | (headerContents->flags_eks & enumValueToBitMask(StateKineticEntry::EkinNoseHooverScaleHalfStep))
2745 | (headerContents->flags_eks & enumValueToBitMask(StateKineticEntry::VelocityScale)))
2748 if (headerContents->flags_enh && observablesHistory->energyHistory == nullptr)
2750 observablesHistory->energyHistory = std::make_unique<energyhistory_t>();
2752 ret = do_cpt_enerhist(
2753 gmx_fio_getxdr(fp), TRUE, headerContents->flags_enh, observablesHistory->energyHistory.get(), nullptr);
2759 if (headerContents->flagsPullHistory)
2761 if (observablesHistory->pullHistory == nullptr)
2763 observablesHistory->pullHistory = std::make_unique<PullHistory>();
2765 ret = doCptPullHist(gmx_fio_getxdr(fp),
2767 headerContents->flagsPullHistory,
2768 observablesHistory->pullHistory.get(),
2776 if (headerContents->file_version < 6)
2779 "Continuing from checkpoint files written before GROMACS 4.5 is not supported");
2782 ret = do_cpt_df_hist(
2783 gmx_fio_getxdr(fp), headerContents->flags_dfh, headerContents->nlambda, &state->dfhist, nullptr);
2789 if (headerContents->nED > 0 && observablesHistory->edsamHistory == nullptr)
2791 observablesHistory->edsamHistory = std::make_unique<edsamhistory_t>(edsamhistory_t{});
2793 ret = do_cpt_EDstate(
2794 gmx_fio_getxdr(fp), TRUE, headerContents->nED, observablesHistory->edsamHistory.get(), nullptr);
2800 if (headerContents->flags_awhh != 0 && state->awhHistory == nullptr)
2802 state->awhHistory = std::make_shared<gmx::AwhHistory>();
2804 ret = do_cpt_awh(gmx_fio_getxdr(fp), TRUE, headerContents->flags_awhh, state->awhHistory.get(), nullptr);
2810 if (headerContents->eSwapCoords != SwapType::No && observablesHistory->swapHistory == nullptr)
2812 observablesHistory->swapHistory = std::make_unique<swaphistory_t>(swaphistory_t{});
2814 ret = do_cpt_swapstate(
2815 gmx_fio_getxdr(fp), TRUE, headerContents->eSwapCoords, observablesHistory->swapHistory.get(), nullptr);
2821 std::vector<gmx_file_position_t> outputfiles;
2822 ret = do_cpt_files(gmx_fio_getxdr(fp), TRUE, &outputfiles, nullptr, headerContents->file_version);
2827 do_cpt_mdmodules(headerContents->file_version, fp, mdModulesNotifier, nullptr);
2828 if (headerContents->file_version >= cptv_ModularSimulator)
2830 gmx::FileIOXdrSerializer serializer(fp);
2831 modularSimulatorCheckpointData->deserialize(&serializer);
2833 ret = do_cpt_footer(gmx_fio_getxdr(fp), headerContents->file_version);
2838 if (gmx_fio_close(fp) != 0)
2840 gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
2845 void load_checkpoint(const char* fn,
2847 const t_commrec* cr,
2851 ObservablesHistory* observablesHistory,
2852 gmx_bool reproducibilityRequested,
2853 const gmx::MdModulesNotifier& mdModulesNotifier,
2854 gmx::ReadCheckpointDataHolder* modularSimulatorCheckpointData,
2855 bool useModularSimulator)
2857 CheckpointHeaderContents headerContents;
2860 /* Read the state from the checkpoint file */
2866 &(ir->fepvals->init_fep_state),
2870 reproducibilityRequested,
2872 modularSimulatorCheckpointData,
2873 useModularSimulator);
2877 gmx_bcast(sizeof(headerContents.step), &headerContents.step, cr->mpiDefaultCommunicator);
2878 gmx::MdModulesCheckpointReadingBroadcast broadcastCheckPointData = {
2879 cr->mpiDefaultCommunicator, PAR(cr), headerContents.file_version
2881 mdModulesNotifier.checkpointingNotifications_.notify(broadcastCheckPointData);
2883 ir->bContinuation = TRUE;
2884 if (ir->nsteps >= 0)
2886 // TODO Should the following condition be <=? Currently if you
2887 // pass a checkpoint written by an normal completion to a restart,
2888 // mdrun will read all input, does some work but no steps, and
2889 // write successful output. But perhaps that is not desirable.
2890 // Note that we do not intend to support the use of mdrun
2891 // -nsteps to circumvent this condition.
2892 if (ir->nsteps + ir->init_step < headerContents.step)
2894 char buf[STEPSTRSIZE];
2895 std::string message =
2896 gmx::formatString("The input requested %s steps, ", gmx_step_str(ir->nsteps, buf));
2897 if (ir->init_step > 0)
2899 message += gmx::formatString("starting from step %s, ", gmx_step_str(ir->init_step, buf));
2901 message += gmx::formatString(
2902 "however the checkpoint "
2903 "file has already reached step %s. The simulation will not "
2904 "proceed, because either your simulation is already complete, "
2905 "or your combination of input files don't match.",
2906 gmx_step_str(headerContents.step, buf));
2907 gmx_fatal(FARGS, "%s", message.c_str());
2909 ir->nsteps += ir->init_step - headerContents.step;
2911 ir->init_step = headerContents.step;
2912 ir->simulation_part = headerContents.simulation_part + 1;
2915 void read_checkpoint_part_and_step(const char* filename, int* simulation_part, int64_t* step)
2919 if (filename == nullptr || !gmx_fexist(filename) || ((fp = gmx_fio_open(filename, "r")) == nullptr))
2921 *simulation_part = 0;
2926 CheckpointHeaderContents headerContents;
2927 do_cpt_header(gmx_fio_getxdr(fp), TRUE, nullptr, &headerContents);
2929 *simulation_part = headerContents.simulation_part;
2930 *step = headerContents.step;
2933 static CheckpointHeaderContents read_checkpoint_data(t_fileio* fp,
2935 std::vector<gmx_file_position_t>* outputfiles,
2936 gmx::ReadCheckpointDataHolder* modularSimulatorCheckpointData)
2938 CheckpointHeaderContents headerContents;
2939 do_cpt_header(gmx_fio_getxdr(fp), TRUE, nullptr, &headerContents);
2940 state->natoms = headerContents.natoms;
2941 state->ngtc = headerContents.ngtc;
2942 state->nnhpres = headerContents.nnhpres;
2943 state->nhchainlength = headerContents.nhchainlength;
2944 state->flags = headerContents.flags_state;
2945 int ret = do_cpt_state(gmx_fio_getxdr(fp), state->flags, state, nullptr);
2950 ret = do_cpt_ekinstate(gmx_fio_getxdr(fp), headerContents.flags_eks, &state->ekinstate, nullptr);
2956 energyhistory_t enerhist;
2957 ret = do_cpt_enerhist(gmx_fio_getxdr(fp), TRUE, headerContents.flags_enh, &enerhist, nullptr);
2962 PullHistory pullHist = {};
2963 ret = doCptPullHist(gmx_fio_getxdr(fp), TRUE, headerContents.flagsPullHistory, &pullHist, nullptr);
2969 ret = do_cpt_df_hist(
2970 gmx_fio_getxdr(fp), headerContents.flags_dfh, headerContents.nlambda, &state->dfhist, nullptr);
2976 edsamhistory_t edsamhist = {};
2977 ret = do_cpt_EDstate(gmx_fio_getxdr(fp), TRUE, headerContents.nED, &edsamhist, nullptr);
2983 ret = do_cpt_awh(gmx_fio_getxdr(fp), TRUE, headerContents.flags_awhh, state->awhHistory.get(), nullptr);
2989 swaphistory_t swaphist = {};
2990 ret = do_cpt_swapstate(gmx_fio_getxdr(fp), TRUE, headerContents.eSwapCoords, &swaphist, nullptr);
2996 ret = do_cpt_files(gmx_fio_getxdr(fp), TRUE, outputfiles, nullptr, headerContents.file_version);
3002 gmx::MdModulesNotifier mdModuleNotifier;
3003 do_cpt_mdmodules(headerContents.file_version, fp, mdModuleNotifier, nullptr);
3004 if (headerContents.file_version >= cptv_ModularSimulator)
3006 // Store modular checkpoint data into modularSimulatorCheckpointData
3007 gmx::FileIOXdrSerializer serializer(fp);
3008 modularSimulatorCheckpointData->deserialize(&serializer);
3010 ret = do_cpt_footer(gmx_fio_getxdr(fp), headerContents.file_version);
3015 return headerContents;
3018 void read_checkpoint_trxframe(t_fileio* fp, t_trxframe* fr)
3021 std::vector<gmx_file_position_t> outputfiles;
3022 gmx::ReadCheckpointDataHolder modularSimulatorCheckpointData;
3023 CheckpointHeaderContents headerContents =
3024 read_checkpoint_data(fp, &state, &outputfiles, &modularSimulatorCheckpointData);
3025 if (headerContents.isModularSimulatorCheckpoint)
3027 gmx::ModularSimulator::readCheckpointToTrxFrame(fr, &modularSimulatorCheckpointData, headerContents);
3031 fr->natoms = state.natoms;
3033 fr->step = int64_to_int(headerContents.step, "conversion of checkpoint to trajectory");
3035 fr->time = headerContents.t;
3037 fr->lambda = state.lambda[FreeEnergyPerturbationCouplingType::Fep];
3038 fr->fep_state = state.fep_state;
3040 fr->bX = ((state.flags & enumValueToBitMask(StateEntry::X)) != 0);
3043 fr->x = makeRvecArray(state.x, state.natoms);
3045 fr->bV = ((state.flags & enumValueToBitMask(StateEntry::V)) != 0);
3048 fr->v = makeRvecArray(state.v, state.natoms);
3051 fr->bBox = ((state.flags & enumValueToBitMask(StateEntry::Box)) != 0);
3054 copy_mat(state.box, fr->box);
3058 void list_checkpoint(const char* fn, FILE* out)
3065 fp = gmx_fio_open(fn, "r");
3066 CheckpointHeaderContents headerContents;
3067 do_cpt_header(gmx_fio_getxdr(fp), TRUE, out, &headerContents);
3068 state.natoms = headerContents.natoms;
3069 state.ngtc = headerContents.ngtc;
3070 state.nnhpres = headerContents.nnhpres;
3071 state.nhchainlength = headerContents.nhchainlength;
3072 state.flags = headerContents.flags_state;
3073 ret = do_cpt_state(gmx_fio_getxdr(fp), state.flags, &state, out);
3078 ret = do_cpt_ekinstate(gmx_fio_getxdr(fp), headerContents.flags_eks, &state.ekinstate, out);
3084 energyhistory_t enerhist;
3085 ret = do_cpt_enerhist(gmx_fio_getxdr(fp), TRUE, headerContents.flags_enh, &enerhist, out);
3089 PullHistory pullHist = {};
3090 ret = doCptPullHist(gmx_fio_getxdr(fp), TRUE, headerContents.flagsPullHistory, &pullHist, out);
3095 ret = do_cpt_df_hist(
3096 gmx_fio_getxdr(fp), headerContents.flags_dfh, headerContents.nlambda, &state.dfhist, out);
3101 edsamhistory_t edsamhist = {};
3102 ret = do_cpt_EDstate(gmx_fio_getxdr(fp), TRUE, headerContents.nED, &edsamhist, out);
3107 ret = do_cpt_awh(gmx_fio_getxdr(fp), TRUE, headerContents.flags_awhh, state.awhHistory.get(), out);
3112 swaphistory_t swaphist = {};
3113 ret = do_cpt_swapstate(gmx_fio_getxdr(fp), TRUE, headerContents.eSwapCoords, &swaphist, out);
3118 std::vector<gmx_file_position_t> outputfiles;
3119 ret = do_cpt_files(gmx_fio_getxdr(fp), TRUE, &outputfiles, out, headerContents.file_version);
3121 gmx::MdModulesNotifier mdModuleNotifier;
3122 do_cpt_mdmodules(headerContents.file_version, fp, mdModuleNotifier, out);
3123 if (headerContents.file_version >= cptv_ModularSimulator)
3125 gmx::FileIOXdrSerializer serializer(fp);
3126 gmx::ReadCheckpointDataHolder modularSimulatorCheckpointData;
3127 modularSimulatorCheckpointData.deserialize(&serializer);
3128 modularSimulatorCheckpointData.dump(out);
3133 ret = do_cpt_footer(gmx_fio_getxdr(fp), headerContents.file_version);
3140 if (gmx_fio_close(fp) != 0)
3142 gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
3146 /* This routine cannot print tons of data, since it is called before the log file is opened. */
3147 CheckpointHeaderContents read_checkpoint_simulation_part_and_filenames(t_fileio* fp,
3148 std::vector<gmx_file_position_t>* outputfiles)
3151 gmx::ReadCheckpointDataHolder modularSimulatorCheckpointData;
3152 CheckpointHeaderContents headerContents =
3153 read_checkpoint_data(fp, &state, outputfiles, &modularSimulatorCheckpointData);
3154 if (gmx_fio_close(fp) != 0)
3156 gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
3158 return headerContents;