2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
39 #include "gromacs/commandline/filenm.h"
40 #include "gromacs/domdec/collect.h"
41 #include "gromacs/domdec/domdec_struct.h"
42 #include "gromacs/fileio/checkpoint.h"
43 #include "gromacs/fileio/gmxfio.h"
44 #include "gromacs/fileio/tngio.h"
45 #include "gromacs/fileio/trrio.h"
46 #include "gromacs/fileio/xtcio.h"
47 #include "gromacs/fileio/xvgr.h"
48 #include "gromacs/math/vec.h"
49 #include "gromacs/mdlib/trajectory_writing.h"
50 #include "gromacs/mdrunutility/handlerestart.h"
51 #include "gromacs/mdtypes/commrec.h"
52 #include "gromacs/mdtypes/imdoutputprovider.h"
53 #include "gromacs/mdtypes/inputrec.h"
54 #include "gromacs/mdtypes/md_enums.h"
55 #include "gromacs/mdtypes/mdrunoptions.h"
56 #include "gromacs/mdtypes/state.h"
57 #include "gromacs/timing/wallcycle.h"
58 #include "gromacs/topology/topology.h"
59 #include "gromacs/utility/fatalerror.h"
60 #include "gromacs/utility/pleasecite.h"
61 #include "gromacs/utility/smalloc.h"
66 gmx_tng_trajectory_t tng;
67 gmx_tng_trajectory_t tng_low_prec;
68 int x_compression_precision; /* only used by XTC output */
71 gmx_bool bKeepAndNumCPT;
78 int natoms_x_compressed;
79 SimulationGroups *groups; /* for compressed position writing */
80 gmx_wallcycle_t wcycle;
82 gmx::IMDOutputProvider *outputProvider;
83 const gmx::MdModulesNotifier *mdModulesNotifier;
87 gmx_mdoutf_t init_mdoutf(FILE *fplog, int nfile, const t_filenm fnm[],
88 const gmx::MdrunOptions &mdrunOptions,
90 gmx::IMDOutputProvider *outputProvider,
91 const gmx::MdModulesNotifier &mdModulesNotifier,
92 const t_inputrec *ir, gmx_mtop_t *top_global,
93 const gmx_output_env_t *oenv, gmx_wallcycle_t wcycle,
94 const gmx::StartingBehavior startingBehavior)
97 const char *appendMode = "a+", *writeMode = "w+", *filemode;
98 gmx_bool bCiteTng = FALSE;
100 bool restartWithAppending = (startingBehavior == gmx::StartingBehavior::RestartWithAppending);
104 of->fp_trn = nullptr;
105 of->fp_ene = nullptr;
106 of->fp_xtc = nullptr;
108 of->tng_low_prec = nullptr;
109 of->fp_dhdl = nullptr;
111 of->eIntegrator = ir->eI;
112 of->bExpanded = ir->bExpanded;
113 of->elamstats = ir->expandedvals->elamstats;
114 of->simulation_part = ir->simulation_part;
115 of->x_compression_precision = static_cast<int>(ir->x_compression_precision);
117 of->f_global = nullptr;
118 of->outputProvider = outputProvider;
122 of->bKeepAndNumCPT = mdrunOptions.checkpointOptions.keepAndNumberCheckpointFiles;
124 filemode = restartWithAppending ? appendMode : writeMode;
126 if (EI_DYNAMICS(ir->eI) &&
127 ir->nstxout_compressed > 0)
129 const char *filename;
130 filename = ftp2fn(efCOMPRESSED, nfile, fnm);
131 switch (fn2ftp(filename))
134 of->fp_xtc = open_xtc(filename, filemode);
137 gmx_tng_open(filename, filemode[0], &of->tng_low_prec);
138 if (filemode[0] == 'w')
140 gmx_tng_prepare_low_prec_writing(of->tng_low_prec, top_global, ir);
145 gmx_incons("Invalid reduced precision file format");
148 if ((EI_DYNAMICS(ir->eI) || EI_ENERGY_MINIMIZATION(ir->eI)) &&
150 !(EI_DYNAMICS(ir->eI) &&
157 const char *filename;
158 filename = ftp2fn(efTRN, nfile, fnm);
159 switch (fn2ftp(filename))
163 /* If there is no uncompressed coordinate output and
164 there is compressed TNG output write forces
165 and/or velocities to the TNG file instead. */
166 if (ir->nstxout != 0 || ir->nstxout_compressed == 0 ||
169 of->fp_trn = gmx_trr_open(filename, filemode);
173 gmx_tng_open(filename, filemode[0], &of->tng);
174 if (filemode[0] == 'w')
176 gmx_tng_prepare_md_writing(of->tng, top_global, ir);
181 gmx_incons("Invalid full precision file format");
184 if (EI_DYNAMICS(ir->eI) || EI_ENERGY_MINIMIZATION(ir->eI))
186 of->fp_ene = open_enx(ftp2fn(efEDR, nfile, fnm), filemode);
188 of->fn_cpt = opt2fn("-cpo", nfile, fnm);
190 if ((ir->efep != efepNO || ir->bSimTemp) && ir->fepvals->nstdhdl > 0 &&
191 (ir->fepvals->separate_dhdl_file == esepdhdlfileYES ) &&
194 if (restartWithAppending)
196 of->fp_dhdl = gmx_fio_fopen(opt2fn("-dhdl", nfile, fnm), filemode);
200 of->fp_dhdl = open_dhdl(opt2fn("-dhdl", nfile, fnm), ir, oenv);
204 outputProvider->initOutput(fplog, nfile, fnm, restartWithAppending, oenv);
205 of->mdModulesNotifier = &mdModulesNotifier;
207 /* Set up atom counts so they can be passed to actual
208 trajectory-writing routines later. Also, XTC writing needs
209 to know what (and how many) atoms might be in the XTC
210 groups, and how to look up later which ones they are. */
211 of->natoms_global = top_global->natoms;
212 of->groups = &top_global->groups;
213 of->natoms_x_compressed = 0;
214 for (i = 0; (i < top_global->natoms); i++)
216 if (getGroupType(*of->groups, SimulationAtomGroupType::CompressedPositionOutput, i) == 0)
218 of->natoms_x_compressed++;
222 if (ir->nstfout && DOMAINDECOMP(cr))
224 snew(of->f_global, top_global->natoms);
230 please_cite(fplog, "Lundborg2014");
236 ener_file_t mdoutf_get_fp_ene(gmx_mdoutf_t of)
241 FILE *mdoutf_get_fp_dhdl(gmx_mdoutf_t of)
246 gmx_wallcycle_t mdoutf_get_wcycle(gmx_mdoutf_t of)
251 void mdoutf_write_to_trajectory_files(FILE *fplog, const t_commrec *cr,
255 int64_t step, double t,
256 t_state *state_local, t_state *state_global,
257 ObservablesHistory *observablesHistory,
258 gmx::ArrayRef<gmx::RVec> f_local)
262 if (DOMAINDECOMP(cr))
264 if (mdof_flags & MDOF_CPT)
266 dd_collect_state(cr->dd, state_local, state_global);
270 if (mdof_flags & (MDOF_X | MDOF_X_COMPRESSED))
272 auto globalXRef = MASTER(cr) ? state_global->x : gmx::ArrayRef<gmx::RVec>();
273 dd_collect_vec(cr->dd, state_local, state_local->x, globalXRef);
275 if (mdof_flags & MDOF_V)
277 auto globalVRef = MASTER(cr) ? state_global->v : gmx::ArrayRef<gmx::RVec>();
278 dd_collect_vec(cr->dd, state_local, state_local->v, globalVRef);
281 f_global = of->f_global;
282 if (mdof_flags & MDOF_F)
284 dd_collect_vec(cr->dd, state_local, f_local, gmx::arrayRefFromArray(reinterpret_cast<gmx::RVec *>(f_global), f_local.size()));
289 /* We have the whole state locally: copy the local state pointer */
290 state_global = state_local;
292 f_global = as_rvec_array(f_local.data());
297 if (mdof_flags & MDOF_CPT)
300 fflush_tng(of->tng_low_prec);
301 ivec one_ivec = { 1, 1, 1 };
302 write_checkpoint(of->fn_cpt, of->bKeepAndNumCPT,
304 DOMAINDECOMP(cr) ? cr->dd->nc : one_ivec,
305 DOMAINDECOMP(cr) ? cr->dd->nnodes : cr->nnodes,
306 of->eIntegrator, of->simulation_part,
307 of->bExpanded, of->elamstats, step, t,
308 state_global, observablesHistory, *(of->mdModulesNotifier));
311 if (mdof_flags & (MDOF_X | MDOF_V | MDOF_F))
313 const rvec *x = (mdof_flags & MDOF_X) ? state_global->x.rvec_array() : nullptr;
314 const rvec *v = (mdof_flags & MDOF_V) ? state_global->v.rvec_array() : nullptr;
315 const rvec *f = (mdof_flags & MDOF_F) ? f_global : nullptr;
319 gmx_trr_write_frame(of->fp_trn, step, t, state_local->lambda[efptFEP],
320 state_local->box, natoms,
322 if (gmx_fio_flush(of->fp_trn) != 0)
324 gmx_file("Cannot write trajectory; maybe you are out of disk space?");
328 /* If a TNG file is open for uncompressed coordinate output also write
329 velocities and forces to it. */
332 gmx_fwrite_tng(of->tng, FALSE, step, t, state_local->lambda[efptFEP],
337 /* If only a TNG file is open for compressed coordinate output (no uncompressed
338 coordinate output) also write forces and velocities to it. */
339 else if (of->tng_low_prec)
341 gmx_fwrite_tng(of->tng_low_prec, FALSE, step, t, state_local->lambda[efptFEP],
347 if (mdof_flags & MDOF_X_COMPRESSED)
349 rvec *xxtc = nullptr;
351 if (of->natoms_x_compressed == of->natoms_global)
353 /* We are writing the positions of all of the atoms to
354 the compressed output */
355 xxtc = state_global->x.rvec_array();
359 /* We are writing the positions of only a subset of
360 the atoms to the compressed output, so we have to
361 make a copy of the subset of coordinates. */
364 snew(xxtc, of->natoms_x_compressed);
365 auto x = makeArrayRef(state_global->x);
366 for (i = 0, j = 0; (i < of->natoms_global); i++)
368 if (getGroupType(*of->groups, SimulationAtomGroupType::CompressedPositionOutput, i) == 0)
370 copy_rvec(x[i], xxtc[j++]);
374 if (write_xtc(of->fp_xtc, of->natoms_x_compressed, step, t,
375 state_local->box, xxtc, of->x_compression_precision) == 0)
378 "XTC error. This indicates you are out of disk space, or a "
379 "simulation with major instabilities resulting in coordinates "
380 "that are NaN or too large to be represented in the XTC format.\n");
382 gmx_fwrite_tng(of->tng_low_prec,
386 state_local->lambda[efptFEP],
388 of->natoms_x_compressed,
392 if (of->natoms_x_compressed != of->natoms_global)
397 if (mdof_flags & (MDOF_BOX | MDOF_LAMBDA) && !(mdof_flags & (MDOF_X | MDOF_V | MDOF_F)) )
403 if (mdof_flags & MDOF_BOX)
405 box = state_local->box;
407 if (mdof_flags & MDOF_LAMBDA)
409 lambda = state_local->lambda[efptFEP];
411 gmx_fwrite_tng(of->tng, FALSE, step, t, lambda,
413 nullptr, nullptr, nullptr);
416 if (mdof_flags & (MDOF_BOX_COMPRESSED | MDOF_LAMBDA_COMPRESSED) && !(mdof_flags & (MDOF_X_COMPRESSED)) )
418 if (of->tng_low_prec)
422 if (mdof_flags & MDOF_BOX_COMPRESSED)
424 box = state_local->box;
426 if (mdof_flags & MDOF_LAMBDA_COMPRESSED)
428 lambda = state_local->lambda[efptFEP];
430 gmx_fwrite_tng(of->tng_low_prec, FALSE, step, t, lambda,
432 nullptr, nullptr, nullptr);
438 void mdoutf_tng_close(gmx_mdoutf_t of)
440 if (of->tng || of->tng_low_prec)
442 wallcycle_start(of->wcycle, ewcTRAJ);
443 gmx_tng_close(&of->tng);
444 gmx_tng_close(&of->tng_low_prec);
445 wallcycle_stop(of->wcycle, ewcTRAJ);
449 void done_mdoutf(gmx_mdoutf_t of)
451 if (of->fp_ene != nullptr)
453 done_ener_file(of->fp_ene);
457 close_xtc(of->fp_xtc);
461 gmx_trr_close(of->fp_trn);
463 if (of->fp_dhdl != nullptr)
465 gmx_fio_fclose(of->fp_dhdl);
467 of->outputProvider->finishOutput();
468 if (of->f_global != nullptr)
473 gmx_tng_close(&of->tng);
474 gmx_tng_close(&of->tng_low_prec);
479 int mdoutf_get_tng_box_output_interval(gmx_mdoutf_t of)
483 return gmx_tng_get_box_output_interval(of->tng);
488 int mdoutf_get_tng_lambda_output_interval(gmx_mdoutf_t of)
492 return gmx_tng_get_lambda_output_interval(of->tng);
497 int mdoutf_get_tng_compressed_box_output_interval(gmx_mdoutf_t of)
499 if (of->tng_low_prec)
501 return gmx_tng_get_box_output_interval(of->tng_low_prec);
506 int mdoutf_get_tng_compressed_lambda_output_interval(gmx_mdoutf_t of)
508 if (of->tng_low_prec)
510 return gmx_tng_get_lambda_output_interval(of->tng_low_prec);