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/mdmodulesnotifiers.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 Version number of the file format written to checkpoint
147 * files by this version of the code.
149 * cpt_version should normally only be changed, via adding a new field
150 * to cptv enumeration, when the header or footer format changes.
152 * The state data format itself is backward and forward compatible.
153 * But old code can not read a new entry that is present in the file
154 * (but can read a new format when new entries are not present).
156 * The cpt_version increases whenever the file format in the main
157 * development branch changes, due to an extension of the CheckPointVersion
158 * enum (see src/gromacs/fileio/checkpoint.h).
159 * Backward compatibility for reading old run input files is maintained
160 * by checking this version number against that of the file and then using
161 * the correct code path. */
162 static constexpr CheckPointVersion cpt_version = CheckPointVersion::CurrentVersion;
164 const char* enumValueToString(StateEntry enumValue)
166 static constexpr gmx::EnumerationArray<StateEntry, const char*> stateEntryNames = {
173 "thermostat-integral",
178 "LD-rng-unsupported",
179 "LD-rng-i-unsupported",
192 "MC-rng-unsupported",
193 "MC-rng-i-unsupported",
196 return stateEntryNames[enumValue];
199 enum class StateKineticEntry : int
207 EkinNoseHooverScaleFullStep,
208 EkinNoseHooverScaleHalfStep,
214 static const char* enumValueToString(StateKineticEntry enumValue)
216 static constexpr gmx::EnumerationArray<StateKineticEntry, const char*> stateKineticEntryNames = {
217 "Ekin_n", "Ekinh", "dEkindlambda", "mv_cos", "Ekinf",
218 "Ekinh_old", "EkinScaleF_NHC", "EkinScaleH_NHC", "Vscale_NHC", "Ekin_Total"
220 return stateKineticEntryNames[enumValue];
223 enum class StateEnergyEntry : int
240 enum class StatePullEntry : int
249 enum class StatePullCoordEntry : int
261 static const char* enumValueToString(StatePullCoordEntry enumValue)
263 static constexpr gmx::EnumerationArray<StatePullCoordEntry, const char*> statePullCoordEntryNames = {
264 "reference-sum", "sum", "dr01-sum", "dr23-sum", "dr45-sum", "fscal-sum", "dynax-sum"
266 return statePullCoordEntryNames[enumValue];
269 enum class StatePullGroupEntry : int
275 static const char* enumValueToString(StatePullGroupEntry enumValue)
277 static constexpr gmx::EnumerationArray<StatePullGroupEntry, const char*> statePullGroupEntryNames = {
280 return statePullGroupEntryNames[enumValue];
283 static const char* enumValueToString(StateEnergyEntry enumValue)
285 static constexpr gmx::EnumerationArray<StateEnergyEntry, const char*> stateEnergyEntryNames = {
295 "energy_delta_h_list",
296 "energy_delta_h_start_time",
297 "energy_delta_h_start_lambda"
299 return stateEnergyEntryNames[enumValue];
302 static const char* enumValueToString(StatePullEntry enumValue)
304 static constexpr gmx::EnumerationArray<StatePullEntry, const char*> statePullEntryNames = {
305 "pullhistory_numcoordinates",
306 "pullhistory_numgroups",
307 "pullhistory_numvaluesinxsum",
308 "pullhistory_numvaluesinfsum"
310 return statePullEntryNames[enumValue];
313 /* free energy history variables -- need to be preserved over checkpoint */
314 enum class StateFepEntry : int
333 //! free energy history names
334 static const char* enumValueToString(StateFepEntry enumValue)
336 static constexpr gmx::EnumerationArray<StateFepEntry, const char*> stateFepEntryNames = {
339 "Wang-Landau Histogram",
347 "accumulated_plus_2",
348 "accumulated_minus_2",
352 return stateFepEntryNames[enumValue];
355 //! AWH biasing history variables
356 enum class StateAwhEntry : int
359 EquilibrateHistogram,
365 LogScaledSampleWeight,
367 ForceCorrelationGrid,
371 static const char* enumValueToString(StateAwhEntry enumValue)
373 static constexpr gmx::EnumerationArray<StateAwhEntry, const char*> stateAwhEntryNames = {
374 "awh_in_initial", "awh_equilibrateHistogram", "awh_histsize", "awh_npoints",
375 "awh_coordpoint", "awh_umbrellaGridpoint", "awh_updatelist", "awh_logScaledSampleWeight",
376 "awh_numupdates", "awh_forceCorrelationGrid"
378 return stateAwhEntryNames[enumValue];
381 enum class StatePullCommunicationEntry : int
387 //! Higher level vector element type, only used for formatting checkpoint dumps
388 enum class CptElementType
390 integer, //!< integer
391 real, //!< float or double, not linked to precision of type real
392 real3, //!< float[3] or double[3], not linked to precision of type real
393 matrix3x3 //!< float[3][3] or double[3][3], not linked to precision of type real
396 static void cp_warning(FILE* fp)
398 fprintf(fp, "\nWARNING: Checkpoint file is corrupted or truncated\n\n");
401 [[noreturn]] static void cp_error()
403 gmx_fatal(FARGS, "Checkpoint file corrupted/truncated, or maybe you are out of disk space?");
406 static void do_cpt_string_err(XDR* xd, const char* desc, gmx::ArrayRef<char> s, FILE* list)
408 char* data = s.data();
409 if (xdr_string(xd, &data, s.size()) == 0)
415 fprintf(list, "%s = %s\n", desc, data);
419 static int do_cpt_int(XDR* xd, const char* desc, int* i, FILE* list)
421 if (xdr_int(xd, i) == 0)
427 fprintf(list, "%s = %d\n", desc, *i);
432 static int do_cpt_u_chars(XDR* xd, const char* desc, int n, unsigned char* i, FILE* list)
436 fprintf(list, "%s = ", desc);
439 for (int j = 0; j < n && res; j++)
441 res &= xdr_u_char(xd, &i[j]);
444 fprintf(list, "%02x", i[j]);
459 template<typename EnumType>
460 static int do_cpt_enum_as_int(XDR* xd, const char* desc, EnumType* enumValue, FILE* list)
462 static_assert(std::is_same<std::underlying_type_t<EnumType>, int>::value,
463 "Only enums with underlying type int are supported.");
464 auto castedValue = static_cast<int>(*enumValue);
465 if (xdr_int(xd, &castedValue) == 0)
469 *enumValue = static_cast<EnumType>(castedValue);
472 fprintf(list, "%s = %d\n", desc, castedValue);
477 template<typename EnumType>
478 static int do_cpt_n_enum_as_int(XDR* xd, const char* desc, int n, EnumType* enumValue, FILE* list)
481 for (int j = 0; j < n && res; j++)
483 res &= do_cpt_enum_as_int<EnumType>(xd, desc, &enumValue[j], list);
493 static void do_cpt_int_err(XDR* xd, const char* desc, int* i, FILE* list)
495 if (do_cpt_int(xd, desc, i, list) < 0)
501 static void do_cpt_bool_err(XDR* xd, const char* desc, bool* b, FILE* list)
503 int i = static_cast<int>(*b);
505 if (do_cpt_int(xd, desc, &i, list) < 0)
513 static void do_cpt_step_err(XDR* xd, const char* desc, int64_t* i, FILE* list)
515 char buf[STEPSTRSIZE];
517 if (xdr_int64(xd, i) == 0)
523 fprintf(list, "%s = %s\n", desc, gmx_step_str(*i, buf));
527 static void do_cpt_double_err(XDR* xd, const char* desc, double* f, FILE* list)
529 if (xdr_double(xd, f) == 0)
535 fprintf(list, "%s = %f\n", desc, *f);
539 static void do_cpt_real_err(XDR* xd, real* f)
542 bool_t res = xdr_double(xd, f);
544 bool_t res = xdr_float(xd, f);
552 static void do_cpt_n_rvecs_err(XDR* xd, const char* desc, int n, rvec f[], FILE* list)
554 for (int i = 0; i < n; i++)
556 for (int j = 0; j < DIM; j++)
558 do_cpt_real_err(xd, &f[i][j]);
564 pr_rvecs(list, 0, desc, f, n);
576 static const XdrDataType value = XdrDataType::Int;
580 struct xdr_type<float>
582 static const XdrDataType value = XdrDataType::Float;
586 struct xdr_type<double>
588 static const XdrDataType value = XdrDataType::Double;
591 //! \brief Returns size in byte of an XdrDataType
592 static inline unsigned int sizeOfXdrType(XdrDataType xdrType)
596 case XdrDataType::Int: return sizeof(int);
597 case XdrDataType::Float: return sizeof(float);
598 case XdrDataType::Double: return sizeof(double);
599 default: GMX_RELEASE_ASSERT(false, "XDR data type not implemented");
605 //! \brief Returns the XDR process function for i/o of an XDR type
606 static inline xdrproc_t xdrProc(XdrDataType xdrType)
610 case XdrDataType::Int: return reinterpret_cast<xdrproc_t>(xdr_int);
611 case XdrDataType::Float: return reinterpret_cast<xdrproc_t>(xdr_float);
612 case XdrDataType::Double: return reinterpret_cast<xdrproc_t>(xdr_double);
613 default: GMX_RELEASE_ASSERT(false, "XDR data type not implemented");
619 /*! \brief Lists or only reads an xdr vector from checkpoint file
621 * When list!=NULL reads and lists the \p nf vector elements of type \p xdrType.
622 * The header for the print is set by \p part and \p ecpt.
623 * The formatting of the printing is set by \p cptElementType.
624 * When list==NULL only reads the elements.
626 template<typename Enum>
627 static bool_t listXdrVector(XDR* xd, Enum ecpt, int nf, XdrDataType xdrType, FILE* list, CptElementType cptElementType)
631 const unsigned int elemSize = sizeOfXdrType(xdrType);
632 std::vector<char> data(nf * elemSize);
633 res = xdr_vector(xd, data.data(), nf, elemSize, xdrProc(xdrType));
639 case XdrDataType::Int:
640 pr_ivec(list, 0, enumValueToString(ecpt), reinterpret_cast<const int*>(data.data()), nf, TRUE);
642 case XdrDataType::Float:
644 if (cptElementType == CptElementType::real3)
646 pr_rvecs(list, 0, enumValueToString(ecpt), reinterpret_cast<const rvec*>(data.data()), nf / 3);
651 /* Note: With double precision code dumping a single precision rvec will produce float iso rvec print, but that's a minor annoyance */
652 pr_fvec(list, 0, enumValueToString(ecpt), reinterpret_cast<const float*>(data.data()), nf, TRUE);
655 case XdrDataType::Double:
657 if (cptElementType == CptElementType::real3)
659 pr_rvecs(list, 0, enumValueToString(ecpt), reinterpret_cast<const rvec*>(data.data()), nf / 3);
664 /* Note: With single precision code dumping a double precision rvec will produce float iso rvec print, but that's a minor annoyance */
665 pr_dvec(list, 0, enumValueToString(ecpt), reinterpret_cast<const double*>(data.data()), nf, TRUE);
668 default: GMX_RELEASE_ASSERT(false, "Data type not implemented for listing");
675 //! \brief Convert a double array, typed char*, to float
676 gmx_unused static void convertArrayRealPrecision(const char* c, float* v, int n)
678 const double* d = reinterpret_cast<const double*>(c);
679 for (int i = 0; i < n; i++)
681 v[i] = static_cast<float>(d[i]);
685 //! \brief Convert a float array, typed char*, to double
686 static void convertArrayRealPrecision(const char* c, double* v, int n)
688 const float* f = reinterpret_cast<const float*>(c);
689 for (int i = 0; i < n; i++)
691 v[i] = static_cast<double>(f[i]);
695 //! \brief Generate an error for trying to convert to integer
696 static void convertArrayRealPrecision(const char gmx_unused* c, int gmx_unused* v, int gmx_unused n)
698 GMX_RELEASE_ASSERT(false,
699 "We only expect type mismatches between float and double, not integer");
702 /*! \brief Low-level routine for reading/writing a vector of reals from/to file.
704 * This is the only routine that does the actually i/o of real vector,
705 * all other routines are intermediate level routines for specific real
706 * data types, calling this routine.
707 * Currently this routine is (too) complex, since it handles both real *
708 * and std::vector<real>. Using real * is deprecated and this routine
709 * will simplify a lot when only std::vector needs to be supported.
711 * The routine is generic to vectors with different allocators,
712 * because as part of reading a checkpoint there are vectors whose
713 * size is not known until reading has progressed far enough, so a
714 * resize method must be called.
716 * When not listing, we use either v or vector, depending on which is !=NULL.
717 * If nval >= 0, nval is used; on read this should match the passed value.
718 * If nval n<0, *nptr (with v) or vector->size() is used. On read using v,
719 * the value is stored in nptr
721 template<typename T, typename AllocatorType, typename Enum>
722 static int doVectorLow(XDR* xd,
728 std::vector<T, AllocatorType>* vector,
730 CptElementType cptElementType)
732 GMX_RELEASE_ASSERT(list != nullptr || (v != nullptr && vector == nullptr)
733 || (v == nullptr && vector != nullptr),
734 "Without list, we should have exactly one of v and vector != NULL");
738 int numElemInTheFile;
743 GMX_RELEASE_ASSERT(nptr == nullptr, "With nval>=0 we should have nptr==NULL");
744 numElemInTheFile = nval;
750 GMX_RELEASE_ASSERT(nptr != nullptr, "With nval<0 we should have nptr!=NULL");
751 numElemInTheFile = *nptr;
755 numElemInTheFile = vector->size();
759 /* Read/write the vector element count */
760 res = xdr_int(xd, &numElemInTheFile);
765 /* Read/write the element data type */
766 constexpr XdrDataType xdrTypeInTheCode = xdr_type<T>::value;
767 XdrDataType xdrTypeInTheFile = xdrTypeInTheCode;
768 int xdrTypeInTheFileAsInt = static_cast<int>(xdrTypeInTheFile);
769 res = xdr_int(xd, &xdrTypeInTheFileAsInt);
770 xdrTypeInTheFile = static_cast<XdrDataType>(xdrTypeInTheFileAsInt);
776 if (list == nullptr && (sflags & enumValueToBitMask(ecpt)))
780 if (numElemInTheFile != nval)
783 "Count mismatch for state entry %s, code count is %d, file count is %d\n",
784 enumValueToString(ecpt),
789 else if (nptr != nullptr)
791 *nptr = numElemInTheFile;
794 bool typesMatch = (xdrTypeInTheFile == xdrTypeInTheCode);
799 "mismatch for state entry %s, code precision is %s, file precision is %s",
800 enumValueToString(ecpt),
801 enumValueToString(xdrTypeInTheCode),
802 enumValueToString(xdrTypeInTheFile));
804 /* Matching int and real should never occur, but check anyhow */
805 if (xdrTypeInTheFile == XdrDataType::Int || xdrTypeInTheCode == XdrDataType::Int)
808 "Type %s: incompatible checkpoint formats or corrupted checkpoint file.",
818 snew(*v, numElemInTheFile);
824 /* This conditional ensures that we don't resize on write.
825 * In particular in the state where this code was written
826 * vector has a size of numElemInThefile and we
827 * don't want to lose that padding here.
829 if (vector->size() < static_cast<unsigned int>(numElemInTheFile))
831 vector->resize(numElemInTheFile);
839 vChar = reinterpret_cast<char*>(vp);
843 snew(vChar, numElemInTheFile * sizeOfXdrType(xdrTypeInTheFile));
846 xd, vChar, numElemInTheFile, sizeOfXdrType(xdrTypeInTheFile), xdrProc(xdrTypeInTheFile));
854 /* In the old code float-double conversion came for free.
855 * In the new code we still support it, mainly because
856 * the tip4p_continue regression test makes use of this.
857 * It's an open question if we do or don't want to allow this.
859 convertArrayRealPrecision(vChar, vp, numElemInTheFile);
865 res = listXdrVector(xd, ecpt, numElemInTheFile, xdrTypeInTheFile, list, cptElementType);
871 //! \brief Read/Write a std::vector, on read checks the number of elements matches \p numElements, if specified.
872 template<typename T, typename Enum>
873 static int doVector(XDR* xd, Enum ecpt, int sflags, std::vector<T>* vector, FILE* list, int numElements = -1)
875 return doVectorLow<T>(
876 xd, ecpt, sflags, numElements, nullptr, nullptr, vector, list, CptElementType::real);
879 //! \brief Read/Write an ArrayRef<real>.
880 template<typename Enum>
881 static int doRealArrayRef(XDR* xd, Enum ecpt, int sflags, gmx::ArrayRef<real> vector, FILE* list)
883 real* v_real = vector.data();
884 return doVectorLow<real, std::allocator<real>>(
885 xd, ecpt, sflags, vector.size(), nullptr, &v_real, nullptr, list, CptElementType::real);
888 //! Convert from view of RVec to view of real.
889 static gmx::ArrayRef<real> realArrayRefFromRVecArrayRef(gmx::ArrayRef<gmx::RVec> ofRVecs)
891 return gmx::arrayRefFromArray<real>(reinterpret_cast<real*>(ofRVecs.data()), ofRVecs.size() * DIM);
894 //! \brief Read/Write a PaddedVector whose value_type is RVec.
895 template<typename PaddedVectorOfRVecType, typename Enum>
896 static int doRvecVector(XDR* xd, Enum ecpt, int sflags, PaddedVectorOfRVecType* v, int numAtoms, FILE* list)
898 const int numReals = numAtoms * DIM;
903 sflags & enumValueToBitMask(ecpt),
904 "When not listing, the flag for the entry should be set when requesting i/o");
905 GMX_RELEASE_ASSERT(v->size() == numAtoms, "v should have sufficient size for numAtoms");
907 return doRealArrayRef(xd, ecpt, sflags, realArrayRefFromRVecArrayRef(makeArrayRef(*v)), list);
911 // Use the rebind facility to change the value_type of the
912 // allocator from RVec to real.
913 using realAllocator =
914 typename std::allocator_traits<typename PaddedVectorOfRVecType::allocator_type>::template rebind_alloc<real>;
915 return doVectorLow<real, realAllocator>(
916 xd, ecpt, sflags, numReals, nullptr, nullptr, nullptr, list, CptElementType::real);
920 /* This function stores n along with the reals for reading,
921 * but on reading it assumes that n matches the value in the checkpoint file,
922 * a fatal error is generated when this is not the case.
924 template<typename Enum>
925 static int do_cpte_reals(XDR* xd, Enum ecpt, int sflags, int n, real** v, FILE* list)
927 return doVectorLow<real, std::allocator<real>>(
928 xd, ecpt, sflags, n, nullptr, v, nullptr, list, CptElementType::real);
931 template<typename Enum>
932 static int do_cpte_real(XDR* xd, Enum ecpt, int sflags, real* r, FILE* list)
934 return doVectorLow<real, std::allocator<real>>(
935 xd, ecpt, sflags, 1, nullptr, &r, nullptr, list, CptElementType::real);
938 template<typename Enum>
939 static int do_cpte_ints(XDR* xd, Enum ecpt, int sflags, int n, int** v, FILE* list)
941 return doVectorLow<int, std::allocator<int>>(
942 xd, ecpt, sflags, n, nullptr, v, nullptr, list, CptElementType::integer);
945 template<typename Enum>
946 static int do_cpte_int(XDR* xd, Enum ecpt, int sflags, int* i, FILE* list)
948 return do_cpte_ints(xd, ecpt, sflags, 1, &i, list);
951 template<typename Enum>
952 static int do_cpte_bool(XDR* xd, Enum ecpt, int sflags, bool* b, FILE* list)
954 int i = static_cast<int>(*b);
955 int ret = do_cpte_int(xd, ecpt, sflags, &i, list);
960 template<typename Enum>
961 static int do_cpte_doubles(XDR* xd, Enum ecpt, int sflags, int n, double** v, FILE* list)
963 return doVectorLow<double, std::allocator<double>>(
964 xd, ecpt, sflags, n, nullptr, v, nullptr, list, CptElementType::real);
967 template<typename Enum>
968 static int do_cpte_double(XDR* xd, Enum ecpt, int sflags, double* r, FILE* list)
970 return do_cpte_doubles(xd, ecpt, sflags, 1, &r, list);
973 template<typename Enum>
974 static int do_cpte_matrix(XDR* xd, Enum ecpt, int sflags, matrix v, FILE* list)
980 ret = doVectorLow<real, std::allocator<real>>(
981 xd, ecpt, sflags, DIM * DIM, nullptr, &vr, nullptr, nullptr, CptElementType::matrix3x3);
983 if (list && ret == 0)
985 pr_rvecs(list, 0, enumValueToString(ecpt), v, DIM);
991 template<typename Enum>
992 static int do_cpte_nmatrix(XDR* xd, Enum ecpt, int sflags, int n, real** v, FILE* list)
996 char name[CPTSTRLEN];
1003 for (i = 0; i < n; i++)
1005 reti = doVectorLow<real, std::allocator<real>>(
1006 xd, ecpt, sflags, n, nullptr, &(v[i]), nullptr, nullptr, CptElementType::matrix3x3);
1007 if (list && reti == 0)
1009 sprintf(name, "%s[%d]", enumValueToString(ecpt), i);
1010 pr_reals(list, 0, name, v[i], n);
1020 template<typename Enum>
1021 static int do_cpte_matrices(XDR* xd, Enum ecpt, int sflags, int n, matrix** v, FILE* list)
1024 matrix *vp, *va = nullptr;
1030 res = xdr_int(xd, &nf);
1035 if (list == nullptr && nf != n)
1038 "Count mismatch for state entry %s, code count is %d, file count is %d\n",
1039 enumValueToString(ecpt),
1043 if (list || !(sflags & enumValueToBitMask(ecpt)))
1056 snew(vr, nf * DIM * DIM);
1057 for (i = 0; i < nf; i++)
1059 for (j = 0; j < DIM; j++)
1061 for (k = 0; k < DIM; k++)
1063 vr[(i * DIM + j) * DIM + k] = vp[i][j][k];
1067 ret = doVectorLow<real, std::allocator<real>>(
1068 xd, ecpt, sflags, nf * DIM * DIM, nullptr, &vr, nullptr, nullptr, CptElementType::matrix3x3);
1069 for (i = 0; i < nf; i++)
1071 for (j = 0; j < DIM; j++)
1073 for (k = 0; k < DIM; k++)
1075 vp[i][j][k] = vr[(i * DIM + j) * DIM + k];
1081 if (list && ret == 0)
1083 for (i = 0; i < nf; i++)
1085 pr_rvecs(list, 0, enumValueToString(ecpt), vp[i], DIM);
1096 static void do_cpt_header(XDR* xd, gmx_bool bRead, FILE* list, CheckpointHeaderContents* contents)
1109 res = xdr_int(xd, &magic);
1113 "The checkpoint file is empty/corrupted, or maybe you are out of disk space?");
1115 if (magic != CPT_MAGIC1)
1118 "Start of file magic number mismatch, checkpoint file has %d, should be %d\n"
1119 "The checkpoint file is corrupted or not a checkpoint file",
1126 gmx_gethostname(fhost, 255);
1128 do_cpt_string_err(xd, "GROMACS version", contents->version, list);
1129 // The following fields are no longer ever written with meaningful
1130 // content, but because they precede the file version, there is no
1131 // good way for new code to read the old and new formats, nor a
1132 // good way for old code to avoid giving an error while reading a
1133 // new format. So we read and write a field that no longer has a
1135 do_cpt_string_err(xd, "GROMACS build time UNUSED", contents->btime_UNUSED, list);
1136 do_cpt_string_err(xd, "GROMACS build user UNUSED", contents->buser_UNUSED, list);
1137 do_cpt_string_err(xd, "GROMACS build host UNUSED", contents->bhost_UNUSED, list);
1138 do_cpt_string_err(xd, "generating program", contents->fprog, list);
1139 do_cpt_string_err(xd, "generation time", contents->ftime, list);
1140 contents->file_version = cpt_version;
1141 do_cpt_enum_as_int<CheckPointVersion>(xd, "checkpoint file version", &contents->file_version, list);
1142 if (contents->file_version > cpt_version)
1145 "Attempting to read a checkpoint file of version %d with code of version %d\n",
1146 static_cast<int>(contents->file_version),
1147 static_cast<int>(cpt_version));
1149 if (contents->file_version >= CheckPointVersion::DoublePrecisionBuild)
1151 do_cpt_int_err(xd, "GROMACS double precision", &contents->double_prec, list);
1155 contents->double_prec = -1;
1157 if (contents->file_version >= CheckPointVersion::HostInformation)
1159 do_cpt_string_err(xd, "generating host", fhost, list);
1161 do_cpt_int_err(xd, "#atoms", &contents->natoms, list);
1162 do_cpt_int_err(xd, "#T-coupling groups", &contents->ngtc, list);
1163 if (contents->file_version >= CheckPointVersion::NoseHooverThermostat)
1165 do_cpt_int_err(xd, "#Nose-Hoover T-chains", &contents->nhchainlength, list);
1169 contents->nhchainlength = 1;
1171 if (contents->file_version >= CheckPointVersion::NoseHooverBarostat)
1173 do_cpt_int_err(xd, "#Nose-Hoover T-chains for barostat ", &contents->nnhpres, list);
1177 contents->nnhpres = 0;
1179 if (contents->file_version >= CheckPointVersion::LambdaStateAndHistory)
1181 do_cpt_int_err(xd, "# of total lambda states ", &contents->nlambda, list);
1185 contents->nlambda = 0;
1188 int integrator = static_cast<int>(contents->eIntegrator);
1189 do_cpt_int_err(xd, "integrator", &integrator, list);
1192 contents->eIntegrator = static_cast<IntegrationAlgorithm>(integrator);
1195 if (contents->file_version >= CheckPointVersion::SafeSimulationPart)
1197 do_cpt_int_err(xd, "simulation part #", &contents->simulation_part, list);
1201 contents->simulation_part = 1;
1203 if (contents->file_version >= CheckPointVersion::SafeSteps)
1205 do_cpt_step_err(xd, "step", &contents->step, list);
1210 do_cpt_int_err(xd, "step", &idum, list);
1211 contents->step = static_cast<int64_t>(idum);
1213 do_cpt_double_err(xd, "t", &contents->t, list);
1214 do_cpt_int_err(xd, "#PP-ranks", &contents->nnodes, list);
1215 do_cpt_int_err(xd, "dd_nc[x]", &contents->dd_nc[XX], list);
1216 do_cpt_int_err(xd, "dd_nc[y]", &contents->dd_nc[YY], list);
1217 do_cpt_int_err(xd, "dd_nc[z]", &contents->dd_nc[ZZ], list);
1218 do_cpt_int_err(xd, "#PME-only ranks", &contents->npme, list);
1219 do_cpt_int_err(xd, "state flags", &contents->flags_state, list);
1220 if (contents->file_version >= CheckPointVersion::EkinDataAndFlags)
1222 do_cpt_int_err(xd, "ekin data flags", &contents->flags_eks, list);
1223 do_cpt_int_err(xd, "energy history flags", &contents->flags_enh, list);
1227 contents->flags_eks = 0;
1228 contents->flags_enh = (contents->flags_state >> (static_cast<int>(StateEntry::OrireDtav) + 1));
1229 contents->flags_state = (contents->flags_state
1230 & ~((1 << (static_cast<int>(StateEntry::OrireDtav) + 1))
1231 | (1 << (static_cast<int>(StateEntry::OrireDtav) + 2))
1232 | (1 << (static_cast<int>(StateEntry::OrireDtav) + 3))));
1234 if (contents->file_version >= CheckPointVersion::LambdaStateAndHistory)
1236 do_cpt_int_err(xd, "df history flags", &contents->flags_dfh, list);
1240 contents->flags_dfh = 0;
1243 if (contents->file_version >= CheckPointVersion::EssentialDynamics)
1245 do_cpt_int_err(xd, "ED data sets", &contents->nED, list);
1252 if (contents->file_version >= CheckPointVersion::SwapState)
1254 int swapState = static_cast<int>(contents->eSwapCoords);
1255 do_cpt_int_err(xd, "swap", &swapState, list);
1258 contents->eSwapCoords = static_cast<SwapType>(swapState);
1263 contents->eSwapCoords = SwapType::No;
1266 if (contents->file_version >= CheckPointVersion::AwhHistoryFlags)
1268 do_cpt_int_err(xd, "AWH history flags", &contents->flags_awhh, list);
1272 contents->flags_awhh = 0;
1275 if (contents->file_version >= CheckPointVersion::RemoveBuildMachineInformation)
1277 do_cpt_int_err(xd, "pull history flags", &contents->flagsPullHistory, list);
1281 contents->flagsPullHistory = 0;
1284 if (contents->file_version >= CheckPointVersion::ModularSimulator)
1287 xd, "Is modular simulator checkpoint", &contents->isModularSimulatorCheckpoint, list);
1291 contents->isModularSimulatorCheckpoint = false;
1295 static int do_cpt_footer(XDR* xd, CheckPointVersion file_version)
1300 if (file_version >= CheckPointVersion::AddMagicNumber)
1303 res = xdr_int(xd, &magic);
1308 if (magic != CPT_MAGIC2)
1317 static int do_cpt_state(XDR* xd, int fflags, t_state* state, FILE* list)
1320 const int sflags = state->flags;
1321 // If reading, state->natoms was probably just read, so
1322 // allocations need to be managed. If writing, this won't change
1323 // anything that matters.
1324 using StateFlags = gmx::EnumerationArray<StateEntry, bool>;
1325 state_change_natoms(state, state->natoms);
1326 for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
1328 if (fflags & enumValueToBitMask(*i))
1332 case StateEntry::Lambda:
1333 ret = doRealArrayRef(xd, *i, sflags, state->lambda, list);
1335 case StateEntry::FepState:
1336 ret = do_cpte_int(xd, *i, sflags, &state->fep_state, list);
1338 case StateEntry::Box: ret = do_cpte_matrix(xd, *i, sflags, state->box, list); break;
1339 case StateEntry::BoxRel:
1340 ret = do_cpte_matrix(xd, *i, sflags, state->box_rel, list);
1342 case StateEntry::BoxV:
1343 ret = do_cpte_matrix(xd, *i, sflags, state->boxv, list);
1345 case StateEntry::PressurePrevious:
1346 ret = do_cpte_matrix(xd, *i, sflags, state->pres_prev, list);
1348 case StateEntry::SVirPrev:
1349 ret = do_cpte_matrix(xd, *i, sflags, state->svir_prev, list);
1351 case StateEntry::FVirPrev:
1352 ret = do_cpte_matrix(xd, *i, sflags, state->fvir_prev, list);
1354 case StateEntry::Nhxi:
1355 ret = doVector<double>(xd, *i, sflags, &state->nosehoover_xi, list);
1357 case StateEntry::Nhvxi:
1358 ret = doVector<double>(xd, *i, sflags, &state->nosehoover_vxi, list);
1360 case StateEntry::Nhpresxi:
1361 ret = doVector<double>(xd, *i, sflags, &state->nhpres_xi, list);
1363 case StateEntry::Nhpresvxi:
1364 ret = doVector<double>(xd, *i, sflags, &state->nhpres_vxi, list);
1366 case StateEntry::ThermInt:
1367 ret = doVector<double>(xd, *i, sflags, &state->therm_integral, list);
1369 case StateEntry::BarosInt:
1370 ret = do_cpte_double(xd, *i, sflags, &state->baros_integral, list);
1372 case StateEntry::Veta:
1373 ret = do_cpte_real(xd, *i, sflags, &state->veta, list);
1375 case StateEntry::Vol0:
1376 ret = do_cpte_real(xd, *i, sflags, &state->vol0, list);
1379 ret = doRvecVector(xd, *i, sflags, &state->x, state->natoms, list);
1382 ret = doRvecVector(xd, *i, sflags, &state->v, state->natoms, list);
1384 /* The RNG entries are no longer written,
1385 * the next 4 lines are only for reading old files.
1386 * It's OK that three case statements fall through.
1388 case StateEntry::LDRngNotSupported:
1389 case StateEntry::LDRngINotSupported:
1390 case StateEntry::MCRngNotSupported:
1391 case StateEntry::MCRngINotSupported:
1392 ret = do_cpte_ints(xd, *i, sflags, 0, nullptr, list);
1394 case StateEntry::DisreInitF:
1395 ret = do_cpte_real(xd, *i, sflags, &state->hist.disre_initf, list);
1397 case StateEntry::DisreRm3Tav:
1398 ret = doVector<real>(xd, *i, sflags, &state->hist.disre_rm3tav, list);
1400 case StateEntry::OrireInitF:
1401 ret = do_cpte_real(xd, *i, sflags, &state->hist.orire_initf, list);
1403 case StateEntry::OrireDtav:
1404 ret = doVector<real>(xd, *i, sflags, &state->hist.orire_Dtav, list);
1406 case StateEntry::PullComPrevStep:
1407 ret = doVector<double>(xd, *i, sflags, &state->pull_com_prev_step, list);
1411 "Unknown state entry %d\n"
1412 "You are reading a checkpoint file written by different code, which "
1414 enumValueToBitMask(*i));
1421 static int do_cpt_ekinstate(XDR* xd, int fflags, ekinstate_t* ekins, FILE* list)
1425 using StateFlags = gmx::EnumerationArray<StateKineticEntry, bool>;
1426 for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
1428 if (fflags & enumValueToBitMask(*i))
1433 case StateKineticEntry::EkinNumber:
1434 ret = do_cpte_int(xd, *i, fflags, &ekins->ekin_n, list);
1436 case StateKineticEntry::EkinHalfStep:
1437 ret = do_cpte_matrices(xd, *i, fflags, ekins->ekin_n, &ekins->ekinh, list);
1439 case StateKineticEntry::EkinFullStep:
1440 ret = do_cpte_matrices(xd, *i, fflags, ekins->ekin_n, &ekins->ekinf, list);
1442 case StateKineticEntry::EkinHalfStepOld:
1443 ret = do_cpte_matrices(xd, *i, fflags, ekins->ekin_n, &ekins->ekinh_old, list);
1445 case StateKineticEntry::EkinTotal:
1446 ret = do_cpte_matrix(xd, *i, fflags, ekins->ekin_total, list);
1448 case StateKineticEntry::EkinNoseHooverScaleFullStep:
1449 ret = doVector<double>(xd, *i, fflags, &ekins->ekinscalef_nhc, list);
1451 case StateKineticEntry::VelocityScale:
1452 ret = doVector<double>(xd, *i, fflags, &ekins->vscale_nhc, list);
1454 case StateKineticEntry::EkinNoseHooverScaleHalfStep:
1455 ret = doVector<double>(xd, *i, fflags, &ekins->ekinscaleh_nhc, list);
1457 case StateKineticEntry::DEkinDLambda:
1458 ret = do_cpte_real(xd, *i, fflags, &ekins->dekindl, list);
1460 case StateKineticEntry::Mvcos:
1461 ret = do_cpte_real(xd, *i, fflags, &ekins->mvcos, list);
1465 "Unknown ekin data state entry %d\n"
1466 "You are probably reading a new checkpoint file with old code",
1467 enumValueToBitMask(*i));
1476 static int do_cpt_swapstate(XDR* xd, gmx_bool bRead, SwapType eSwapCoords, swaphistory_t* swapstate, FILE* list)
1478 int swap_cpt_version = 2;
1480 if (eSwapCoords == SwapType::No)
1485 swapstate->bFromCpt = bRead;
1486 swapstate->eSwapCoords = eSwapCoords;
1488 do_cpt_int_err(xd, "swap checkpoint version", &swap_cpt_version, list);
1489 if (bRead && swap_cpt_version < 2)
1492 "Cannot read checkpoint files that were written with old versions"
1493 "of the ion/water position swapping protocol.\n");
1496 do_cpt_int_err(xd, "swap coupling steps", &swapstate->nAverage, list);
1498 /* When reading, init_swapcoords has not been called yet,
1499 * so we have to allocate memory first. */
1500 do_cpt_int_err(xd, "number of ion types", &swapstate->nIonTypes, list);
1503 snew(swapstate->ionType, swapstate->nIonTypes);
1506 for (auto ic : gmx::EnumerationWrapper<Compartment>{})
1508 for (int ii = 0; ii < swapstate->nIonTypes; ii++)
1510 swapstateIons_t* gs = &swapstate->ionType[ii];
1514 do_cpt_int_err(xd, "swap requested atoms", &gs->nMolReq[ic], list);
1518 do_cpt_int_err(xd, "swap requested atoms p", gs->nMolReq_p[ic], list);
1523 do_cpt_int_err(xd, "swap influx net", &gs->inflow_net[ic], list);
1527 do_cpt_int_err(xd, "swap influx net p", gs->inflow_net_p[ic], list);
1530 if (bRead && (nullptr == gs->nMolPast[ic]))
1532 snew(gs->nMolPast[ic], swapstate->nAverage);
1535 for (int j = 0; j < swapstate->nAverage; j++)
1539 do_cpt_int_err(xd, "swap past atom counts", &gs->nMolPast[ic][j], list);
1543 do_cpt_int_err(xd, "swap past atom counts p", &gs->nMolPast_p[ic][j], list);
1549 /* Ion flux per channel */
1550 for (auto ic : gmx::EnumerationWrapper<Channel>{})
1552 for (int ii = 0; ii < swapstate->nIonTypes; ii++)
1554 swapstateIons_t* gs = &swapstate->ionType[ii];
1558 do_cpt_int_err(xd, "channel flux A->B", &gs->fluxfromAtoB[ic], list);
1562 do_cpt_int_err(xd, "channel flux A->B p", gs->fluxfromAtoB_p[ic], list);
1567 /* Ion flux leakage */
1570 do_cpt_int_err(xd, "flux leakage", &swapstate->fluxleak, list);
1574 do_cpt_int_err(xd, "flux leakage", swapstate->fluxleak_p, list);
1578 for (int ii = 0; ii < swapstate->nIonTypes; ii++)
1580 swapstateIons_t* gs = &swapstate->ionType[ii];
1582 do_cpt_int_err(xd, "number of ions", &gs->nMol, list);
1586 snew(gs->channel_label, gs->nMol);
1587 snew(gs->comp_from, gs->nMol);
1590 do_cpt_n_enum_as_int<ChannelHistory>(xd, "channel history", gs->nMol, gs->channel_label, list);
1591 do_cpt_n_enum_as_int<Domain>(xd, "domain history", gs->nMol, gs->comp_from, list);
1594 /* Save the last known whole positions to checkpoint
1595 * file to be able to also make multimeric channels whole in PBC */
1596 do_cpt_int_err(xd, "Ch0 atoms", &swapstate->nat[Channel::Zero], list);
1597 do_cpt_int_err(xd, "Ch1 atoms", &swapstate->nat[Channel::One], list);
1600 snew(swapstate->xc_old_whole[Channel::Zero], swapstate->nat[Channel::Zero]);
1601 snew(swapstate->xc_old_whole[Channel::One], swapstate->nat[Channel::One]);
1603 xd, "Ch0 whole x", swapstate->nat[Channel::Zero], swapstate->xc_old_whole[Channel::Zero], list);
1605 xd, "Ch1 whole x", swapstate->nat[Channel::One], swapstate->xc_old_whole[Channel::One], list);
1609 do_cpt_n_rvecs_err(xd,
1611 swapstate->nat[Channel::Zero],
1612 *swapstate->xc_old_whole_p[Channel::Zero],
1615 xd, "Ch1 whole x", swapstate->nat[Channel::One], *swapstate->xc_old_whole_p[Channel::One], list);
1622 static int do_cpt_enerhist(XDR* xd, gmx_bool bRead, int fflags, energyhistory_t* enerhist, FILE* list)
1631 GMX_RELEASE_ASSERT(enerhist != nullptr, "With energy history, we need a valid enerhist pointer");
1633 /* This is stored/read for backward compatibility */
1634 int energyHistoryNumEnergies = 0;
1637 enerhist->nsteps = 0;
1639 enerhist->nsteps_sim = 0;
1640 enerhist->nsum_sim = 0;
1642 else if (enerhist != nullptr)
1644 energyHistoryNumEnergies = enerhist->ener_sum_sim.size();
1647 delta_h_history_t* deltaH = enerhist->deltaHForeignLambdas.get();
1648 using StateFlags = gmx::EnumerationArray<StateEnergyEntry, bool>;
1649 for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
1651 if (fflags & enumValueToBitMask(*i))
1655 case StateEnergyEntry::N:
1656 ret = do_cpte_int(xd, *i, fflags, &energyHistoryNumEnergies, list);
1658 case StateEnergyEntry::Aver:
1659 ret = doVector<double>(xd, *i, fflags, &enerhist->ener_ave, list);
1661 case StateEnergyEntry::Sum:
1662 ret = doVector<double>(xd, *i, fflags, &enerhist->ener_sum, list);
1664 case StateEnergyEntry::NumSum:
1665 do_cpt_step_err(xd, enumValueToString(*i), &enerhist->nsum, list);
1667 case StateEnergyEntry::SumSim:
1668 ret = doVector<double>(xd, *i, fflags, &enerhist->ener_sum_sim, list);
1670 case StateEnergyEntry::NumSumSim:
1671 do_cpt_step_err(xd, enumValueToString(*i), &enerhist->nsum_sim, list);
1673 case StateEnergyEntry::NumSteps:
1674 do_cpt_step_err(xd, enumValueToString(*i), &enerhist->nsteps, list);
1676 case StateEnergyEntry::NumStepsSim:
1677 do_cpt_step_err(xd, enumValueToString(*i), &enerhist->nsteps_sim, list);
1679 case StateEnergyEntry::DeltaHNN:
1682 if (!bRead && deltaH != nullptr)
1684 numDeltaH = deltaH->dh.size();
1686 do_cpt_int_err(xd, enumValueToString(*i), &numDeltaH, list);
1689 if (deltaH == nullptr)
1691 enerhist->deltaHForeignLambdas = std::make_unique<delta_h_history_t>();
1692 deltaH = enerhist->deltaHForeignLambdas.get();
1694 deltaH->dh.resize(numDeltaH);
1695 deltaH->start_lambda_set = FALSE;
1699 case StateEnergyEntry::DeltaHList:
1700 for (auto dh : deltaH->dh)
1702 ret = doVector<real>(xd, *i, fflags, &dh, list);
1705 case StateEnergyEntry::DeltaHStartTime:
1706 ret = do_cpte_double(xd, *i, fflags, &(deltaH->start_time), list);
1708 case StateEnergyEntry::DeltaHStartLambda:
1709 ret = do_cpte_double(xd, *i, fflags, &(deltaH->start_lambda), list);
1713 "Unknown energy history entry %d\n"
1714 "You are probably reading a new checkpoint file with old code",
1715 enumValueToBitMask(*i));
1720 if ((fflags & enumValueToBitMask(StateEnergyEntry::Sum))
1721 && !(fflags & enumValueToBitMask(StateEnergyEntry::SumSim)))
1723 /* Assume we have an old file format and copy sum to sum_sim */
1724 enerhist->ener_sum_sim = enerhist->ener_sum;
1727 if ((fflags & enumValueToBitMask(StateEnergyEntry::NumSum))
1728 && !(fflags & enumValueToBitMask(StateEnergyEntry::NumSteps)))
1730 /* Assume we have an old file format and copy nsum to nsteps */
1731 enerhist->nsteps = enerhist->nsum;
1733 if ((fflags & enumValueToBitMask(StateEnergyEntry::NumSumSim))
1734 && !(fflags & enumValueToBitMask(StateEnergyEntry::NumStepsSim)))
1736 /* Assume we have an old file format and copy nsum to nsteps */
1737 enerhist->nsteps_sim = enerhist->nsum_sim;
1743 static int doCptPullCoordHist(XDR* xd, PullCoordinateHistory* pullCoordHist, FILE* list)
1748 flags |= (enumValueToBitMask(StatePullCoordEntry::ValueReferenceSum)
1749 | enumValueToBitMask(StatePullCoordEntry::ValueSum)
1750 | enumValueToBitMask(StatePullCoordEntry::DR01Sum)
1751 | enumValueToBitMask(StatePullCoordEntry::DR23Sum)
1752 | enumValueToBitMask(StatePullCoordEntry::DR45Sum)
1753 | enumValueToBitMask(StatePullCoordEntry::FScalarSum));
1755 using StateFlags = gmx::EnumerationArray<StatePullCoordEntry, bool>;
1756 for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
1760 case StatePullCoordEntry::ValueReferenceSum:
1761 ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->valueRef), list);
1763 case StatePullCoordEntry::ValueSum:
1764 ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->value), list);
1766 case StatePullCoordEntry::DR01Sum:
1767 for (int j = 0; j < DIM && ret == 0; j++)
1769 ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->dr01[j]), list);
1772 case StatePullCoordEntry::DR23Sum:
1773 for (int j = 0; j < DIM && ret == 0; j++)
1775 ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->dr23[j]), list);
1778 case StatePullCoordEntry::DR45Sum:
1779 for (int j = 0; j < DIM && ret == 0; j++)
1781 ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->dr45[j]), list);
1784 case StatePullCoordEntry::FScalarSum:
1785 ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->scalarForce), list);
1787 case StatePullCoordEntry::DynaxSum:
1788 for (int j = 0; j < DIM && ret == 0; j++)
1790 ret = do_cpte_double(xd, *i, flags, &(pullCoordHist->dynaX[j]), list);
1794 gmx_fatal(FARGS, "Unhandled StatePullCoordEntry enum value: %d", enumValueToBitMask(*i));
1801 static int doCptPullGroupHist(XDR* xd, PullGroupHistory* pullGroupHist, FILE* list)
1806 flags |= (enumValueToBitMask(StatePullGroupEntry::XSum));
1808 using StateFlags = gmx::EnumerationArray<StatePullGroupEntry, bool>;
1809 for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
1813 case StatePullGroupEntry::XSum:
1814 for (int j = 0; j < DIM && ret == 0; j++)
1816 ret = do_cpte_double(xd, *i, flags, &(pullGroupHist->x[j]), list);
1819 default: gmx_fatal(FARGS, "Unhandled pull group state entry");
1827 static int doCptPullHist(XDR* xd, gmx_bool bRead, int fflags, PullHistory* pullHist, FILE* list)
1830 int pullHistoryNumCoordinates = 0;
1831 int pullHistoryNumGroups = 0;
1833 /* Retain the number of terms in the sum and the number of coordinates (used for writing
1834 * average pull forces and coordinates) in the pull history, in temporary variables,
1835 * in case they cannot be read from the checkpoint, in order to have backward compatibility */
1838 pullHist->numValuesInXSum = 0;
1839 pullHist->numValuesInFSum = 0;
1841 else if (pullHist != nullptr)
1843 pullHistoryNumCoordinates = pullHist->pullCoordinateSums.size();
1844 pullHistoryNumGroups = pullHist->pullGroupSums.size();
1848 GMX_RELEASE_ASSERT(fflags == 0, "Without pull history, all flags should be off");
1851 using StateFlags = gmx::EnumerationArray<StatePullEntry, bool>;
1852 for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
1854 if (fflags & (1 << enumValueToBitMask(*i)))
1858 case StatePullEntry::NumCoordinates:
1859 ret = do_cpte_int(xd, *i, fflags, &pullHistoryNumCoordinates, list);
1861 case StatePullEntry::NumGroups:
1862 do_cpt_int_err(xd, enumValueToString(*i), &pullHistoryNumGroups, list);
1864 case StatePullEntry::NumValuesInXSum:
1865 do_cpt_int_err(xd, enumValueToString(*i), &pullHist->numValuesInXSum, list);
1867 case StatePullEntry::NumValuesInFSum:
1868 do_cpt_int_err(xd, enumValueToString(*i), &pullHist->numValuesInFSum, list);
1872 "Unknown pull history entry %d\n"
1873 "You are probably reading a new checkpoint file with old code",
1874 enumValueToBitMask(*i));
1880 pullHist->pullCoordinateSums.resize(pullHistoryNumCoordinates);
1881 pullHist->pullGroupSums.resize(pullHistoryNumGroups);
1883 if (pullHist->numValuesInXSum > 0 || pullHist->numValuesInFSum > 0)
1885 for (size_t i = 0; i < pullHist->pullCoordinateSums.size() && ret == 0; i++)
1887 ret = doCptPullCoordHist(xd, &(pullHist->pullCoordinateSums[i]), list);
1889 for (size_t i = 0; i < pullHist->pullGroupSums.size() && ret == 0; i++)
1891 ret = doCptPullGroupHist(xd, &(pullHist->pullGroupSums[i]), list);
1898 static int do_cpt_df_hist(XDR* xd, int fflags, int nlambda, df_history_t** dfhistPtr, FILE* list)
1907 std::unique_ptr<df_history_t> localDFHistory = nullptr;
1908 if (*dfhistPtr == nullptr)
1910 localDFHistory = std::make_unique<df_history_t>();
1911 *dfhistPtr = localDFHistory.get();
1912 (*dfhistPtr)->nlambda = nlambda;
1913 init_df_history(*dfhistPtr, nlambda);
1915 df_history_t* dfhist = *dfhistPtr;
1917 using StateFlags = gmx::EnumerationArray<StateFepEntry, bool>;
1918 for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
1920 if (fflags & enumValueToBitMask(*i))
1924 case StateFepEntry::IsEquilibrated:
1925 ret = do_cpte_bool(xd, *i, fflags, &dfhist->bEquil, list);
1927 case StateFepEntry::NumAtLambda:
1928 ret = do_cpte_ints(xd, *i, fflags, nlambda, &dfhist->n_at_lam, list);
1930 case StateFepEntry::WangLandauHistogram:
1931 ret = do_cpte_reals(xd, *i, fflags, nlambda, &dfhist->wl_histo, list);
1933 case StateFepEntry::WangLandauDelta:
1934 ret = do_cpte_real(xd, *i, fflags, &dfhist->wl_delta, list);
1936 case StateFepEntry::SumWeights:
1937 ret = do_cpte_reals(xd, *i, fflags, nlambda, &dfhist->sum_weights, list);
1939 case StateFepEntry::SumDG:
1940 ret = do_cpte_reals(xd, *i, fflags, nlambda, &dfhist->sum_dg, list);
1942 case StateFepEntry::SumMinVar:
1943 ret = do_cpte_reals(xd, *i, fflags, nlambda, &dfhist->sum_minvar, list);
1945 case StateFepEntry::SumVar:
1946 ret = do_cpte_reals(xd, *i, fflags, nlambda, &dfhist->sum_variance, list);
1948 case StateFepEntry::Accump:
1949 ret = do_cpte_nmatrix(xd, *i, fflags, nlambda, dfhist->accum_p, list);
1951 case StateFepEntry::Accumm:
1952 ret = do_cpte_nmatrix(xd, *i, fflags, nlambda, dfhist->accum_m, list);
1954 case StateFepEntry::Accump2:
1955 ret = do_cpte_nmatrix(xd, *i, fflags, nlambda, dfhist->accum_p2, list);
1957 case StateFepEntry::Accumm2:
1958 ret = do_cpte_nmatrix(xd, *i, fflags, nlambda, dfhist->accum_m2, list);
1960 case StateFepEntry::Tij:
1961 ret = do_cpte_nmatrix(xd, *i, fflags, nlambda, dfhist->Tij, list);
1963 case StateFepEntry::TijEmp:
1964 ret = do_cpte_nmatrix(xd, *i, fflags, nlambda, dfhist->Tij_empirical, list);
1969 "Unknown df history entry %d\n"
1970 "You are probably reading a new checkpoint file with old code",
1971 enumValueToBitMask(*i));
1980 /* This function stores the last whole configuration of the reference and
1981 * average structure in the .cpt file
1983 static int do_cpt_EDstate(XDR* xd, gmx_bool bRead, int nED, edsamhistory_t* EDstate, FILE* list)
1990 EDstate->bFromCpt = bRead;
1993 /* When reading, init_edsam has not been called yet,
1994 * so we have to allocate memory first. */
1997 snew(EDstate->nref, EDstate->nED);
1998 snew(EDstate->old_sref, EDstate->nED);
1999 snew(EDstate->nav, EDstate->nED);
2000 snew(EDstate->old_sav, EDstate->nED);
2003 /* Read/write the last whole conformation of SREF and SAV for each ED dataset (usually only one) */
2004 for (int i = 0; i < EDstate->nED; i++)
2008 /* Reference structure SREF */
2009 sprintf(buf, "ED%d # of atoms in reference structure", i + 1);
2010 do_cpt_int_err(xd, buf, &EDstate->nref[i], list);
2011 sprintf(buf, "ED%d x_ref", i + 1);
2014 snew(EDstate->old_sref[i], EDstate->nref[i]);
2015 do_cpt_n_rvecs_err(xd, buf, EDstate->nref[i], EDstate->old_sref[i], list);
2019 do_cpt_n_rvecs_err(xd, buf, EDstate->nref[i], EDstate->old_sref_p[i], list);
2022 /* Average structure SAV */
2023 sprintf(buf, "ED%d # of atoms in average structure", i + 1);
2024 do_cpt_int_err(xd, buf, &EDstate->nav[i], list);
2025 sprintf(buf, "ED%d x_av", i + 1);
2028 snew(EDstate->old_sav[i], EDstate->nav[i]);
2029 do_cpt_n_rvecs_err(xd, buf, EDstate->nav[i], EDstate->old_sav[i], list);
2033 do_cpt_n_rvecs_err(xd, buf, EDstate->nav[i], EDstate->old_sav_p[i], list);
2040 static int do_cpt_correlation_grid(XDR* xd,
2042 gmx_unused int fflags,
2043 gmx::CorrelationGridHistory* corrGrid,
2045 StateAwhEntry eawhh)
2049 do_cpt_int_err(xd, enumValueToString(eawhh), &(corrGrid->numCorrelationTensors), list);
2050 do_cpt_int_err(xd, enumValueToString(eawhh), &(corrGrid->tensorSize), list);
2051 do_cpt_int_err(xd, enumValueToString(eawhh), &(corrGrid->blockDataListSize), list);
2055 initCorrelationGridHistory(
2056 corrGrid, corrGrid->numCorrelationTensors, corrGrid->tensorSize, corrGrid->blockDataListSize);
2059 for (gmx::CorrelationBlockDataHistory& blockData : corrGrid->blockDataBuffer)
2061 do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.blockSumWeight), list);
2062 do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.blockSumSquareWeight), list);
2063 do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.blockSumWeightX), list);
2064 do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.blockSumWeightY), list);
2065 do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.sumOverBlocksSquareBlockWeight), list);
2066 do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.sumOverBlocksBlockSquareWeight), list);
2068 xd, enumValueToString(eawhh), &(blockData.sumOverBlocksBlockWeightBlockWeightX), list);
2070 xd, enumValueToString(eawhh), &(blockData.sumOverBlocksBlockWeightBlockWeightY), list);
2071 do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.blockLength), list);
2072 do_cpt_int_err(xd, enumValueToString(eawhh), &(blockData.previousBlockIndex), list);
2073 do_cpt_double_err(xd, enumValueToString(eawhh), &(blockData.correlationIntegral), list);
2079 static int do_cpt_awh_bias(XDR* xd, gmx_bool bRead, int fflags, gmx::AwhBiasHistory* biasHistory, FILE* list)
2083 gmx::AwhBiasStateHistory* state = &biasHistory->state;
2084 using StateFlags = gmx::EnumerationArray<StateAwhEntry, bool>;
2085 for (auto i = StateFlags::keys().begin(); (i != StateFlags::keys().end() && ret == 0); i++)
2087 if (fflags & enumValueToBitMask(*i))
2091 case StateAwhEntry::InInitial:
2092 do_cpt_bool_err(xd, enumValueToString(*i), &state->in_initial, list);
2094 case StateAwhEntry::EquilibrateHistogram:
2095 do_cpt_bool_err(xd, enumValueToString(*i), &state->equilibrateHistogram, list);
2097 case StateAwhEntry::HistogramSize:
2098 do_cpt_double_err(xd, enumValueToString(*i), &state->histSize, list);
2100 case StateAwhEntry::NumPoints:
2105 numPoints = biasHistory->pointState.size();
2107 do_cpt_int_err(xd, enumValueToString(*i), &numPoints, list);
2110 biasHistory->pointState.resize(numPoints);
2114 case StateAwhEntry::CoordPoint:
2115 for (auto& psh : biasHistory->pointState)
2117 do_cpt_double_err(xd, enumValueToString(*i), &psh.target, list);
2118 do_cpt_double_err(xd, enumValueToString(*i), &psh.free_energy, list);
2119 do_cpt_double_err(xd, enumValueToString(*i), &psh.bias, list);
2120 do_cpt_double_err(xd, enumValueToString(*i), &psh.weightsum_iteration, list);
2121 do_cpt_double_err(xd, enumValueToString(*i), &psh.weightsum_covering, list);
2122 do_cpt_double_err(xd, enumValueToString(*i), &psh.weightsum_tot, list);
2123 do_cpt_double_err(xd, enumValueToString(*i), &psh.weightsum_ref, list);
2124 do_cpt_step_err(xd, enumValueToString(*i), &psh.last_update_index, list);
2125 do_cpt_double_err(xd, enumValueToString(*i), &psh.log_pmfsum, list);
2126 do_cpt_double_err(xd, enumValueToString(*i), &psh.visits_iteration, list);
2127 do_cpt_double_err(xd, enumValueToString(*i), &psh.visits_tot, list);
2130 case StateAwhEntry::UmbrellaGridPoint:
2131 do_cpt_int_err(xd, enumValueToString(*i), &(state->umbrellaGridpoint), list);
2133 case StateAwhEntry::UpdateList:
2134 do_cpt_int_err(xd, enumValueToString(*i), &(state->origin_index_updatelist), list);
2135 do_cpt_int_err(xd, enumValueToString(*i), &(state->end_index_updatelist), list);
2137 case StateAwhEntry::LogScaledSampleWeight:
2138 do_cpt_double_err(xd, enumValueToString(*i), &(state->logScaledSampleWeight), list);
2139 do_cpt_double_err(xd, enumValueToString(*i), &(state->maxLogScaledSampleWeight), list);
2141 case StateAwhEntry::NumUpdates:
2142 do_cpt_step_err(xd, enumValueToString(*i), &(state->numUpdates), list);
2144 case StateAwhEntry::ForceCorrelationGrid:
2145 ret = do_cpt_correlation_grid(
2146 xd, bRead, fflags, &biasHistory->forceCorrelationGrid, list, *i);
2148 default: gmx_fatal(FARGS, "Unknown awh history entry %d\n", enumValueToBitMask(*i));
2156 static int do_cpt_awh(XDR* xd, gmx_bool bRead, int fflags, gmx::AwhHistory* awhHistory, FILE* list)
2162 std::shared_ptr<gmx::AwhHistory> awhHistoryLocal;
2164 if (awhHistory == nullptr)
2166 GMX_RELEASE_ASSERT(bRead,
2167 "do_cpt_awh should not be called for writing without an AwhHistory");
2169 awhHistoryLocal = std::make_shared<gmx::AwhHistory>();
2170 awhHistory = awhHistoryLocal.get();
2173 /* To be able to read and write the AWH data several parameters determining the layout of the AWH structs need to be known
2174 (nbias, npoints, etc.). The best thing (?) would be to have these passed to this function. When writing to a checkpoint
2175 these parameters are available in awh_history (after calling init_awh_history). When reading from a checkpoint though, there
2176 is no initialized awh_history (it is initialized and set in this function). The AWH parameters have not always been read
2177 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
2178 when writing a checkpoint, also storing parameters needed for future reading of the checkpoint.
2180 Another issue is that some variables that AWH checkpoints don't have a registered enum and string (e.g. nbias below).
2181 One difficulty is the multilevel structure of the data which would need to be represented somehow. */
2186 numBias = awhHistory->bias.size();
2188 do_cpt_int_err(xd, "awh_nbias", &numBias, list);
2192 awhHistory->bias.resize(numBias);
2194 for (auto& bias : awhHistory->bias)
2196 ret = do_cpt_awh_bias(xd, bRead, fflags, &bias, list);
2202 do_cpt_double_err(xd, "awh_potential_offset", &awhHistory->potentialOffset, list);
2207 static void do_cpt_mdmodules(CheckPointVersion fileVersion,
2208 t_fileio* checkpointFileHandle,
2209 const gmx::MDModulesNotifiers& mdModulesNotifiers,
2212 if (fileVersion >= CheckPointVersion::MDModules)
2214 gmx::FileIOXdrSerializer serializer(checkpointFileHandle);
2215 gmx::KeyValueTreeObject mdModuleCheckpointParameterTree =
2216 gmx::deserializeKeyValueTree(&serializer);
2219 gmx::TextWriter textWriter(outputFile);
2220 gmx::dumpKeyValueTree(&textWriter, mdModuleCheckpointParameterTree);
2222 gmx::MDModulesCheckpointReadingDataOnMaster mdModuleCheckpointReadingDataOnMaster = {
2223 mdModuleCheckpointParameterTree, fileVersion
2225 mdModulesNotifiers.checkpointingNotifier_.notify(mdModuleCheckpointReadingDataOnMaster);
2229 static int do_cpt_files(XDR* xd,
2231 std::vector<gmx_file_position_t>* outputfiles,
2233 CheckPointVersion file_version)
2236 gmx_off_t mask = 0xFFFFFFFFL;
2237 int offset_high, offset_low;
2238 std::array<char, CPTSTRLEN> buf;
2239 GMX_RELEASE_ASSERT(outputfiles, "Must have valid outputfiles");
2241 // Ensure that reading pre-allocates outputfiles, while writing
2242 // writes what is already there.
2243 int nfiles = outputfiles->size();
2244 if (do_cpt_int(xd, "number of output files", &nfiles, list) != 0)
2250 outputfiles->resize(nfiles);
2253 for (auto& outputfile : *outputfiles)
2255 /* 64-bit XDR numbers are not portable, so it is stored as separate high/low fractions */
2258 do_cpt_string_err(xd, "output filename", buf, list);
2259 std::copy(std::begin(buf), std::end(buf), std::begin(outputfile.filename));
2261 if (do_cpt_int(xd, "file_offset_high", &offset_high, list) != 0)
2265 if (do_cpt_int(xd, "file_offset_low", &offset_low, list) != 0)
2269 outputfile.offset = (static_cast<gmx_off_t>(offset_high) << 32)
2270 | (static_cast<gmx_off_t>(offset_low) & mask);
2274 do_cpt_string_err(xd, "output filename", outputfile.filename, list);
2276 offset = outputfile.offset;
2284 offset_low = static_cast<int>(offset & mask);
2285 offset_high = static_cast<int>((offset >> 32) & mask);
2287 if (do_cpt_int(xd, "file_offset_high", &offset_high, list) != 0)
2291 if (do_cpt_int(xd, "file_offset_low", &offset_low, list) != 0)
2296 if (file_version >= CheckPointVersion::FileChecksumAndSize)
2298 if (do_cpt_int(xd, "file_checksum_size", &outputfile.checksumSize, list) != 0)
2302 if (do_cpt_u_chars(xd, "file_checksum", outputfile.checksum.size(), outputfile.checksum.data(), list)
2310 outputfile.checksumSize = -1;
2316 void write_checkpoint_data(t_fileio* fp,
2317 CheckpointHeaderContents headerContents,
2319 LambdaWeightCalculation elamstats,
2321 ObservablesHistory* observablesHistory,
2322 const gmx::MDModulesNotifiers& mdModulesNotifiers,
2323 std::vector<gmx_file_position_t>* outputfiles,
2324 gmx::WriteCheckpointDataHolder* modularSimulatorCheckpointData)
2326 headerContents.flags_eks = 0;
2327 if (state->ekinstate.bUpToDate)
2329 headerContents.flags_eks = (enumValueToBitMask(StateKineticEntry::EkinNumber)
2330 | enumValueToBitMask(StateKineticEntry::EkinHalfStep)
2331 | enumValueToBitMask(StateKineticEntry::EkinFullStep)
2332 | enumValueToBitMask(StateKineticEntry::EkinHalfStepOld)
2333 | enumValueToBitMask(StateKineticEntry::EkinNoseHooverScaleFullStep)
2334 | enumValueToBitMask(StateKineticEntry::EkinNoseHooverScaleHalfStep)
2335 | enumValueToBitMask(StateKineticEntry::VelocityScale)
2336 | enumValueToBitMask(StateKineticEntry::DEkinDLambda)
2337 | enumValueToBitMask(StateKineticEntry::Mvcos));
2339 headerContents.isModularSimulatorCheckpoint = !modularSimulatorCheckpointData->empty();
2341 energyhistory_t* enerhist = observablesHistory->energyHistory.get();
2342 headerContents.flags_enh = 0;
2343 if (enerhist != nullptr && (enerhist->nsum > 0 || enerhist->nsum_sim > 0))
2345 headerContents.flags_enh |= enumValueToBitMask(StateEnergyEntry::N)
2346 | enumValueToBitMask(StateEnergyEntry::NumSteps)
2347 | enumValueToBitMask(StateEnergyEntry::NumStepsSim);
2348 if (enerhist->nsum > 0)
2350 headerContents.flags_enh |= (enumValueToBitMask(StateEnergyEntry::Aver)
2351 | enumValueToBitMask(StateEnergyEntry::Sum)
2352 | enumValueToBitMask(StateEnergyEntry::NumSum));
2354 if (enerhist->nsum_sim > 0)
2356 headerContents.flags_enh |= (enumValueToBitMask(StateEnergyEntry::SumSim)
2357 | enumValueToBitMask(StateEnergyEntry::NumSumSim));
2359 if (enerhist->deltaHForeignLambdas != nullptr)
2361 headerContents.flags_enh |= (enumValueToBitMask(StateEnergyEntry::DeltaHNN)
2362 | enumValueToBitMask(StateEnergyEntry::DeltaHList)
2363 | enumValueToBitMask(StateEnergyEntry::DeltaHStartTime)
2364 | enumValueToBitMask(StateEnergyEntry::DeltaHStartLambda));
2368 PullHistory* pullHist = observablesHistory->pullHistory.get();
2369 headerContents.flagsPullHistory = 0;
2370 if (pullHist != nullptr && (pullHist->numValuesInXSum > 0 || pullHist->numValuesInFSum > 0))
2372 headerContents.flagsPullHistory |= enumValueToBitMask(StatePullEntry::NumCoordinates);
2373 headerContents.flagsPullHistory |= (enumValueToBitMask(StatePullEntry::NumGroups)
2374 | enumValueToBitMask(StatePullEntry::NumValuesInXSum)
2375 | enumValueToBitMask(StatePullEntry::NumValuesInFSum));
2378 headerContents.flags_dfh = 0;
2381 headerContents.flags_dfh =
2382 (enumValueToBitMask(StateFepEntry::IsEquilibrated)
2383 | enumValueToBitMask(StateFepEntry::NumAtLambda)
2384 | enumValueToBitMask(StateFepEntry::SumWeights) | enumValueToBitMask(StateFepEntry::SumDG)
2385 | enumValueToBitMask(StateFepEntry::Tij) | enumValueToBitMask(StateFepEntry::TijEmp));
2388 headerContents.flags_dfh |= (enumValueToBitMask(StateFepEntry::WangLandauDelta)
2389 | enumValueToBitMask(StateFepEntry::WangLandauHistogram));
2391 if ((elamstats == LambdaWeightCalculation::Minvar) || (elamstats == LambdaWeightCalculation::Barker)
2392 || (elamstats == LambdaWeightCalculation::Metropolis))
2394 headerContents.flags_dfh |= (enumValueToBitMask(StateFepEntry::Accump)
2395 | enumValueToBitMask(StateFepEntry::Accumm)
2396 | enumValueToBitMask(StateFepEntry::Accump2)
2397 | enumValueToBitMask(StateFepEntry::Accumm2)
2398 | enumValueToBitMask(StateFepEntry::SumMinVar)
2399 | enumValueToBitMask(StateFepEntry::SumVar));
2403 headerContents.flags_awhh = 0;
2404 if (state->awhHistory != nullptr && !state->awhHistory->bias.empty())
2406 headerContents.flags_awhh |= (enumValueToBitMask(StateAwhEntry::InInitial)
2407 | enumValueToBitMask(StateAwhEntry::EquilibrateHistogram)
2408 | enumValueToBitMask(StateAwhEntry::HistogramSize)
2409 | enumValueToBitMask(StateAwhEntry::NumPoints)
2410 | enumValueToBitMask(StateAwhEntry::CoordPoint)
2411 | enumValueToBitMask(StateAwhEntry::UmbrellaGridPoint)
2412 | enumValueToBitMask(StateAwhEntry::UpdateList)
2413 | enumValueToBitMask(StateAwhEntry::LogScaledSampleWeight)
2414 | enumValueToBitMask(StateAwhEntry::NumUpdates)
2415 | enumValueToBitMask(StateAwhEntry::ForceCorrelationGrid));
2418 do_cpt_header(gmx_fio_getxdr(fp), FALSE, nullptr, &headerContents);
2420 if ((do_cpt_state(gmx_fio_getxdr(fp), state->flags, state, nullptr) < 0)
2421 || (do_cpt_ekinstate(gmx_fio_getxdr(fp), headerContents.flags_eks, &state->ekinstate, nullptr) < 0)
2422 || (do_cpt_enerhist(gmx_fio_getxdr(fp), FALSE, headerContents.flags_enh, enerhist, nullptr) < 0)
2423 || (doCptPullHist(gmx_fio_getxdr(fp), FALSE, headerContents.flagsPullHistory, pullHist, nullptr) < 0)
2424 || (do_cpt_df_hist(gmx_fio_getxdr(fp), headerContents.flags_dfh, headerContents.nlambda, &state->dfhist, nullptr)
2427 gmx_fio_getxdr(fp), FALSE, headerContents.nED, observablesHistory->edsamHistory.get(), nullptr)
2429 || (do_cpt_awh(gmx_fio_getxdr(fp), FALSE, headerContents.flags_awhh, state->awhHistory.get(), nullptr) < 0)
2430 || (do_cpt_swapstate(gmx_fio_getxdr(fp),
2432 headerContents.eSwapCoords,
2433 observablesHistory->swapHistory.get(),
2436 || (do_cpt_files(gmx_fio_getxdr(fp), FALSE, outputfiles, nullptr, headerContents.file_version) < 0))
2438 gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
2441 // Checkpointing MDModules
2443 gmx::KeyValueTreeBuilder builder;
2444 gmx::MDModulesWriteCheckpointData mdModulesWriteCheckpoint = { builder.rootObject(),
2445 headerContents.file_version };
2446 mdModulesNotifiers.checkpointingNotifier_.notify(mdModulesWriteCheckpoint);
2447 auto tree = builder.build();
2448 gmx::FileIOXdrSerializer serializer(fp);
2449 gmx::serializeKeyValueTree(tree, &serializer);
2452 // Checkpointing modular simulator
2454 gmx::FileIOXdrSerializer serializer(fp);
2455 modularSimulatorCheckpointData->serialize(&serializer);
2458 do_cpt_footer(gmx_fio_getxdr(fp), headerContents.file_version);
2460 /* Always FAH checkpoint immediately after a Gromacs checkpoint.
2462 * Note that it is critical that we save a FAH checkpoint directly
2463 * after writing a Gromacs checkpoint. If the program dies, either
2464 * by the machine powering off suddenly or the process being,
2465 * killed, FAH can recover files that have only appended data by
2466 * truncating them to the last recorded length. The Gromacs
2467 * checkpoint does not just append data, it is fully rewritten each
2468 * time so a crash between moving the new Gromacs checkpoint file in
2469 * to place and writing a FAH checkpoint is not recoverable. Thus
2470 * the time between these operations must be kept as short a
2477 static void check_int(FILE* fplog, const char* type, int p, int f, gmx_bool* mm)
2479 bool foundMismatch = (p != f);
2487 fprintf(fplog, " %s mismatch,\n", type);
2488 fprintf(fplog, " current program: %d\n", p);
2489 fprintf(fplog, " checkpoint file: %d\n", f);
2490 fprintf(fplog, "\n");
2494 static void check_string(FILE* fplog, const char* type, const char* p, const char* f, gmx_bool* mm)
2496 bool foundMismatch = (std::strcmp(p, f) != 0);
2504 fprintf(fplog, " %s mismatch,\n", type);
2505 fprintf(fplog, " current program: %s\n", p);
2506 fprintf(fplog, " checkpoint file: %s\n", f);
2507 fprintf(fplog, "\n");
2511 static void check_match(FILE* fplog,
2512 const t_commrec* cr,
2514 const CheckpointHeaderContents& headerContents,
2515 gmx_bool reproducibilityRequested)
2517 /* Note that this check_string on the version will also print a message
2518 * when only the minor version differs. But we only print a warning
2519 * message further down with reproducibilityRequested=TRUE.
2521 gmx_bool versionDiffers = FALSE;
2522 check_string(fplog, "Version", gmx_version(), headerContents.version, &versionDiffers);
2524 gmx_bool precisionDiffers = FALSE;
2525 check_int(fplog, "Double prec.", GMX_DOUBLE, headerContents.double_prec, &precisionDiffers);
2526 if (precisionDiffers)
2528 const char msg_precision_difference[] =
2529 "You are continuing a simulation with a different precision. Not matching\n"
2530 "mixed/double precision will lead to precision or performance loss.\n";
2533 fprintf(fplog, "%s\n", msg_precision_difference);
2537 gmx_bool mm = (versionDiffers || precisionDiffers);
2539 if (reproducibilityRequested)
2542 fplog, "Program name", gmx::getProgramContext().fullBinaryPath(), headerContents.fprog, &mm);
2544 check_int(fplog, "#ranks", cr->nnodes, headerContents.nnodes, &mm);
2547 if (cr->sizeOfDefaultCommunicator > 1 && reproducibilityRequested)
2549 // TODO: These checks are incorrect (see redmine #3309)
2550 check_int(fplog, "#PME-ranks", cr->npmenodes, headerContents.npme, &mm);
2552 int npp = cr->sizeOfDefaultCommunicator;
2553 if (cr->npmenodes >= 0)
2555 npp -= cr->npmenodes;
2557 int npp_f = headerContents.nnodes;
2558 if (headerContents.npme >= 0)
2560 npp_f -= headerContents.npme;
2564 check_int(fplog, "#DD-cells[x]", dd_nc[XX], headerContents.dd_nc[XX], &mm);
2565 check_int(fplog, "#DD-cells[y]", dd_nc[YY], headerContents.dd_nc[YY], &mm);
2566 check_int(fplog, "#DD-cells[z]", dd_nc[ZZ], headerContents.dd_nc[ZZ], &mm);
2572 /* Gromacs should be able to continue from checkpoints between
2573 * different patch level versions, but we do not guarantee
2574 * compatibility between different major/minor versions - check this.
2578 sscanf(gmx_version(), "%5d", &gmx_major);
2579 int ret = sscanf(headerContents.version, "%5d", &cpt_major);
2580 gmx_bool majorVersionDiffers = (ret < 1 || gmx_major != cpt_major);
2582 const char msg_major_version_difference[] =
2583 "The current GROMACS major version is not identical to the one that\n"
2584 "generated the checkpoint file. In principle GROMACS does not support\n"
2585 "continuation from checkpoints between different versions, so we advise\n"
2586 "against this. If you still want to try your luck we recommend that you use\n"
2587 "the -noappend flag to keep your output files from the two versions separate.\n"
2588 "This might also work around errors where the output fields in the energy\n"
2589 "file have changed between the different versions.\n";
2591 const char msg_mismatch_notice[] =
2592 "GROMACS patchlevel, binary or parallel settings differ from previous run.\n"
2593 "Continuation is exact, but not guaranteed to be binary identical.\n";
2595 if (majorVersionDiffers)
2599 fprintf(fplog, "%s\n", msg_major_version_difference);
2602 else if (reproducibilityRequested)
2604 /* Major & minor versions match at least, but something is different. */
2607 fprintf(fplog, "%s\n", msg_mismatch_notice);
2613 static void read_checkpoint(const char* fn,
2615 const t_commrec* cr,
2617 IntegrationAlgorithm eIntegrator,
2618 int* init_fep_state,
2619 CheckpointHeaderContents* headerContents,
2621 ObservablesHistory* observablesHistory,
2622 gmx_bool reproducibilityRequested,
2623 const gmx::MDModulesNotifiers& mdModulesNotifiers,
2624 gmx::ReadCheckpointDataHolder* modularSimulatorCheckpointData,
2625 bool useModularSimulator)
2628 char buf[STEPSTRSIZE];
2631 fp = gmx_fio_open(fn, "r");
2632 do_cpt_header(gmx_fio_getxdr(fp), TRUE, nullptr, headerContents);
2634 // If we are appending, then we don't want write to the open log
2635 // file because we still need to compute a checksum for it. In
2636 // that case, the filehandle will be nullptr. Otherwise, we report
2637 // to the new log file about the checkpoint file that we are
2639 FILE* fplog = gmx_fio_getfp(logfio);
2642 fprintf(fplog, "\n");
2643 fprintf(fplog, "Reading checkpoint file %s\n", fn);
2644 fprintf(fplog, " file generated by: %s\n", headerContents->fprog);
2645 fprintf(fplog, " file generated at: %s\n", headerContents->ftime);
2646 fprintf(fplog, " GROMACS double prec.: %d\n", headerContents->double_prec);
2647 fprintf(fplog, " simulation part #: %d\n", headerContents->simulation_part);
2648 fprintf(fplog, " step: %s\n", gmx_step_str(headerContents->step, buf));
2649 fprintf(fplog, " time: %f\n", headerContents->t);
2650 fprintf(fplog, "\n");
2653 if (headerContents->natoms != state->natoms)
2656 "Checkpoint file is for a system of %d atoms, while the current system consists "
2658 headerContents->natoms,
2661 if (headerContents->ngtc != state->ngtc)
2664 "Checkpoint file is for a system of %d T-coupling groups, while the current "
2665 "system consists of %d T-coupling groups",
2666 headerContents->ngtc,
2669 if (headerContents->nnhpres != state->nnhpres)
2672 "Checkpoint file is for a system of %d NH-pressure-coupling variables, while the "
2673 "current system consists of %d NH-pressure-coupling variables",
2674 headerContents->nnhpres,
2678 int nlambdaHistory = (state->dfhist ? state->dfhist->nlambda : 0);
2679 if (headerContents->nlambda != nlambdaHistory)
2682 "Checkpoint file is for a system with %d lambda states, while the current system "
2683 "consists of %d lambda states",
2684 headerContents->nlambda,
2688 init_gtc_state(state,
2691 headerContents->nhchainlength); /* need to keep this here to keep the tpr format working */
2692 /* write over whatever was read; we use the number of Nose-Hoover chains from the checkpoint */
2694 if (headerContents->eIntegrator != eIntegrator)
2697 "Cannot change integrator during a checkpoint restart. Perhaps you should make a "
2698 "new .tpr with grompp -f new.mdp -t %s",
2702 // For modular simulator, no state object is populated, so we cannot do this check here!
2703 if (headerContents->flags_state != state->flags && !useModularSimulator)
2706 "Cannot change a simulation algorithm during a checkpoint restart. Perhaps you "
2707 "should make a new .tpr with grompp -f new.mdp -t %s",
2711 GMX_RELEASE_ASSERT(!(headerContents->isModularSimulatorCheckpoint && !useModularSimulator),
2712 "Checkpoint file was written by modular simulator, but the current "
2713 "simulation uses the legacy simulator.\n\n"
2714 "Try the following steps:\n"
2715 "1. Make sure the GMX_DISABLE_MODULAR_SIMULATOR environment variable is not "
2716 "set to return to the default behavior. Retry running the simulation.\n"
2717 "2. If the problem persists, set the environment variable "
2718 "GMX_USE_MODULAR_SIMULATOR=ON to overwrite the default behavior and use "
2719 "modular simulator for all implemented use cases.");
2720 GMX_RELEASE_ASSERT(!(!headerContents->isModularSimulatorCheckpoint && useModularSimulator),
2721 "Checkpoint file was written by legacy simulator, but the current "
2722 "simulation uses the modular simulator.\n\n"
2723 "Try the following steps:\n"
2724 "1. Make sure the GMX_USE_MODULAR_SIMULATOR environment variable is not set "
2725 "to return to the default behavior. Retry running the simulation.\n"
2726 "2. If the problem persists, set the environment variable "
2727 "GMX_DISABLE_MODULAR_SIMULATOR=ON to overwrite the default behavior and use "
2728 "legacy simulator for all implemented use cases.");
2732 check_match(fplog, cr, dd_nc, *headerContents, reproducibilityRequested);
2735 ret = do_cpt_state(gmx_fio_getxdr(fp), headerContents->flags_state, state, nullptr);
2736 *init_fep_state = state->fep_state; /* there should be a better way to do this than setting it
2737 here. Investigate for 5.0. */
2742 ret = do_cpt_ekinstate(gmx_fio_getxdr(fp), headerContents->flags_eks, &state->ekinstate, nullptr);
2747 state->ekinstate.hasReadEkinState =
2748 (((headerContents->flags_eks & enumValueToBitMask(StateKineticEntry::EkinHalfStep)) != 0)
2749 || ((headerContents->flags_eks & enumValueToBitMask(StateKineticEntry::EkinFullStep)) != 0)
2750 || ((headerContents->flags_eks & enumValueToBitMask(StateKineticEntry::EkinHalfStepOld)) != 0)
2751 || (((headerContents->flags_eks & enumValueToBitMask(StateKineticEntry::EkinNoseHooverScaleFullStep))
2752 | (headerContents->flags_eks & enumValueToBitMask(StateKineticEntry::EkinNoseHooverScaleHalfStep))
2753 | (headerContents->flags_eks & enumValueToBitMask(StateKineticEntry::VelocityScale)))
2756 if (headerContents->flags_enh && observablesHistory->energyHistory == nullptr)
2758 observablesHistory->energyHistory = std::make_unique<energyhistory_t>();
2760 ret = do_cpt_enerhist(
2761 gmx_fio_getxdr(fp), TRUE, headerContents->flags_enh, observablesHistory->energyHistory.get(), nullptr);
2767 if (headerContents->flagsPullHistory)
2769 if (observablesHistory->pullHistory == nullptr)
2771 observablesHistory->pullHistory = std::make_unique<PullHistory>();
2773 ret = doCptPullHist(gmx_fio_getxdr(fp),
2775 headerContents->flagsPullHistory,
2776 observablesHistory->pullHistory.get(),
2784 if (headerContents->file_version < CheckPointVersion::Version45)
2787 "Continuing from checkpoint files written before GROMACS 4.5 is not supported");
2790 ret = do_cpt_df_hist(
2791 gmx_fio_getxdr(fp), headerContents->flags_dfh, headerContents->nlambda, &state->dfhist, nullptr);
2797 if (headerContents->nED > 0 && observablesHistory->edsamHistory == nullptr)
2799 observablesHistory->edsamHistory = std::make_unique<edsamhistory_t>(edsamhistory_t{});
2801 ret = do_cpt_EDstate(
2802 gmx_fio_getxdr(fp), TRUE, headerContents->nED, observablesHistory->edsamHistory.get(), nullptr);
2808 if (headerContents->flags_awhh != 0 && state->awhHistory == nullptr)
2810 state->awhHistory = std::make_shared<gmx::AwhHistory>();
2812 ret = do_cpt_awh(gmx_fio_getxdr(fp), TRUE, headerContents->flags_awhh, state->awhHistory.get(), nullptr);
2818 if (headerContents->eSwapCoords != SwapType::No && observablesHistory->swapHistory == nullptr)
2820 observablesHistory->swapHistory = std::make_unique<swaphistory_t>(swaphistory_t{});
2822 ret = do_cpt_swapstate(
2823 gmx_fio_getxdr(fp), TRUE, headerContents->eSwapCoords, observablesHistory->swapHistory.get(), nullptr);
2829 std::vector<gmx_file_position_t> outputfiles;
2830 ret = do_cpt_files(gmx_fio_getxdr(fp), TRUE, &outputfiles, nullptr, headerContents->file_version);
2835 do_cpt_mdmodules(headerContents->file_version, fp, mdModulesNotifiers, nullptr);
2836 if (headerContents->file_version >= CheckPointVersion::ModularSimulator)
2838 gmx::FileIOXdrSerializer serializer(fp);
2839 modularSimulatorCheckpointData->deserialize(&serializer);
2841 ret = do_cpt_footer(gmx_fio_getxdr(fp), headerContents->file_version);
2846 if (gmx_fio_close(fp) != 0)
2848 gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
2853 void load_checkpoint(const char* fn,
2855 const t_commrec* cr,
2859 ObservablesHistory* observablesHistory,
2860 gmx_bool reproducibilityRequested,
2861 const gmx::MDModulesNotifiers& mdModulesNotifiers,
2862 gmx::ReadCheckpointDataHolder* modularSimulatorCheckpointData,
2863 bool useModularSimulator)
2865 CheckpointHeaderContents headerContents;
2868 /* Read the state from the checkpoint file */
2874 &(ir->fepvals->init_fep_state),
2878 reproducibilityRequested,
2880 modularSimulatorCheckpointData,
2881 useModularSimulator);
2885 gmx_bcast(sizeof(headerContents.step), &headerContents.step, cr->mpiDefaultCommunicator);
2886 gmx::MDModulesCheckpointReadingBroadcast broadcastCheckPointData = {
2887 cr->mpiDefaultCommunicator, PAR(cr), headerContents.file_version
2889 mdModulesNotifiers.checkpointingNotifier_.notify(broadcastCheckPointData);
2891 ir->bContinuation = TRUE;
2892 if (ir->nsteps >= 0)
2894 // TODO Should the following condition be <=? Currently if you
2895 // pass a checkpoint written by an normal completion to a restart,
2896 // mdrun will read all input, does some work but no steps, and
2897 // write successful output. But perhaps that is not desirable.
2898 // Note that we do not intend to support the use of mdrun
2899 // -nsteps to circumvent this condition.
2900 if (ir->nsteps + ir->init_step < headerContents.step)
2902 char buf[STEPSTRSIZE];
2903 std::string message =
2904 gmx::formatString("The input requested %s steps, ", gmx_step_str(ir->nsteps, buf));
2905 if (ir->init_step > 0)
2907 message += gmx::formatString("starting from step %s, ", gmx_step_str(ir->init_step, buf));
2909 message += gmx::formatString(
2910 "however the checkpoint "
2911 "file has already reached step %s. The simulation will not "
2912 "proceed, because either your simulation is already complete, "
2913 "or your combination of input files don't match.",
2914 gmx_step_str(headerContents.step, buf));
2915 gmx_fatal(FARGS, "%s", message.c_str());
2917 ir->nsteps += ir->init_step - headerContents.step;
2919 ir->init_step = headerContents.step;
2920 ir->simulation_part = headerContents.simulation_part + 1;
2923 void read_checkpoint_part_and_step(const char* filename, int* simulation_part, int64_t* step)
2927 if (filename == nullptr || !gmx_fexist(filename) || ((fp = gmx_fio_open(filename, "r")) == nullptr))
2929 *simulation_part = 0;
2934 CheckpointHeaderContents headerContents;
2935 do_cpt_header(gmx_fio_getxdr(fp), TRUE, nullptr, &headerContents);
2937 *simulation_part = headerContents.simulation_part;
2938 *step = headerContents.step;
2941 static CheckpointHeaderContents read_checkpoint_data(t_fileio* fp,
2943 std::vector<gmx_file_position_t>* outputfiles,
2944 gmx::ReadCheckpointDataHolder* modularSimulatorCheckpointData)
2946 CheckpointHeaderContents headerContents;
2947 do_cpt_header(gmx_fio_getxdr(fp), TRUE, nullptr, &headerContents);
2948 state->natoms = headerContents.natoms;
2949 state->ngtc = headerContents.ngtc;
2950 state->nnhpres = headerContents.nnhpres;
2951 state->nhchainlength = headerContents.nhchainlength;
2952 state->flags = headerContents.flags_state;
2953 int ret = do_cpt_state(gmx_fio_getxdr(fp), state->flags, state, nullptr);
2958 ret = do_cpt_ekinstate(gmx_fio_getxdr(fp), headerContents.flags_eks, &state->ekinstate, nullptr);
2964 energyhistory_t enerhist;
2965 ret = do_cpt_enerhist(gmx_fio_getxdr(fp), TRUE, headerContents.flags_enh, &enerhist, nullptr);
2970 PullHistory pullHist = {};
2971 ret = doCptPullHist(gmx_fio_getxdr(fp), TRUE, headerContents.flagsPullHistory, &pullHist, nullptr);
2977 ret = do_cpt_df_hist(
2978 gmx_fio_getxdr(fp), headerContents.flags_dfh, headerContents.nlambda, &state->dfhist, nullptr);
2984 edsamhistory_t edsamhist = {};
2985 ret = do_cpt_EDstate(gmx_fio_getxdr(fp), TRUE, headerContents.nED, &edsamhist, nullptr);
2991 ret = do_cpt_awh(gmx_fio_getxdr(fp), TRUE, headerContents.flags_awhh, state->awhHistory.get(), nullptr);
2997 swaphistory_t swaphist = {};
2998 ret = do_cpt_swapstate(gmx_fio_getxdr(fp), TRUE, headerContents.eSwapCoords, &swaphist, nullptr);
3004 ret = do_cpt_files(gmx_fio_getxdr(fp), TRUE, outputfiles, nullptr, headerContents.file_version);
3010 gmx::MDModulesNotifiers mdModuleNotifiers;
3011 do_cpt_mdmodules(headerContents.file_version, fp, mdModuleNotifiers, nullptr);
3012 if (headerContents.file_version >= CheckPointVersion::ModularSimulator)
3014 // Store modular checkpoint data into modularSimulatorCheckpointData
3015 gmx::FileIOXdrSerializer serializer(fp);
3016 modularSimulatorCheckpointData->deserialize(&serializer);
3018 ret = do_cpt_footer(gmx_fio_getxdr(fp), headerContents.file_version);
3023 return headerContents;
3026 void read_checkpoint_trxframe(t_fileio* fp, t_trxframe* fr)
3029 std::vector<gmx_file_position_t> outputfiles;
3030 gmx::ReadCheckpointDataHolder modularSimulatorCheckpointData;
3031 CheckpointHeaderContents headerContents =
3032 read_checkpoint_data(fp, &state, &outputfiles, &modularSimulatorCheckpointData);
3033 if (headerContents.isModularSimulatorCheckpoint)
3035 gmx::ModularSimulator::readCheckpointToTrxFrame(fr, &modularSimulatorCheckpointData, headerContents);
3039 fr->natoms = state.natoms;
3041 fr->step = int64_to_int(headerContents.step, "conversion of checkpoint to trajectory");
3043 fr->time = headerContents.t;
3045 fr->lambda = state.lambda[FreeEnergyPerturbationCouplingType::Fep];
3046 fr->fep_state = state.fep_state;
3048 fr->bX = ((state.flags & enumValueToBitMask(StateEntry::X)) != 0);
3051 fr->x = makeRvecArray(state.x, state.natoms);
3053 fr->bV = ((state.flags & enumValueToBitMask(StateEntry::V)) != 0);
3056 fr->v = makeRvecArray(state.v, state.natoms);
3059 fr->bBox = ((state.flags & enumValueToBitMask(StateEntry::Box)) != 0);
3062 copy_mat(state.box, fr->box);
3066 void list_checkpoint(const char* fn, FILE* out)
3073 fp = gmx_fio_open(fn, "r");
3074 CheckpointHeaderContents headerContents;
3075 do_cpt_header(gmx_fio_getxdr(fp), TRUE, out, &headerContents);
3076 state.natoms = headerContents.natoms;
3077 state.ngtc = headerContents.ngtc;
3078 state.nnhpres = headerContents.nnhpres;
3079 state.nhchainlength = headerContents.nhchainlength;
3080 state.flags = headerContents.flags_state;
3081 ret = do_cpt_state(gmx_fio_getxdr(fp), state.flags, &state, out);
3086 ret = do_cpt_ekinstate(gmx_fio_getxdr(fp), headerContents.flags_eks, &state.ekinstate, out);
3092 energyhistory_t enerhist;
3093 ret = do_cpt_enerhist(gmx_fio_getxdr(fp), TRUE, headerContents.flags_enh, &enerhist, out);
3097 PullHistory pullHist = {};
3098 ret = doCptPullHist(gmx_fio_getxdr(fp), TRUE, headerContents.flagsPullHistory, &pullHist, out);
3103 ret = do_cpt_df_hist(
3104 gmx_fio_getxdr(fp), headerContents.flags_dfh, headerContents.nlambda, &state.dfhist, out);
3109 edsamhistory_t edsamhist = {};
3110 ret = do_cpt_EDstate(gmx_fio_getxdr(fp), TRUE, headerContents.nED, &edsamhist, out);
3115 ret = do_cpt_awh(gmx_fio_getxdr(fp), TRUE, headerContents.flags_awhh, state.awhHistory.get(), out);
3120 swaphistory_t swaphist = {};
3121 ret = do_cpt_swapstate(gmx_fio_getxdr(fp), TRUE, headerContents.eSwapCoords, &swaphist, out);
3126 std::vector<gmx_file_position_t> outputfiles;
3127 ret = do_cpt_files(gmx_fio_getxdr(fp), TRUE, &outputfiles, out, headerContents.file_version);
3129 gmx::MDModulesNotifiers mdModuleNotifiers;
3130 do_cpt_mdmodules(headerContents.file_version, fp, mdModuleNotifiers, out);
3131 if (headerContents.file_version >= CheckPointVersion::ModularSimulator)
3133 gmx::FileIOXdrSerializer serializer(fp);
3134 gmx::ReadCheckpointDataHolder modularSimulatorCheckpointData;
3135 modularSimulatorCheckpointData.deserialize(&serializer);
3136 modularSimulatorCheckpointData.dump(out);
3141 ret = do_cpt_footer(gmx_fio_getxdr(fp), headerContents.file_version);
3148 if (gmx_fio_close(fp) != 0)
3150 gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
3154 /* This routine cannot print tons of data, since it is called before the log file is opened. */
3155 CheckpointHeaderContents read_checkpoint_simulation_part_and_filenames(t_fileio* fp,
3156 std::vector<gmx_file_position_t>* outputfiles)
3159 gmx::ReadCheckpointDataHolder modularSimulatorCheckpointData;
3160 CheckpointHeaderContents headerContents =
3161 read_checkpoint_data(fp, &state, outputfiles, &modularSimulatorCheckpointData);
3162 if (gmx_fio_close(fp) != 0)
3164 gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
3166 return headerContents;