t_fileio *fio,
bool TopOnlyOK)
{
- gmx_bool bDouble;
int precision;
int idum = 0;
real rdum = 0;
" Make a new one with grompp or use a gro or pdb file, if possible",
filename);
}
+ // We need to know the precision used to write the TPR file, to match it
+ // to the precision of the currently running binary. If the precisions match
+ // there is no problem, but mismatching precision needs to be accounted for
+ // by reading into temporary variables of the correct precision instead
+ // of the desired target datastructures.
serializer->doInt(&precision);
- bDouble = (precision == sizeof(double));
- if ((precision != sizeof(float)) && !bDouble)
+ tpx->isDouble = (precision == sizeof(double));
+ if ((precision != sizeof(float)) && !tpx->isDouble)
{
gmx_fatal(FARGS, "Unknown precision in file %s: real is %d bytes "
"instead of %zu or %zu",
filename, precision, sizeof(float), sizeof(double));
}
- gmx_fio_setprecision(fio, bDouble);
+ gmx_fio_setprecision(fio, tpx->isDouble);
fprintf(stderr, "Reading file %s, %s (%s precision)\n",
- filename, buf.c_str(), bDouble ? "double" : "single");
+ filename, buf.c_str(), tpx->isDouble ? "double" : "single");
}
else
{
buf = gmx::formatString("VERSION %s", gmx_version());
serializer->doString(&buf);
- bDouble = (precision == sizeof(double));
- gmx_fio_setprecision(fio, bDouble);
+ gmx_fio_setprecision(fio, tpx->isDouble);
serializer->doInt(&precision);
fileTag = gmx::formatString("%s", tpx_tag);
}
#define do_test(serializer, b, p) if ((serializer)->reading() && ((p) != nullptr) && !(b)) gmx_fatal(FARGS, "No %s in input file",#p)
+/*! \brief
+ * Process the first part of the TPR into the state datastructure.
+ *
+ * Due to the structure of the legacy code, it is necessary
+ * to split up the state reading into two parts, with the
+ * box and legacy temperature coupling processed before the
+ * topology datastructures.
+ *
+ * See the documentation for do_tpx_body for the correct order of
+ * the operations for reading a tpr file.
+ *
+ * \param[in] serializer Abstract serializer used to read/write data.
+ * \param[in] tpx The file header data.
+ * \param[in, out] state Global state data.
+ */
static void do_tpx_state_first(gmx::ISerializer *serializer,
TpxFileHeader *tpx,
t_state *state)
}
}
+/*! \brief
+ * Process global topology data.
+ *
+ * See the documentation for do_tpx_body for the correct order of
+ * the operations for reading a tpr file.
+ *
+ * \param[in] serializer Abstract serializer used to read/write data.
+ * \param[in] tpx The file header data.
+ * \param[in,out] mtop Global topology.
+ */
static void do_tpx_mtop(gmx::ISerializer *serializer,
TpxFileHeader *tpx,
gmx_mtop_t *mtop)
}
}
}
-
+/*! \brief
+ * Process coordinate vectors for state data.
+ *
+ * Main part of state gets processed here.
+ *
+ * See the documentation for do_tpx_body for the correct order of
+ * the operations for reading a tpr file.
+ *
+ * \param[in] serializer Abstract serializer used to read/write data.
+ * \param[in] tpx The file header data.
+ * \param[in,out] state Global state data.
+ * \param[in,out] x Individual coordinates for processing, deprecated.
+ * \param[in,out] v Individual velocities for processing, deprecated.
+ */
static void do_tpx_state_second(gmx::ISerializer *serializer,
TpxFileHeader *tpx,
t_state *state,
serializer->doRvecArray(as_rvec_array(dummyForces.data()), tpx->natoms);
}
}
-
+/*! \brief
+ * Process simulation parameters.
+ *
+ * See the documentation for do_tpx_body for the correct order of
+ * the operations for reading a tpr file.
+ *
+ * \param[in] serializer Abstract serializer used to read/write data.
+ * \param[in] tpx The file header data.
+ * \param[in,out] ir Datastructure with simulation parameters.
+ */
static int do_tpx_ir(gmx::ISerializer *serializer,
TpxFileHeader *tpx,
t_inputrec *ir)
/*! \brief
* Correct and finalize read information.
*
- * Moved here from previous code because this is done after reading files.
+ * If \p state is nullptr, skip the parts dependent on it.
+ *
+ * See the documentation for do_tpx_body for the correct order of
+ * the operations for reading a tpr file.
*
* \param[in] tpx The file header used to check version numbers.
* \param[out] ir Input rec that needs correction.
t_state *state,
gmx_mtop_t *mtop)
{
- if (tpx->fileVersion < 51)
+ if (tpx->fileVersion < 51 && state)
{
set_box_rel(ir, state);
}
if (tpx->bIr && ir)
{
- if (state->ngtc == 0)
+ if (state && state->ngtc == 0)
{
/* Reading old version without tcoupl state data: set it */
init_gtc_state(state, ir->opts.ngtc, 0, ir->opts.nhchainlength);
}
}
+/*! \brief
+ * Process TPR data for file reading/writing.
+ *
+ * The TPR file gets processed in in four stages due to the organization
+ * of the data within it.
+ *
+ * First, state data for the box is processed in do_tpx_state_first.
+ * This is followed by processing the topology in do_tpx_mtop.
+ * Coordinate and velocity vectors are handled next in do_tpx_state_second.
+ * The last file information processed is the collection of simulation parameters in do_tpx_ir.
+ * When reading, a final processing step is undertaken at the end.
+ *
+ * \param[in] serializer Abstract serializer used to read/write data.
+ * \param[in] tpx The file header data.
+ * \param[in,out] ir Datastructures with simulation parameters.
+ * \param[in,out] state Global state data.
+ * \param[in,out] x Individual coordinates for processing, deprecated.
+ * \param[in,out] v Individual velocities for processing, deprecated.
+ * \param[in,out] mtop Global topology.
+ */
static int do_tpx_body(gmx::ISerializer *serializer,
TpxFileHeader *tpx,
t_inputrec *ir,
rvec *v,
gmx_mtop_t *mtop)
{
- do_tpx_state_first(serializer, tpx, state);
+ if (state)
+ {
+ do_tpx_state_first(serializer, tpx, state);
+ }
do_tpx_mtop(serializer, tpx, mtop);
- do_tpx_state_second(serializer, tpx, state, x, v);
+ if (state)
+ {
+ do_tpx_state_second(serializer, tpx, state, x, v);
+ }
int ePBC = do_tpx_ir(serializer, tpx, ir);
if (serializer->reading())
{
return ePBC;
}
+/*! \brief
+ * Overload for do_tpx_body that defaults to state vectors being nullptr.
+ *
+ * \param[in] serializer Abstract serializer used to read/write data.
+ * \param[in] tpx The file header data.
+ * \param[in,out] ir Datastructures with simulation parameters.
+ * \param[in,out] mtop Global topology.
+ */
+static int do_tpx_body(gmx::ISerializer *serializer,
+ TpxFileHeader *tpx,
+ t_inputrec *ir,
+ gmx_mtop_t *mtop)
+{
+ return do_tpx_body(serializer, tpx, ir, nullptr, nullptr, nullptr, mtop);
+}
+
static t_fileio *open_tpx(const char *fn, const char *mode)
{
return gmx_fio_open(fn, mode);
header.bBox = true;
header.fileVersion = tpx_version;
header.fileGeneration = tpx_generation;
+ header.isDouble = (sizeof(real) == sizeof(double));
return header;
}
-static void doTpxBodyBuffer(gmx::ISerializer *topologySerializer, gmx::ArrayRef<char> buffer)
+/*! \brief
+ * Process the body of a TPR file as char buffer.
+ *
+ * Reads/writes the information in \p buffer from/to the \p serializer
+ * provided to the function. Does not interact with the actual
+ * TPR datastructures but with an in memory representation of the
+ * data, so that this data can be efficiently read or written from/to
+ * an original source.
+ *
+ * \param[in] serializer The abstract serializer used for reading or writing
+ * the information in \p buffer.
+ * \param[in,out] buffer Information from TPR file as char buffer.
+ */
+static void doTpxBodyBuffer(gmx::ISerializer *serializer, gmx::ArrayRef<char> buffer)
+{
+ serializer->doCharArray(buffer.data(), buffer.size());
+}
+
+/*! \brief
+ * Populates simulation datastructures.
+ *
+ * Here the information from the serialization interface \p serializer
+ * is used to first populate the datastructures containing the simulation
+ * information. Depending on the version found in the header \p tpx,
+ * this is done using the new reading of the data as one block from disk,
+ * followed by complete deserialization of the information read from there.
+ * Otherwise, the datastructures are populated as before one by one from disk.
+ * The second version is the default for the legacy tools that read the
+ * coordinates and velocities separate from the state.
+ *
+ * After reading in the data, a separate buffer is populated from them
+ * containing only \p ir and \p mtop that can be communicated directly
+ * to nodes needing the information to set up a simulation.
+ *
+ * \param[in] tpx The file header.
+ * \param[in] serializer The Serialization interface used to read the TPR.
+ * \param[out] ir Input rec to populate.
+ * \param[out] state State vectors to populate.
+ * \param[out] x Coordinates to populate if needed.
+ * \param[out] v Velocities to populate if needed.
+ * \param[out] mtop Global topology to populate.
+ *
+ * \returns Partial de-serialized TPR used for communication to nodes.
+ */
+static PartialDeserializedTprFile readTpxBody(TpxFileHeader *tpx,
+ gmx::ISerializer *serializer,
+ t_inputrec *ir,
+ t_state *state,
+ rvec *x, rvec *v,
+ gmx_mtop_t *mtop)
{
- topologySerializer->doCharArray(buffer.data(), buffer.size());
+ PartialDeserializedTprFile partialDeserializedTpr;
+ if (tpx->fileVersion >= tpxv_AddSizeField && tpx->fileGeneration >= 27)
+ {
+ partialDeserializedTpr.body.resize(tpx->sizeOfTprBody);
+ partialDeserializedTpr.header = *tpx;
+ doTpxBodyBuffer(serializer, partialDeserializedTpr.body);
+
+ partialDeserializedTpr.ePBC =
+ completeTprDeserialization(&partialDeserializedTpr,
+ ir,
+ state,
+ x, v,
+ mtop);
+ }
+ else
+ {
+ partialDeserializedTpr.ePBC =
+ do_tpx_body(serializer,
+ tpx,
+ ir,
+ state,
+ x,
+ v,
+ mtop);
+ }
+ // Update header to system info for communication to nodes.
+ // As we only need to communicate the inputrec and mtop to other nodes,
+ // we prepare a new char buffer with the information we have already read
+ // in on master.
+ partialDeserializedTpr.header = populateTpxHeader(*state, ir, mtop);
+ gmx::InMemorySerializer tprBodySerializer;
+ do_tpx_body(&tprBodySerializer,
+ &partialDeserializedTpr.header,
+ ir,
+ mtop);
+ partialDeserializedTpr.body = tprBodySerializer.finishAndGetBuffer();
+
+ return partialDeserializedTpr;
}
/************************************************************
close_tpx(fio);
}
-/*! \brief
- * Wraps reading of header before and after introduction of size field.
- *
- * \param[in] tpx The file header.
- * \param[in] serializer The Serialization interface used to read the TPR.
- * \param[in] isDouble Whether the file is double or single precision.
- * \param[out] ir Input rec to populate.
- * \param[out] state State vectors to populate.
- * \param[out] x Coordinates to populate if needed.
- * \param[out] v Velocities to populate if needed.
- * \param[out] mtop Global topology to populate.
- *
- * \returns Flag for pbc.
- */
-static int do_tpx_body_dispatcher(TpxFileHeader *tpx,
- gmx::ISerializer *serializer,
- bool isDouble,
- t_inputrec *ir,
- t_state *state,
- rvec *x, rvec *v,
- gmx_mtop_t *mtop)
+int completeTprDeserialization(PartialDeserializedTprFile *partialDeserializedTpr,
+ t_inputrec *ir,
+ t_state *state,
+ rvec *x,
+ rvec *v,
+ gmx_mtop_t *mtop)
{
- int ePBC;
- if (tpx->fileVersion >= tpxv_AddSizeField && tpx->fileGeneration >= 27)
- {
- std::vector<char> tprBody(tpx->sizeOfTprBody);
- doTpxBodyBuffer(serializer, tprBody);
- gmx::InMemoryDeserializer tprBodyDeserializer(tprBody, isDouble);
-
- ePBC = do_tpx_body(&tprBodyDeserializer,
- tpx,
- ir,
- state,
- x,
- v,
- mtop);
- }
- else
- {
- ePBC = do_tpx_body(serializer,
- tpx,
- ir,
- state,
- x,
- v,
- mtop);
- }
- return ePBC;
+ gmx::InMemoryDeserializer tprBodyDeserializer(partialDeserializedTpr->body,
+ partialDeserializedTpr->header.isDouble);
+ return do_tpx_body(&tprBodyDeserializer,
+ &partialDeserializedTpr->header,
+ ir,
+ state,
+ x,
+ v,
+ mtop);
}
-
-void read_tpx_state(const char *fn,
- t_inputrec *ir, t_state *state, gmx_mtop_t *mtop)
+int completeTprDeserialization(PartialDeserializedTprFile *partialDeserializedTpr,
+ t_inputrec *ir,
+ gmx_mtop_t *mtop)
{
- t_fileio *fio;
+ return completeTprDeserialization(partialDeserializedTpr, ir, nullptr, nullptr, nullptr, mtop);
+}
- TpxFileHeader tpx;
+PartialDeserializedTprFile read_tpx_state(const char *fn,
+ t_inputrec *ir,
+ t_state *state,
+ gmx_mtop_t *mtop)
+{
+ t_fileio *fio;
fio = open_tpx(fn, "r");
- gmx::FileIOXdrSerializer serializer(fio);
+ gmx::FileIOXdrSerializer serializer(fio);
+ PartialDeserializedTprFile partialDeserializedTpr;
do_tpxheader(&serializer,
- &tpx,
+ &partialDeserializedTpr.header,
fn,
fio,
ir == nullptr);
- do_tpx_body_dispatcher(&tpx, &serializer, gmx_fio_is_double(fio),
- ir, state, nullptr, nullptr, mtop);
+ partialDeserializedTpr = readTpxBody(&partialDeserializedTpr.header,
+ &serializer,
+ ir,
+ state,
+ nullptr,
+ nullptr,
+ mtop);
close_tpx(fio);
+ return partialDeserializedTpr;
}
int read_tpx(const char *fn,
{
t_fileio *fio;
t_state state;
- int ePBC;
TpxFileHeader tpx;
fio = open_tpx(fn, "r");
fn,
fio,
ir == nullptr);
- ePBC = do_tpx_body_dispatcher(&tpx, &serializer, gmx_fio_is_double(fio),
- ir, &state, x, v, mtop);
+ PartialDeserializedTprFile partialDeserializedTpr
+ = readTpxBody(&tpx, &serializer,
+ ir, &state, x, v, mtop);
close_tpx(fio);
if (mtop != nullptr && natoms != nullptr)
{
{
copy_mat(state.box, box);
}
- return ePBC;
+ return partialDeserializedTpr.ePBC;
}
int read_tpx_top(const char *fn,
#include "broadcaststructs.h"
-#include <cstring>
-
-#include <memory>
-
+#include "gromacs/fileio/tpxio.h"
#include "gromacs/gmxlib/network.h"
-#include "gromacs/math/vec.h"
-#include "gromacs/mdlib/tgroup.h"
-#include "gromacs/mdtypes/awh_params.h"
#include "gromacs/mdtypes/commrec.h"
-#include "gromacs/mdtypes/inputrec.h"
-#include "gromacs/mdtypes/md_enums.h"
-#include "gromacs/mdtypes/pull_params.h"
#include "gromacs/mdtypes/state.h"
-#include "gromacs/topology/mtop_util.h"
-#include "gromacs/topology/symtab.h"
-#include "gromacs/topology/topology.h"
-#include "gromacs/utility/fatalerror.h"
-#include "gromacs/utility/inmemoryserializer.h"
-#include "gromacs/utility/keyvaluetree.h"
-#include "gromacs/utility/keyvaluetreeserializer.h"
-#include "gromacs/utility/smalloc.h"
-
-static void bc_cstring(const t_commrec *cr, char **s)
-{
- int size = 0;
-
- if (MASTER(cr) && *s != nullptr)
- {
- /* Size of the char buffer is string length + 1 for '\0' */
- size = strlen(*s) + 1;
- }
- block_bc(cr, size);
- if (size > 0)
- {
- if (!MASTER(cr))
- {
- srenew(*s, size);
- }
- nblock_bc(cr, size, *s);
- }
- else if (!MASTER(cr) && *s != nullptr)
- {
- sfree(*s);
- *s = nullptr;
- }
-}
-
-static void bc_string(const t_commrec *cr, t_symtab *symtab, char ***s)
-{
- int handle;
-
- if (MASTER(cr))
- {
- handle = lookup_symtab(symtab, *s);
- }
- block_bc(cr, handle);
- if (!MASTER(cr))
- {
- *s = get_symtab_handle(symtab, handle);
- }
-}
-
-static void bc_strings(const t_commrec *cr, t_symtab *symtab, int nr, char ****nm)
-{
- int i;
- int *handle;
-
- snew(handle, nr);
- if (MASTER(cr))
- {
- for (i = 0; (i < nr); i++)
- {
- handle[i] = lookup_symtab(symtab, (*nm)[i]);
- }
- }
- nblock_bc(cr, nr, handle);
-
- if (!MASTER(cr))
- {
- snew_bc(cr, *nm, nr);
- for (i = 0; (i < nr); i++)
- {
- (*nm)[i] = get_symtab_handle(symtab, handle[i]);
- }
- }
- sfree(handle);
-}
-
-static void bc_strings_container(const t_commrec *cr,
- t_symtab *symtab,
- int nr,
- std::vector<char **> *nm)
-{
- std::vector<int> handle;
- if (MASTER(cr))
- {
- for (int i = 0; (i < nr); i++)
- {
- handle.emplace_back(lookup_symtab(symtab, (*nm)[i]));
- }
- }
- block_bc(cr, nr);
- nblock_abc(cr, nr, &handle);
-
- if (!MASTER(cr))
- {
- nm->resize(nr);
- for (int i = 0; (i < nr); i++)
- {
- (*nm)[i] = get_symtab_handle(symtab, handle[i]);
- }
- }
-}
-
-static void bc_strings_resinfo(const t_commrec *cr, t_symtab *symtab,
- int nr, t_resinfo *resinfo)
-{
- int i;
- int *handle;
-
- snew(handle, nr);
- if (MASTER(cr))
- {
- for (i = 0; (i < nr); i++)
- {
- handle[i] = lookup_symtab(symtab, resinfo[i].name);
- }
- }
- nblock_bc(cr, nr, handle);
-
- if (!MASTER(cr))
- {
- for (i = 0; (i < nr); i++)
- {
- resinfo[i].name = get_symtab_handle(symtab, handle[i]);
- }
- }
- sfree(handle);
-}
-
-static void bc_symtab(const t_commrec *cr, t_symtab *symtab)
-{
- int i, nr, len;
- t_symbuf *symbuf;
-
- block_bc(cr, symtab->nr);
- nr = symtab->nr;
- snew_bc(cr, symtab->symbuf, 1);
- symbuf = symtab->symbuf;
- symbuf->bufsize = nr;
- snew_bc(cr, symbuf->buf, nr);
- for (i = 0; i < nr; i++)
- {
- if (MASTER(cr))
- {
- len = strlen(symbuf->buf[i]) + 1;
- }
- block_bc(cr, len);
- snew_bc(cr, symbuf->buf[i], len);
- nblock_bc(cr, len, symbuf->buf[i]);
- }
-}
-
-static void bc_block(const t_commrec *cr, t_block *block)
-{
- block_bc(cr, block->nr);
- snew_bc(cr, block->index, block->nr+1);
- nblock_bc(cr, block->nr+1, block->index);
-}
-
-static void bc_blocka(const t_commrec *cr, t_blocka *block)
-{
- block_bc(cr, block->nr);
- snew_bc(cr, block->index, block->nr+1);
- nblock_bc(cr, block->nr+1, block->index);
- block_bc(cr, block->nra);
- if (block->nra)
- {
- snew_bc(cr, block->a, block->nra);
- nblock_bc(cr, block->nra, block->a);
- }
-}
-
-static void bc_grps(const t_commrec *cr, gmx::ArrayRef<AtomGroupIndices> grps)
-{
- for (auto &group : grps)
- {
- int size = group.size();
- block_bc(cr, size);
- nblock_abc(cr, size, &group);
- }
-}
-
-static void bc_atoms(const t_commrec *cr, t_symtab *symtab, t_atoms *atoms)
-{
- block_bc(cr, atoms->nr);
- snew_bc(cr, atoms->atom, atoms->nr);
- nblock_bc(cr, atoms->nr, atoms->atom);
- bc_strings(cr, symtab, atoms->nr, &atoms->atomname);
- block_bc(cr, atoms->nres);
- snew_bc(cr, atoms->resinfo, atoms->nres);
- nblock_bc(cr, atoms->nres, atoms->resinfo);
- bc_strings_resinfo(cr, symtab, atoms->nres, atoms->resinfo);
- /* QMMM requires atomtypes to be known on all nodes as well */
- bc_strings(cr, symtab, atoms->nr, &atoms->atomtype);
- bc_strings(cr, symtab, atoms->nr, &atoms->atomtypeB);
-}
-
-static void bc_groups(const t_commrec *cr, t_symtab *symtab,
- int natoms, SimulationGroups *groups)
-{
- int n;
-
- bc_grps(cr, groups->groups);
- bc_strings_container(cr, symtab, groups->groupNames.size(), &groups->groupNames);
- for (auto group : gmx::keysOf(groups->groups))
- {
- if (MASTER(cr))
- {
- if (!groups->groupNumbers[group].empty())
- {
- n = natoms;
- }
- else
- {
- n = 0;
- }
- }
- block_bc(cr, n);
- if (n != 0)
- {
- nblock_abc(cr, n, &groups->groupNumbers[group]);
- }
- }
- if (debug)
- {
- fprintf(debug, "after bc_groups\n");
- }
-}
template <typename AllocatorType>
static void bcastPaddedRVecVector(const t_commrec *cr, gmx::PaddedVector<gmx::RVec, AllocatorType> *v, int numAtoms)
}
}
-static void bc_ilists(const t_commrec *cr, InteractionLists *ilist)
-{
- int ftype;
-
- /* Here we only communicate the non-zero length ilists */
- if (MASTER(cr))
- {
- for (ftype = 0; ftype < F_NRE; ftype++)
- {
- if ((*ilist)[ftype].size() > 0)
- {
- block_bc(cr, ftype);
- int nr = (*ilist)[ftype].size();
- block_bc(cr, nr);
- nblock_bc(cr, nr, (*ilist)[ftype].iatoms.data());
- }
- }
- ftype = -1;
- block_bc(cr, ftype);
- }
- else
- {
- for (ftype = 0; ftype < F_NRE; ftype++)
- {
- (*ilist)[ftype].iatoms.clear();
- }
- do
- {
- block_bc(cr, ftype);
- if (ftype >= 0)
- {
- int nr;
- block_bc(cr, nr);
- (*ilist)[ftype].iatoms.resize(nr);
- nblock_bc(cr, nr, (*ilist)[ftype].iatoms.data());
- }
- }
- while (ftype >= 0);
- }
-
- if (debug)
- {
- fprintf(debug, "after bc_ilists\n");
- }
-}
-
-static void bc_cmap(const t_commrec *cr, gmx_cmap_t *cmap_grid)
-{
- int ngrid = cmap_grid->cmapdata.size();
- block_bc(cr, ngrid);
- block_bc(cr, cmap_grid->grid_spacing);
-
- int nelem = cmap_grid->grid_spacing * cmap_grid->grid_spacing;
-
- if (ngrid > 0)
- {
- if (!MASTER(cr))
- {
- cmap_grid->cmapdata.resize(ngrid);
- }
-
- for (int i = 0; i < ngrid; i++)
- {
- nblock_abc(cr, 4*nelem, &cmap_grid->cmapdata[i].cmap);
- }
- }
-}
-
-static void bc_ffparams(const t_commrec *cr, gmx_ffparams_t *ffp)
-{
- int numTypes = ffp->numTypes();
- block_bc(cr, numTypes);
- block_bc(cr, ffp->atnr);
- nblock_abc(cr, numTypes, &ffp->functype);
- nblock_abc(cr, numTypes, &ffp->iparams);
- block_bc(cr, ffp->reppow);
- block_bc(cr, ffp->fudgeQQ);
- bc_cmap(cr, &ffp->cmap_grid);
-}
-
-static void bc_grpopts(const t_commrec *cr, t_grpopts *g)
-{
- int i, n;
-
- block_bc(cr, g->ngtc);
- block_bc(cr, g->ngacc);
- block_bc(cr, g->ngfrz);
- block_bc(cr, g->ngener);
- snew_bc(cr, g->nrdf, g->ngtc);
- snew_bc(cr, g->tau_t, g->ngtc);
- snew_bc(cr, g->ref_t, g->ngtc);
- snew_bc(cr, g->acc, g->ngacc);
- snew_bc(cr, g->nFreeze, g->ngfrz);
- snew_bc(cr, g->egp_flags, g->ngener*g->ngener);
-
- nblock_bc(cr, g->ngtc, g->nrdf);
- nblock_bc(cr, g->ngtc, g->tau_t);
- nblock_bc(cr, g->ngtc, g->ref_t);
- nblock_bc(cr, g->ngacc, g->acc);
- nblock_bc(cr, g->ngfrz, g->nFreeze);
- nblock_bc(cr, g->ngener*g->ngener, g->egp_flags);
- snew_bc(cr, g->annealing, g->ngtc);
- snew_bc(cr, g->anneal_npoints, g->ngtc);
- snew_bc(cr, g->anneal_time, g->ngtc);
- snew_bc(cr, g->anneal_temp, g->ngtc);
- nblock_bc(cr, g->ngtc, g->annealing);
- nblock_bc(cr, g->ngtc, g->anneal_npoints);
- for (i = 0; (i < g->ngtc); i++)
- {
- n = g->anneal_npoints[i];
- if (n > 0)
- {
- snew_bc(cr, g->anneal_time[i], n);
- snew_bc(cr, g->anneal_temp[i], n);
- nblock_bc(cr, n, g->anneal_time[i]);
- nblock_bc(cr, n, g->anneal_temp[i]);
- }
- }
-
- /* QMMM stuff, see inputrec */
- block_bc(cr, g->ngQM);
- snew_bc(cr, g->QMmethod, g->ngQM);
- snew_bc(cr, g->QMbasis, g->ngQM);
- snew_bc(cr, g->QMcharge, g->ngQM);
- snew_bc(cr, g->QMmult, g->ngQM);
- snew_bc(cr, g->bSH, g->ngQM);
- snew_bc(cr, g->CASorbitals, g->ngQM);
- snew_bc(cr, g->CASelectrons, g->ngQM);
- snew_bc(cr, g->SAon, g->ngQM);
- snew_bc(cr, g->SAoff, g->ngQM);
- snew_bc(cr, g->SAsteps, g->ngQM);
-
- if (g->ngQM)
- {
- nblock_bc(cr, g->ngQM, g->QMmethod);
- nblock_bc(cr, g->ngQM, g->QMbasis);
- nblock_bc(cr, g->ngQM, g->QMcharge);
- nblock_bc(cr, g->ngQM, g->QMmult);
- nblock_bc(cr, g->ngQM, g->bSH);
- nblock_bc(cr, g->ngQM, g->CASorbitals);
- nblock_bc(cr, g->ngQM, g->CASelectrons);
- nblock_bc(cr, g->ngQM, g->SAon);
- nblock_bc(cr, g->ngQM, g->SAoff);
- nblock_bc(cr, g->ngQM, g->SAsteps);
- /* end of QMMM stuff */
- }
-}
-
-static void bc_awhBias(const t_commrec *cr, gmx::AwhBiasParams *awhBiasParams)
-{
- block_bc(cr, *awhBiasParams);
-
- snew_bc(cr, awhBiasParams->dimParams, awhBiasParams->ndim);
- nblock_bc(cr, awhBiasParams->ndim, awhBiasParams->dimParams);
-}
-
-static void bc_awh(const t_commrec *cr, gmx::AwhParams *awhParams)
-{
- int k;
-
- block_bc(cr, *awhParams);
- snew_bc(cr, awhParams->awhBiasParams, awhParams->numBias);
- for (k = 0; k < awhParams->numBias; k++)
- {
- bc_awhBias(cr, &awhParams->awhBiasParams[k]);
- }
-}
-
-static void bc_pull_group(const t_commrec *cr, t_pull_group *pgrp)
-{
- block_bc(cr, *pgrp);
- if (pgrp->nat > 0)
- {
- snew_bc(cr, pgrp->ind, pgrp->nat);
- nblock_bc(cr, pgrp->nat, pgrp->ind);
- }
- if (pgrp->nweight > 0)
- {
- snew_bc(cr, pgrp->weight, pgrp->nweight);
- nblock_bc(cr, pgrp->nweight, pgrp->weight);
- }
-}
-
-static void bc_pull(const t_commrec *cr, pull_params_t *pull)
-{
- int g;
-
- block_bc(cr, *pull);
- snew_bc(cr, pull->group, pull->ngroup);
- for (g = 0; g < pull->ngroup; g++)
- {
- bc_pull_group(cr, &pull->group[g]);
- }
- snew_bc(cr, pull->coord, pull->ncoord);
- nblock_bc(cr, pull->ncoord, pull->coord);
- for (int c = 0; c < pull->ncoord; c++)
- {
- if (!MASTER(cr))
- {
- pull->coord[c].externalPotentialProvider = nullptr;
- }
- if (pull->coord[c].eType == epullEXTERNAL)
- {
- bc_cstring(cr, &pull->coord[c].externalPotentialProvider);
- }
- }
-}
-
-static void bc_rotgrp(const t_commrec *cr, t_rotgrp *rotg)
-{
- block_bc(cr, *rotg);
- if (rotg->nat > 0)
- {
- snew_bc(cr, rotg->ind, rotg->nat);
- nblock_bc(cr, rotg->nat, rotg->ind);
- snew_bc(cr, rotg->x_ref, rotg->nat);
- nblock_bc(cr, rotg->nat, rotg->x_ref);
- }
-}
-
-static void bc_rot(const t_commrec *cr, t_rot *rot)
-{
- int g;
-
- block_bc(cr, *rot);
- snew_bc(cr, rot->grp, rot->ngrp);
- for (g = 0; g < rot->ngrp; g++)
- {
- bc_rotgrp(cr, &rot->grp[g]);
- }
-}
-
-static void bc_imd(const t_commrec *cr, t_IMD *imd)
-{
- block_bc(cr, *imd);
- snew_bc(cr, imd->ind, imd->nat);
- nblock_bc(cr, imd->nat, imd->ind);
-}
-
-static void bc_fepvals(const t_commrec *cr, t_lambda *fep)
-{
- int i;
-
- block_bc(cr, fep->nstdhdl);
- block_bc(cr, fep->init_lambda);
- block_bc(cr, fep->init_fep_state);
- block_bc(cr, fep->delta_lambda);
- block_bc(cr, fep->edHdLPrintEnergy);
- block_bc(cr, fep->n_lambda);
- if (fep->n_lambda > 0)
- {
- snew_bc(cr, fep->all_lambda, efptNR);
- nblock_bc(cr, efptNR, fep->all_lambda);
- for (i = 0; i < efptNR; i++)
- {
- snew_bc(cr, fep->all_lambda[i], fep->n_lambda);
- nblock_bc(cr, fep->n_lambda, fep->all_lambda[i]);
- }
- }
- block_bc(cr, fep->sc_alpha);
- block_bc(cr, fep->sc_power);
- block_bc(cr, fep->sc_r_power);
- block_bc(cr, fep->sc_sigma);
- block_bc(cr, fep->sc_sigma_min);
- block_bc(cr, fep->bScCoul);
- nblock_bc(cr, efptNR, &(fep->separate_dvdl[0]));
- block_bc(cr, fep->dhdl_derivatives);
- block_bc(cr, fep->dh_hist_size);
- block_bc(cr, fep->dh_hist_spacing);
- if (debug)
- {
- fprintf(debug, "after bc_fepvals\n");
- }
-}
-
-static void bc_expandedvals(const t_commrec *cr, t_expanded *expand, int n_lambda)
-{
- block_bc(cr, expand->nstexpanded);
- block_bc(cr, expand->elamstats);
- block_bc(cr, expand->elmcmove);
- block_bc(cr, expand->elmceq);
- block_bc(cr, expand->equil_n_at_lam);
- block_bc(cr, expand->equil_wl_delta);
- block_bc(cr, expand->equil_ratio);
- block_bc(cr, expand->equil_steps);
- block_bc(cr, expand->equil_samples);
- block_bc(cr, expand->lmc_seed);
- block_bc(cr, expand->minvar);
- block_bc(cr, expand->minvar_const);
- block_bc(cr, expand->c_range);
- block_bc(cr, expand->bSymmetrizedTMatrix);
- block_bc(cr, expand->nstTij);
- block_bc(cr, expand->lmc_repeats);
- block_bc(cr, expand->lmc_forced_nstart);
- block_bc(cr, expand->gibbsdeltalam);
- block_bc(cr, expand->wl_scale);
- block_bc(cr, expand->wl_ratio);
- block_bc(cr, expand->init_wl_delta);
- block_bc(cr, expand->bInit_weights);
- snew_bc(cr, expand->init_lambda_weights, n_lambda);
- nblock_bc(cr, n_lambda, expand->init_lambda_weights);
- block_bc(cr, expand->mc_temp);
- if (debug)
- {
- fprintf(debug, "after bc_expandedvals\n");
- }
-}
-
-static void bc_simtempvals(const t_commrec *cr, t_simtemp *simtemp, int n_lambda)
-{
- block_bc(cr, simtemp->simtemp_low);
- block_bc(cr, simtemp->simtemp_high);
- block_bc(cr, simtemp->eSimTempScale);
- snew_bc(cr, simtemp->temperatures, n_lambda);
- nblock_bc(cr, n_lambda, simtemp->temperatures);
- if (debug)
- {
- fprintf(debug, "after bc_simtempvals\n");
- }
-}
-
-
-static void bc_swapions(const t_commrec *cr, t_swapcoords *swap)
-{
- block_bc(cr, *swap);
-
- /* Broadcast atom indices for split groups, solvent group, and for all user-defined swap groups */
- snew_bc(cr, swap->grp, swap->ngrp);
- for (int i = 0; i < swap->ngrp; i++)
- {
- t_swapGroup *g = &swap->grp[i];
-
- block_bc(cr, *g);
- snew_bc(cr, g->ind, g->nat);
- nblock_bc(cr, g->nat, g->ind);
-
- int len = 0;
- if (MASTER(cr))
- {
- len = strlen(g->molname);
- }
- block_bc(cr, len);
- snew_bc(cr, g->molname, len);
- nblock_bc(cr, len, g->molname);
- }
-}
-
-
-static void bc_inputrec(const t_commrec *cr, t_inputrec *inputrec)
+static void bc_tpxheader(const t_commrec *cr, TpxFileHeader *tpx)
{
- // Make sure to destruct all previously set internal parameters properly
- // before the block_bc on the inputrec overwrites them.
- // They are expected to be null anyway, but we can't guarantee this here.
- if (!SIMMASTER(cr))
- {
- // will call destructor on previously set parameters upon leaving this block
- std::unique_ptr<gmx::KeyValueTreeObject> previouslySetInternalParametersOnNonMaster;
- inputrec->internalParameters.swap(previouslySetInternalParametersOnNonMaster);
- }
- // Note that this overwrites pointers in inputrec, so all pointer fields
- // Must be initialized separately below.
- block_bc(cr, *inputrec);
- if (SIMMASTER(cr))
- {
- gmx::InMemorySerializer serializer;
- gmx::serializeKeyValueTree(*inputrec->params, &serializer);
- gmx::serializeKeyValueTree(*inputrec->internalParameters, &serializer);
- std::vector<char> buffer = serializer.finishAndGetBuffer();
- size_t size = buffer.size();
- block_bc(cr, size);
- nblock_bc(cr, size, buffer.data());
- }
- else
- {
- // block_bc() of inputrec above overwrites the old pointer, so set it to a
- // reasonable value in case code below throws.
- inputrec->params = nullptr;
- std::vector<char> buffer;
- size_t size;
- block_bc(cr, size);
- nblock_abc(cr, size, &buffer);
- gmx::InMemoryDeserializer serializer(buffer, false);
- inputrec->params = new gmx::KeyValueTreeObject(
- gmx::deserializeKeyValueTree(&serializer));
- // release is required because internalParameters' destructor will fail
- // if block_bc() of inputrec overwrites the internalParameters pointer with garbage
- auto gmx_unused releasedGarbagePointer = inputrec->internalParameters.release();
- inputrec->internalParameters = std::make_unique<gmx::KeyValueTreeObject>(
- gmx::deserializeKeyValueTree(&serializer));
- }
-
- bc_grpopts(cr, &(inputrec->opts));
-
- /* even if efep is efepNO, we need to initialize to make sure that
- * n_lambda is set to zero */
-
- snew_bc(cr, inputrec->fepvals, 1);
- if (inputrec->efep != efepNO || inputrec->bSimTemp)
- {
- bc_fepvals(cr, inputrec->fepvals);
- }
- /* need to initialize this as well because of data checked for in the logic */
- snew_bc(cr, inputrec->expandedvals, 1);
- if (inputrec->bExpanded)
- {
- bc_expandedvals(cr, inputrec->expandedvals, inputrec->fepvals->n_lambda);
- }
- snew_bc(cr, inputrec->simtempvals, 1);
- if (inputrec->bSimTemp)
- {
- bc_simtempvals(cr, inputrec->simtempvals, inputrec->fepvals->n_lambda);
- }
- if (inputrec->bPull)
- {
- snew_bc(cr, inputrec->pull, 1);
- bc_pull(cr, inputrec->pull);
- }
- if (inputrec->bDoAwh)
- {
- snew_bc(cr, inputrec->awhParams, 1);
- bc_awh(cr, inputrec->awhParams);
- }
-
- if (inputrec->bRot)
- {
- snew_bc(cr, inputrec->rot, 1);
- bc_rot(cr, inputrec->rot);
- }
- if (inputrec->bIMD)
- {
- snew_bc(cr, inputrec->imd, 1);
- bc_imd(cr, inputrec->imd);
- }
- if (inputrec->eSwapCoords != eswapNO)
- {
- snew_bc(cr, inputrec->swap, 1);
- bc_swapions(cr, inputrec->swap);
- }
+ block_bc(cr, tpx->bIr);
+ block_bc(cr, tpx->bBox);
+ block_bc(cr, tpx->bTop);
+ block_bc(cr, tpx->bX);
+ block_bc(cr, tpx->bV);
+ block_bc(cr, tpx->bF);
+ block_bc(cr, tpx->natoms);
+ block_bc(cr, tpx->ngtc);
+ block_bc(cr, tpx->lambda);
+ block_bc(cr, tpx->fep_state);
+ block_bc(cr, tpx->sizeOfTprBody);
+ block_bc(cr, tpx->fileVersion);
+ block_bc(cr, tpx->fileGeneration);
+ block_bc(cr, tpx->isDouble);
}
-static void bc_moltype(const t_commrec *cr, t_symtab *symtab,
- gmx_moltype_t *moltype)
+static void bc_tprCharBuffer(const t_commrec *cr, std::vector<char> *charBuffer)
{
- bc_string(cr, symtab, &moltype->name);
- bc_atoms(cr, symtab, &moltype->atoms);
- if (debug)
- {
- fprintf(debug, "after bc_atoms\n");
- }
+ int elements = charBuffer->size();
+ block_bc(cr, elements);
- bc_ilists(cr, &moltype->ilist);
- bc_block(cr, &moltype->cgs);
- bc_blocka(cr, &moltype->excls);
+ nblock_abc(cr, elements, charBuffer);
}
-static void bc_vector_of_rvec(const t_commrec *cr, std::vector<gmx::RVec> *vec)
+void init_parallel(t_commrec *cr,
+ t_inputrec *inputrec,
+ gmx_mtop_t *mtop,
+ PartialDeserializedTprFile *partialDeserializedTpr)
{
- int numElements = vec->size();
- block_bc(cr, numElements);
+ bc_tpxheader(cr, &partialDeserializedTpr->header);
+ bc_tprCharBuffer(cr, &partialDeserializedTpr->body);
if (!MASTER(cr))
{
- vec->resize(numElements);
- }
- if (numElements > 0)
- {
- nblock_bc(cr, numElements, as_rvec_array(vec->data()));
- }
-}
-
-static void bc_molblock(const t_commrec *cr, gmx_molblock_t *molb)
-{
- block_bc(cr, molb->type);
- block_bc(cr, molb->nmol);
- bc_vector_of_rvec(cr, &molb->posres_xA);
- bc_vector_of_rvec(cr, &molb->posres_xB);
- if (debug)
- {
- fprintf(debug, "after bc_molblock\n");
+ completeTprDeserialization(partialDeserializedTpr,
+ inputrec,
+ mtop);
}
}
-
-static void bc_atomtypes(const t_commrec *cr, t_atomtypes *atomtypes)
-{
- block_bc(cr, atomtypes->nr);
-}
-
-/*! \brief Broadcasts ir and mtop from the master to all nodes in
- * cr->mpi_comm_mygroup. */
-static
-void bcast_ir_mtop(const t_commrec *cr, t_inputrec *inputrec, gmx_mtop_t *mtop)
-{
- if (debug)
- {
- fprintf(debug, "in bc_data\n");
- }
- bc_inputrec(cr, inputrec);
- if (debug)
- {
- fprintf(debug, "after bc_inputrec\n");
- }
- bc_symtab(cr, &mtop->symtab);
- if (debug)
- {
- fprintf(debug, "after bc_symtab\n");
- }
- bc_string(cr, &mtop->symtab, &mtop->name);
- if (debug)
- {
- fprintf(debug, "after bc_name\n");
- }
-
- bc_ffparams(cr, &mtop->ffparams);
-
- int nmoltype = mtop->moltype.size();
- block_bc(cr, nmoltype);
- mtop->moltype.resize(nmoltype);
- for (gmx_moltype_t &moltype : mtop->moltype)
- {
- bc_moltype(cr, &mtop->symtab, &moltype);
- }
-
- block_bc(cr, mtop->bIntermolecularInteractions);
- if (mtop->bIntermolecularInteractions)
- {
- if (!MASTER(cr))
- {
- mtop->intermolecular_ilist = std::make_unique<InteractionLists>();
- }
- bc_ilists(cr, mtop->intermolecular_ilist.get());
- }
-
- int nmolblock = mtop->molblock.size();
- block_bc(cr, nmolblock);
- mtop->molblock.resize(nmolblock);
- for (gmx_molblock_t &molblock : mtop->molblock)
- {
- bc_molblock(cr, &molblock);
- }
-
- block_bc(cr, mtop->natoms);
-
- bc_atomtypes(cr, &mtop->atomtypes);
-
- bc_groups(cr, &mtop->symtab, mtop->natoms, &mtop->groups);
-
- GMX_RELEASE_ASSERT(!MASTER(cr) || mtop->haveMoleculeIndices, "mtop should have valid molecule indices");
- if (!MASTER(cr))
- {
- mtop->haveMoleculeIndices = true;
-
- gmx_mtop_finalize(mtop);
- }
-}
-
-void init_parallel(t_commrec *cr, t_inputrec *inputrec,
- gmx_mtop_t *mtop)
-{
- bcast_ir_mtop(cr, inputrec, mtop);
-}