Separate VV first and second steps from MD loop
[alexxy/gromacs.git] / src / gromacs / mdrun / md.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team.
6  * Copyright (c) 2011-2019,2020, 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.
10  *
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.
15  *
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.
20  *
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.
25  *
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.
33  *
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.
36  */
37 /*! \internal \file
38  *
39  * \brief Implements the integrator for normal molecular dynamics simulations
40  *
41  * \author David van der Spoel <david.vanderspoel@icm.uu.se>
42  * \ingroup module_mdrun
43  */
44 #include "gmxpre.h"
45
46 #include <cinttypes>
47 #include <cmath>
48 #include <cstdio>
49 #include <cstdlib>
50
51 #include <algorithm>
52 #include <memory>
53 #include <numeric>
54
55 #include "gromacs/applied_forces/awh/awh.h"
56 #include "gromacs/commandline/filenm.h"
57 #include "gromacs/domdec/collect.h"
58 #include "gromacs/domdec/dlbtiming.h"
59 #include "gromacs/domdec/domdec.h"
60 #include "gromacs/domdec/domdec_network.h"
61 #include "gromacs/domdec/domdec_struct.h"
62 #include "gromacs/domdec/gpuhaloexchange.h"
63 #include "gromacs/domdec/mdsetup.h"
64 #include "gromacs/domdec/partition.h"
65 #include "gromacs/essentialdynamics/edsam.h"
66 #include "gromacs/ewald/pme_load_balancing.h"
67 #include "gromacs/ewald/pme_pp.h"
68 #include "gromacs/fileio/trxio.h"
69 #include "gromacs/gmxlib/network.h"
70 #include "gromacs/gmxlib/nrnb.h"
71 #include "gromacs/gpu_utils/device_stream_manager.h"
72 #include "gromacs/gpu_utils/gpu_utils.h"
73 #include "gromacs/imd/imd.h"
74 #include "gromacs/listed_forces/listed_forces.h"
75 #include "gromacs/math/functions.h"
76 #include "gromacs/math/invertmatrix.h"
77 #include "gromacs/math/vec.h"
78 #include "gromacs/math/vectypes.h"
79 #include "gromacs/mdlib/checkpointhandler.h"
80 #include "gromacs/mdlib/compute_io.h"
81 #include "gromacs/mdlib/constr.h"
82 #include "gromacs/mdlib/coupling.h"
83 #include "gromacs/mdlib/ebin.h"
84 #include "gromacs/mdlib/enerdata_utils.h"
85 #include "gromacs/mdlib/energyoutput.h"
86 #include "gromacs/mdlib/expanded.h"
87 #include "gromacs/mdlib/force.h"
88 #include "gromacs/mdlib/force_flags.h"
89 #include "gromacs/mdlib/forcerec.h"
90 #include "gromacs/mdlib/freeenergyparameters.h"
91 #include "gromacs/mdlib/md_support.h"
92 #include "gromacs/mdlib/mdatoms.h"
93 #include "gromacs/mdlib/mdoutf.h"
94 #include "gromacs/mdlib/membed.h"
95 #include "gromacs/mdlib/resethandler.h"
96 #include "gromacs/mdlib/sighandler.h"
97 #include "gromacs/mdlib/simulationsignal.h"
98 #include "gromacs/mdlib/stat.h"
99 #include "gromacs/mdlib/stophandler.h"
100 #include "gromacs/mdlib/tgroup.h"
101 #include "gromacs/mdlib/trajectory_writing.h"
102 #include "gromacs/mdlib/update.h"
103 #include "gromacs/mdlib/update_constrain_gpu.h"
104 #include "gromacs/mdlib/update_vv.h"
105 #include "gromacs/mdlib/vcm.h"
106 #include "gromacs/mdlib/vsite.h"
107 #include "gromacs/mdrunutility/handlerestart.h"
108 #include "gromacs/mdrunutility/multisim.h"
109 #include "gromacs/mdrunutility/printtime.h"
110 #include "gromacs/mdtypes/awh_history.h"
111 #include "gromacs/mdtypes/awh_params.h"
112 #include "gromacs/mdtypes/commrec.h"
113 #include "gromacs/mdtypes/df_history.h"
114 #include "gromacs/mdtypes/energyhistory.h"
115 #include "gromacs/mdtypes/fcdata.h"
116 #include "gromacs/mdtypes/forcebuffers.h"
117 #include "gromacs/mdtypes/forcerec.h"
118 #include "gromacs/mdtypes/group.h"
119 #include "gromacs/mdtypes/inputrec.h"
120 #include "gromacs/mdtypes/interaction_const.h"
121 #include "gromacs/mdtypes/md_enums.h"
122 #include "gromacs/mdtypes/mdatom.h"
123 #include "gromacs/mdtypes/mdrunoptions.h"
124 #include "gromacs/mdtypes/multipletimestepping.h"
125 #include "gromacs/mdtypes/observableshistory.h"
126 #include "gromacs/mdtypes/pullhistory.h"
127 #include "gromacs/mdtypes/simulation_workload.h"
128 #include "gromacs/mdtypes/state.h"
129 #include "gromacs/mdtypes/state_propagator_data_gpu.h"
130 #include "gromacs/modularsimulator/energydata.h"
131 #include "gromacs/nbnxm/gpu_data_mgmt.h"
132 #include "gromacs/nbnxm/nbnxm.h"
133 #include "gromacs/pbcutil/pbc.h"
134 #include "gromacs/pulling/output.h"
135 #include "gromacs/pulling/pull.h"
136 #include "gromacs/swap/swapcoords.h"
137 #include "gromacs/timing/wallcycle.h"
138 #include "gromacs/timing/walltime_accounting.h"
139 #include "gromacs/topology/atoms.h"
140 #include "gromacs/topology/idef.h"
141 #include "gromacs/topology/mtop_util.h"
142 #include "gromacs/topology/topology.h"
143 #include "gromacs/trajectory/trajectoryframe.h"
144 #include "gromacs/utility/basedefinitions.h"
145 #include "gromacs/utility/cstringutil.h"
146 #include "gromacs/utility/fatalerror.h"
147 #include "gromacs/utility/logger.h"
148 #include "gromacs/utility/real.h"
149 #include "gromacs/utility/smalloc.h"
150
151 #include "legacysimulator.h"
152 #include "replicaexchange.h"
153 #include "shellfc.h"
154
155 using gmx::SimulationSignaller;
156
157 void gmx::LegacySimulator::do_md()
158 {
159     // TODO Historically, the EM and MD "integrators" used different
160     // names for the t_inputrec *parameter, but these must have the
161     // same name, now that it's a member of a struct. We use this ir
162     // alias to avoid a large ripple of nearly useless changes.
163     // t_inputrec is being replaced by IMdpOptionsProvider, so this
164     // will go away eventually.
165     t_inputrec*  ir = inputrec;
166     int64_t      step, step_rel;
167     double       t, t0 = ir->init_t;
168     gmx_bool     bGStatEveryStep, bGStat, bCalcVir, bCalcEnerStep, bCalcEner;
169     gmx_bool     bNS = FALSE, bNStList, bStopCM, bFirstStep, bInitStep, bLastStep = FALSE;
170     gmx_bool     bDoDHDL = FALSE, bDoFEP = FALSE, bDoExpanded = FALSE;
171     gmx_bool     do_ene, do_log, do_verbose;
172     gmx_bool     bMasterState;
173     unsigned int force_flags;
174     tensor force_vir = { { 0 } }, shake_vir = { { 0 } }, total_vir = { { 0 } }, pres = { { 0 } };
175     int    i, m;
176     rvec   mu_tot;
177     matrix pressureCouplingMu, M;
178     gmx_repl_ex_t     repl_ex = nullptr;
179     gmx_global_stat_t gstat;
180     gmx_shellfc_t*    shellfc;
181     gmx_bool          bSumEkinhOld, bDoReplEx, bExchanged, bNeedRepartition;
182     gmx_bool          bTrotter;
183     real              dvdl_constr;
184     std::vector<RVec> cbuf;
185     matrix            lastbox;
186     int               lamnew = 0;
187     /* for FEP */
188     int       nstfep = 0;
189     double    cycles;
190     real      saved_conserved_quantity = 0;
191     real      last_ekin                = 0;
192     t_extmass MassQ;
193     char      sbuf[STEPSTRSIZE], sbuf2[STEPSTRSIZE];
194
195     /* PME load balancing data for GPU kernels */
196     gmx_bool bPMETune         = FALSE;
197     gmx_bool bPMETunePrinting = FALSE;
198
199     bool bInteractiveMDstep = false;
200
201     /* Domain decomposition could incorrectly miss a bonded
202        interaction, but checking for that requires a global
203        communication stage, which does not otherwise happen in DD
204        code. So we do that alongside the first global energy reduction
205        after a new DD is made. These variables handle whether the
206        check happens, and the result it returns. */
207     bool shouldCheckNumberOfBondedInteractions = false;
208     int  totalNumberOfBondedInteractions       = -1;
209
210     SimulationSignals signals;
211     // Most global communnication stages don't propagate mdrun
212     // signals, and will use this object to achieve that.
213     SimulationSignaller nullSignaller(nullptr, nullptr, nullptr, false, false);
214
215     if (!mdrunOptions.writeConfout)
216     {
217         // This is on by default, and the main known use case for
218         // turning it off is for convenience in benchmarking, which is
219         // something that should not show up in the general user
220         // interface.
221         GMX_LOG(mdlog.info)
222                 .asParagraph()
223                 .appendText(
224                         "The -noconfout functionality is deprecated, and may be removed in a "
225                         "future version.");
226     }
227
228     /* md-vv uses averaged full step velocities for T-control
229        md-vv-avek uses averaged half step velocities for T-control (but full step ekin for P control)
230        md uses averaged half step kinetic energies to determine temperature unless defined otherwise by GMX_EKIN_AVE_VEL; */
231     bTrotter = (EI_VV(ir->eI)
232                 && (inputrecNptTrotter(ir) || inputrecNphTrotter(ir) || inputrecNvtTrotter(ir)));
233
234     const bool bRerunMD = false;
235
236     int nstglobalcomm = computeGlobalCommunicationPeriod(mdlog, ir, cr);
237     bGStatEveryStep   = (nstglobalcomm == 1);
238
239     const SimulationGroups* groups = &top_global->groups;
240
241     std::unique_ptr<EssentialDynamics> ed = nullptr;
242     if (opt2bSet("-ei", nfile, fnm))
243     {
244         /* Initialize essential dynamics sampling */
245         ed = init_edsam(mdlog, opt2fn_null("-ei", nfile, fnm), opt2fn("-eo", nfile, fnm), top_global,
246                         ir, cr, constr, state_global, observablesHistory, oenv, startingBehavior);
247     }
248     else if (observablesHistory->edsamHistory)
249     {
250         gmx_fatal(FARGS,
251                   "The checkpoint is from a run with essential dynamics sampling, "
252                   "but the current run did not specify the -ei option. "
253                   "Either specify the -ei option to mdrun, or do not use this checkpoint file.");
254     }
255
256     int*                fep_state = MASTER(cr) ? &state_global->fep_state : nullptr;
257     gmx::ArrayRef<real> lambda    = MASTER(cr) ? state_global->lambda : gmx::ArrayRef<real>();
258     initialize_lambdas(fplog, *ir, MASTER(cr), fep_state, lambda);
259     Update     upd(*ir, deform);
260     const bool doSimulatedAnnealing = initSimulatedAnnealing(ir, &upd);
261     const bool useReplicaExchange   = (replExParams.exchangeInterval > 0);
262
263     const t_fcdata& fcdata = *fr->fcdata;
264
265     bool simulationsShareState = false;
266     int  nstSignalComm         = nstglobalcomm;
267     {
268         // TODO This implementation of ensemble orientation restraints is nasty because
269         // a user can't just do multi-sim with single-sim orientation restraints.
270         bool usingEnsembleRestraints =
271                 (fcdata.disres->nsystems > 1) || ((ms != nullptr) && (fcdata.orires->nr != 0));
272         bool awhUsesMultiSim = (ir->bDoAwh && ir->awhParams->shareBiasMultisim && (ms != nullptr));
273
274         // Replica exchange, ensemble restraints and AWH need all
275         // simulations to remain synchronized, so they need
276         // checkpoints and stop conditions to act on the same step, so
277         // the propagation of such signals must take place between
278         // simulations, not just within simulations.
279         // TODO: Make algorithm initializers set these flags.
280         simulationsShareState = useReplicaExchange || usingEnsembleRestraints || awhUsesMultiSim;
281
282         if (simulationsShareState)
283         {
284             // Inter-simulation signal communication does not need to happen
285             // often, so we use a minimum of 200 steps to reduce overhead.
286             const int c_minimumInterSimulationSignallingInterval = 200;
287             nstSignalComm = ((c_minimumInterSimulationSignallingInterval + nstglobalcomm - 1) / nstglobalcomm)
288                             * nstglobalcomm;
289         }
290     }
291
292     if (startingBehavior != StartingBehavior::RestartWithAppending)
293     {
294         pleaseCiteCouplingAlgorithms(fplog, *ir);
295     }
296     gmx_mdoutf* outf =
297             init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider, mdModulesNotifier, ir,
298                         top_global, oenv, wcycle, startingBehavior, simulationsShareState, ms);
299     gmx::EnergyOutput energyOutput(mdoutf_get_fp_ene(outf), top_global, ir, pull_work,
300                                    mdoutf_get_fp_dhdl(outf), false, startingBehavior, mdModulesNotifier);
301
302     gstat = global_stat_init(ir);
303
304     const auto& simulationWork     = runScheduleWork->simulationWork;
305     const bool  useGpuForPme       = simulationWork.useGpuPme;
306     const bool  useGpuForNonbonded = simulationWork.useGpuNonbonded;
307     const bool  useGpuForBufferOps = simulationWork.useGpuBufferOps;
308     const bool  useGpuForUpdate    = simulationWork.useGpuUpdate;
309
310     /* Check for polarizable models and flexible constraints */
311     shellfc = init_shell_flexcon(fplog, top_global, constr ? constr->numFlexibleConstraints() : 0,
312                                  ir->nstcalcenergy, DOMAINDECOMP(cr), useGpuForPme);
313
314     {
315         double io = compute_io(ir, top_global->natoms, *groups, energyOutput.numEnergyTerms(), 1);
316         if ((io > 2000) && MASTER(cr))
317         {
318             fprintf(stderr, "\nWARNING: This run will generate roughly %.0f Mb of data\n\n", io);
319         }
320     }
321
322     // Local state only becomes valid now.
323     std::unique_ptr<t_state> stateInstance;
324     t_state*                 state;
325
326     gmx_localtop_t top(top_global->ffparams);
327
328     auto mdatoms = mdAtoms->mdatoms();
329
330     ForceBuffers f(fr->useMts, ((useGpuForNonbonded && useGpuForBufferOps) || useGpuForUpdate)
331                                        ? PinningPolicy::PinnedIfSupported
332                                        : PinningPolicy::CannotBePinned);
333     if (DOMAINDECOMP(cr))
334     {
335         stateInstance = std::make_unique<t_state>();
336         state         = stateInstance.get();
337         dd_init_local_state(cr->dd, state_global, state);
338
339         /* Distribute the charge groups over the nodes from the master node */
340         dd_partition_system(fplog, mdlog, ir->init_step, cr, TRUE, 1, state_global, *top_global, ir,
341                             imdSession, pull_work, state, &f, mdAtoms, &top, fr, vsite, constr,
342                             nrnb, nullptr, FALSE);
343         shouldCheckNumberOfBondedInteractions = true;
344         upd.setNumAtoms(state->natoms);
345     }
346     else
347     {
348         state_change_natoms(state_global, state_global->natoms);
349         /* Copy the pointer to the global state */
350         state = state_global;
351
352         /* Generate and initialize new topology */
353         mdAlgorithmsSetupAtomData(cr, ir, *top_global, &top, fr, &f, mdAtoms, constr, vsite, shellfc);
354
355         upd.setNumAtoms(state->natoms);
356     }
357
358     std::unique_ptr<UpdateConstrainGpu> integrator;
359
360     StatePropagatorDataGpu* stateGpu = fr->stateGpu;
361
362     // TODO: the assertions below should be handled by UpdateConstraintsBuilder.
363     if (useGpuForUpdate)
364     {
365         GMX_RELEASE_ASSERT(!DOMAINDECOMP(cr) || ddUsesUpdateGroups(*cr->dd) || constr == nullptr
366                                    || constr->numConstraintsTotal() == 0,
367                            "Constraints in domain decomposition are only supported with update "
368                            "groups if using GPU update.\n");
369         GMX_RELEASE_ASSERT(ir->eConstrAlg != econtSHAKE || constr == nullptr
370                                    || constr->numConstraintsTotal() == 0,
371                            "SHAKE is not supported with GPU update.");
372         GMX_RELEASE_ASSERT(useGpuForPme || (useGpuForNonbonded && simulationWork.useGpuBufferOps),
373                            "Either PME or short-ranged non-bonded interaction tasks must run on "
374                            "the GPU to use GPU update.\n");
375         GMX_RELEASE_ASSERT(ir->eI == eiMD,
376                            "Only the md integrator is supported with the GPU update.\n");
377         GMX_RELEASE_ASSERT(
378                 ir->etc != etcNOSEHOOVER,
379                 "Nose-Hoover temperature coupling is not supported with the GPU update.\n");
380         GMX_RELEASE_ASSERT(
381                 ir->epc == epcNO || ir->epc == epcPARRINELLORAHMAN || ir->epc == epcBERENDSEN
382                         || ir->epc == epcCRESCALE,
383                 "Only Parrinello-Rahman, Berendsen, and C-rescale pressure coupling are supported "
384                 "with the GPU update.\n");
385         GMX_RELEASE_ASSERT(!mdatoms->haveVsites,
386                            "Virtual sites are not supported with the GPU update.\n");
387         GMX_RELEASE_ASSERT(ed == nullptr,
388                            "Essential dynamics is not supported with the GPU update.\n");
389         GMX_RELEASE_ASSERT(!ir->bPull || !pull_have_constraint(*ir->pull),
390                            "Constraints pulling is not supported with the GPU update.\n");
391         GMX_RELEASE_ASSERT(fcdata.orires->nr == 0,
392                            "Orientation restraints are not supported with the GPU update.\n");
393         GMX_RELEASE_ASSERT(
394                 ir->efep == efepNO
395                         || (!haveFreeEnergyType(*ir, efptBONDED) && !haveFreeEnergyType(*ir, efptMASS)),
396                 "Free energy perturbation of masses and constraints are not supported with the GPU "
397                 "update.");
398
399         if (constr != nullptr && constr->numConstraintsTotal() > 0)
400         {
401             GMX_LOG(mdlog.info)
402                     .asParagraph()
403                     .appendText("Updating coordinates and applying constraints on the GPU.");
404         }
405         else
406         {
407             GMX_LOG(mdlog.info).asParagraph().appendText("Updating coordinates on the GPU.");
408         }
409         GMX_RELEASE_ASSERT(fr->deviceStreamManager != nullptr,
410                            "Device stream manager should be initialized in order to use GPU "
411                            "update-constraints.");
412         GMX_RELEASE_ASSERT(
413                 fr->deviceStreamManager->streamIsValid(gmx::DeviceStreamType::UpdateAndConstraints),
414                 "Update stream should be initialized in order to use GPU "
415                 "update-constraints.");
416         integrator = std::make_unique<UpdateConstrainGpu>(
417                 *ir, *top_global, fr->deviceStreamManager->context(),
418                 fr->deviceStreamManager->stream(gmx::DeviceStreamType::UpdateAndConstraints),
419                 stateGpu->xUpdatedOnDevice(), wcycle);
420
421         integrator->setPbc(PbcType::Xyz, state->box);
422     }
423
424     if (useGpuForPme || (useGpuForNonbonded && useGpuForBufferOps) || useGpuForUpdate)
425     {
426         changePinningPolicy(&state->x, PinningPolicy::PinnedIfSupported);
427     }
428     if (useGpuForUpdate)
429     {
430         changePinningPolicy(&state->v, PinningPolicy::PinnedIfSupported);
431     }
432
433     // NOTE: The global state is no longer used at this point.
434     // But state_global is still used as temporary storage space for writing
435     // the global state to file and potentially for replica exchange.
436     // (Global topology should persist.)
437
438     update_mdatoms(mdatoms, state->lambda[efptMASS]);
439
440     if (ir->bExpanded)
441     {
442         /* Check nstexpanded here, because the grompp check was broken */
443         if (ir->expandedvals->nstexpanded % ir->nstcalcenergy != 0)
444         {
445             gmx_fatal(FARGS,
446                       "With expanded ensemble, nstexpanded should be a multiple of nstcalcenergy");
447         }
448         init_expanded_ensemble(startingBehavior != StartingBehavior::NewSimulation, ir, state->dfhist);
449     }
450
451     if (MASTER(cr))
452     {
453         EnergyData::initializeEnergyHistory(startingBehavior, observablesHistory, &energyOutput);
454     }
455
456     preparePrevStepPullCom(ir, pull_work, mdatoms->massT, state, state_global, cr,
457                            startingBehavior != StartingBehavior::NewSimulation);
458
459     // TODO: Remove this by converting AWH into a ForceProvider
460     auto awh = prepareAwhModule(fplog, *ir, state_global, cr, ms,
461                                 startingBehavior != StartingBehavior::NewSimulation,
462                                 shellfc != nullptr, opt2fn("-awh", nfile, fnm), pull_work);
463
464     if (useReplicaExchange && MASTER(cr))
465     {
466         repl_ex = init_replica_exchange(fplog, ms, top_global->natoms, ir, replExParams);
467     }
468     /* PME tuning is only supported in the Verlet scheme, with PME for
469      * Coulomb. It is not supported with only LJ PME. */
470     bPMETune = (mdrunOptions.tunePme && EEL_PME(fr->ic->eeltype) && !mdrunOptions.reproducible
471                 && ir->cutoff_scheme != ecutsGROUP);
472
473     pme_load_balancing_t* pme_loadbal = nullptr;
474     if (bPMETune)
475     {
476         pme_loadbal_init(&pme_loadbal, cr, mdlog, *ir, state->box, *fr->ic, *fr->nbv, fr->pmedata,
477                          fr->nbv->useGpu());
478     }
479
480     if (!ir->bContinuation)
481     {
482         if (state->flags & (1U << estV))
483         {
484             auto v = makeArrayRef(state->v);
485             /* Set the velocities of vsites, shells and frozen atoms to zero */
486             for (i = 0; i < mdatoms->homenr; i++)
487             {
488                 if (mdatoms->ptype[i] == eptVSite || mdatoms->ptype[i] == eptShell)
489                 {
490                     clear_rvec(v[i]);
491                 }
492                 else if (mdatoms->cFREEZE)
493                 {
494                     for (m = 0; m < DIM; m++)
495                     {
496                         if (ir->opts.nFreeze[mdatoms->cFREEZE[i]][m])
497                         {
498                             v[i][m] = 0;
499                         }
500                     }
501                 }
502             }
503         }
504
505         if (constr)
506         {
507             /* Constrain the initial coordinates and velocities */
508             do_constrain_first(fplog, constr, ir, mdatoms->nr, mdatoms->homenr,
509                                state->x.arrayRefWithPadding(), state->v.arrayRefWithPadding(),
510                                state->box, state->lambda[efptBONDED]);
511         }
512         if (vsite)
513         {
514             /* Construct the virtual sites for the initial configuration */
515             vsite->construct(state->x, ir->delta_t, {}, state->box);
516         }
517     }
518
519     if (ir->efep != efepNO)
520     {
521         /* Set free energy calculation frequency as the greatest common
522          * denominator of nstdhdl and repl_ex_nst. */
523         nstfep = ir->fepvals->nstdhdl;
524         if (ir->bExpanded)
525         {
526             nstfep = std::gcd(ir->expandedvals->nstexpanded, nstfep);
527         }
528         if (useReplicaExchange)
529         {
530             nstfep = std::gcd(replExParams.exchangeInterval, nstfep);
531         }
532         if (ir->bDoAwh)
533         {
534             nstfep = std::gcd(ir->awhParams->nstSampleCoord, nstfep);
535         }
536     }
537
538     /* Be REALLY careful about what flags you set here. You CANNOT assume
539      * this is the first step, since we might be restarting from a checkpoint,
540      * and in that case we should not do any modifications to the state.
541      */
542     bStopCM = (ir->comm_mode != ecmNO && !ir->bContinuation);
543
544     // When restarting from a checkpoint, it can be appropriate to
545     // initialize ekind from quantities in the checkpoint. Otherwise,
546     // compute_globals must initialize ekind before the simulation
547     // starts/restarts. However, only the master rank knows what was
548     // found in the checkpoint file, so we have to communicate in
549     // order to coordinate the restart.
550     //
551     // TODO Consider removing this communication if/when checkpoint
552     // reading directly follows .tpr reading, because all ranks can
553     // agree on hasReadEkinState at that time.
554     bool hasReadEkinState = MASTER(cr) ? state_global->ekinstate.hasReadEkinState : false;
555     if (PAR(cr))
556     {
557         gmx_bcast(sizeof(hasReadEkinState), &hasReadEkinState, cr->mpi_comm_mygroup);
558     }
559     if (hasReadEkinState)
560     {
561         restore_ekinstate_from_state(cr, ekind, &state_global->ekinstate);
562     }
563
564     unsigned int cglo_flags =
565             (CGLO_TEMPERATURE | CGLO_GSTAT | (EI_VV(ir->eI) ? CGLO_PRESSURE : 0)
566              | (EI_VV(ir->eI) ? CGLO_CONSTRAINT : 0) | (hasReadEkinState ? CGLO_READEKIN : 0));
567
568     bSumEkinhOld = FALSE;
569
570     t_vcm vcm(top_global->groups, *ir);
571     reportComRemovalInfo(fplog, vcm);
572
573     /* To minimize communication, compute_globals computes the COM velocity
574      * and the kinetic energy for the velocities without COM motion removed.
575      * Thus to get the kinetic energy without the COM contribution, we need
576      * to call compute_globals twice.
577      */
578     for (int cgloIteration = 0; cgloIteration < (bStopCM ? 2 : 1); cgloIteration++)
579     {
580         unsigned int cglo_flags_iteration = cglo_flags;
581         if (bStopCM && cgloIteration == 0)
582         {
583             cglo_flags_iteration |= CGLO_STOPCM;
584             cglo_flags_iteration &= ~CGLO_TEMPERATURE;
585         }
586         compute_globals(gstat, cr, ir, fr, ekind, makeConstArrayRef(state->x),
587                         makeConstArrayRef(state->v), state->box, mdatoms, nrnb, &vcm, nullptr,
588                         enerd, force_vir, shake_vir, total_vir, pres, constr, &nullSignaller,
589                         state->box, &totalNumberOfBondedInteractions, &bSumEkinhOld,
590                         cglo_flags_iteration
591                                 | (shouldCheckNumberOfBondedInteractions ? CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS
592                                                                          : 0));
593         if (cglo_flags_iteration & CGLO_STOPCM)
594         {
595             /* At initialization, do not pass x with acceleration-correction mode
596              * to avoid (incorrect) correction of the initial coordinates.
597              */
598             auto x = (vcm.mode == ecmLINEAR_ACCELERATION_CORRECTION) ? ArrayRef<RVec>()
599                                                                      : makeArrayRef(state->x);
600             process_and_stopcm_grp(fplog, &vcm, *mdatoms, x, makeArrayRef(state->v));
601             inc_nrnb(nrnb, eNR_STOPCM, mdatoms->homenr);
602         }
603     }
604     checkNumberOfBondedInteractions(mdlog, cr, totalNumberOfBondedInteractions, top_global, &top,
605                                     makeConstArrayRef(state->x), state->box,
606                                     &shouldCheckNumberOfBondedInteractions);
607     if (ir->eI == eiVVAK)
608     {
609         /* a second call to get the half step temperature initialized as well */
610         /* we do the same call as above, but turn the pressure off -- internally to
611            compute_globals, this is recognized as a velocity verlet half-step
612            kinetic energy calculation.  This minimized excess variables, but
613            perhaps loses some logic?*/
614
615         compute_globals(gstat, cr, ir, fr, ekind, makeConstArrayRef(state->x),
616                         makeConstArrayRef(state->v), state->box, mdatoms, nrnb, &vcm, nullptr,
617                         enerd, force_vir, shake_vir, total_vir, pres, constr, &nullSignaller,
618                         state->box, nullptr, &bSumEkinhOld, cglo_flags & ~CGLO_PRESSURE);
619     }
620
621     /* Calculate the initial half step temperature, and save the ekinh_old */
622     if (startingBehavior == StartingBehavior::NewSimulation)
623     {
624         for (i = 0; (i < ir->opts.ngtc); i++)
625         {
626             copy_mat(ekind->tcstat[i].ekinh, ekind->tcstat[i].ekinh_old);
627         }
628     }
629
630     /* need to make an initiation call to get the Trotter variables set, as well as other constants
631        for non-trotter temperature control */
632     auto trotter_seq = init_npt_vars(ir, state, &MassQ, bTrotter);
633
634     if (MASTER(cr))
635     {
636         if (!ir->bContinuation)
637         {
638             if (constr && ir->eConstrAlg == econtLINCS)
639             {
640                 fprintf(fplog, "RMS relative constraint deviation after constraining: %.2e\n",
641                         constr->rmsd());
642             }
643             if (EI_STATE_VELOCITY(ir->eI))
644             {
645                 real temp = enerd->term[F_TEMP];
646                 if (ir->eI != eiVV)
647                 {
648                     /* Result of Ekin averaged over velocities of -half
649                      * and +half step, while we only have -half step here.
650                      */
651                     temp *= 2;
652                 }
653                 fprintf(fplog, "Initial temperature: %g K\n", temp);
654             }
655         }
656
657         char tbuf[20];
658         fprintf(stderr, "starting mdrun '%s'\n", *(top_global->name));
659         if (ir->nsteps >= 0)
660         {
661             sprintf(tbuf, "%8.1f", (ir->init_step + ir->nsteps) * ir->delta_t);
662         }
663         else
664         {
665             sprintf(tbuf, "%s", "infinite");
666         }
667         if (ir->init_step > 0)
668         {
669             fprintf(stderr, "%s steps, %s ps (continuing from step %s, %8.1f ps).\n",
670                     gmx_step_str(ir->init_step + ir->nsteps, sbuf), tbuf,
671                     gmx_step_str(ir->init_step, sbuf2), ir->init_step * ir->delta_t);
672         }
673         else
674         {
675             fprintf(stderr, "%s steps, %s ps.\n", gmx_step_str(ir->nsteps, sbuf), tbuf);
676         }
677         fprintf(fplog, "\n");
678     }
679
680     walltime_accounting_start_time(walltime_accounting);
681     wallcycle_start(wcycle, ewcRUN);
682     print_start(fplog, cr, walltime_accounting, "mdrun");
683
684     /***********************************************************
685      *
686      *             Loop over MD steps
687      *
688      ************************************************************/
689
690     bFirstStep = TRUE;
691     /* Skip the first Nose-Hoover integration when we get the state from tpx */
692     bInitStep        = startingBehavior == StartingBehavior::NewSimulation || EI_VV(ir->eI);
693     bSumEkinhOld     = FALSE;
694     bExchanged       = FALSE;
695     bNeedRepartition = FALSE;
696
697     step     = ir->init_step;
698     step_rel = 0;
699
700     auto stopHandler = stopHandlerBuilder->getStopHandlerMD(
701             compat::not_null<SimulationSignal*>(&signals[eglsSTOPCOND]), simulationsShareState,
702             MASTER(cr), ir->nstlist, mdrunOptions.reproducible, nstSignalComm,
703             mdrunOptions.maximumHoursToRun, ir->nstlist == 0, fplog, step, bNS, walltime_accounting);
704
705     auto checkpointHandler = std::make_unique<CheckpointHandler>(
706             compat::make_not_null<SimulationSignal*>(&signals[eglsCHKPT]), simulationsShareState,
707             ir->nstlist == 0, MASTER(cr), mdrunOptions.writeConfout,
708             mdrunOptions.checkpointOptions.period);
709
710     const bool resetCountersIsLocal = true;
711     auto       resetHandler         = std::make_unique<ResetHandler>(
712             compat::make_not_null<SimulationSignal*>(&signals[eglsRESETCOUNTERS]),
713             !resetCountersIsLocal, ir->nsteps, MASTER(cr), mdrunOptions.timingOptions.resetHalfway,
714             mdrunOptions.maximumHoursToRun, mdlog, wcycle, walltime_accounting);
715
716     const DDBalanceRegionHandler ddBalanceRegionHandler(cr);
717
718     if (MASTER(cr) && isMultiSim(ms) && !useReplicaExchange)
719     {
720         logInitialMultisimStatus(ms, cr, mdlog, simulationsShareState, ir->nsteps, ir->init_step);
721     }
722
723     /* and stop now if we should */
724     bLastStep = (bLastStep || (ir->nsteps >= 0 && step_rel > ir->nsteps));
725     while (!bLastStep)
726     {
727
728         /* Determine if this is a neighbor search step */
729         bNStList = (ir->nstlist > 0 && step % ir->nstlist == 0);
730
731         if (bPMETune && bNStList)
732         {
733             // This has to be here because PME load balancing is called so early.
734             // TODO: Move to after all booleans are defined.
735             if (useGpuForUpdate && !bFirstStep)
736             {
737                 stateGpu->copyCoordinatesFromGpu(state->x, AtomLocality::Local);
738                 stateGpu->waitCoordinatesReadyOnHost(AtomLocality::Local);
739             }
740             /* PME grid + cut-off optimization with GPUs or PME nodes */
741             pme_loadbal_do(pme_loadbal, cr, (mdrunOptions.verbose && MASTER(cr)) ? stderr : nullptr,
742                            fplog, mdlog, *ir, fr, state->box, state->x, wcycle, step, step_rel,
743                            &bPMETunePrinting, simulationWork.useGpuPmePpCommunication);
744         }
745
746         wallcycle_start(wcycle, ewcSTEP);
747
748         bLastStep = (step_rel == ir->nsteps);
749         t         = t0 + step * ir->delta_t;
750
751         // TODO Refactor this, so that nstfep does not need a default value of zero
752         if (ir->efep != efepNO || ir->bSimTemp)
753         {
754             /* find and set the current lambdas */
755             state->lambda = currentLambdas(step, *(ir->fepvals), state->fep_state);
756
757             bDoDHDL     = do_per_step(step, ir->fepvals->nstdhdl);
758             bDoFEP      = ((ir->efep != efepNO) && do_per_step(step, nstfep));
759             bDoExpanded = (do_per_step(step, ir->expandedvals->nstexpanded) && (ir->bExpanded)
760                            && (!bFirstStep));
761         }
762
763         bDoReplEx = (useReplicaExchange && (step > 0) && !bLastStep
764                      && do_per_step(step, replExParams.exchangeInterval));
765
766         if (doSimulatedAnnealing)
767         {
768             update_annealing_target_temp(ir, t, &upd);
769         }
770
771         /* Stop Center of Mass motion */
772         bStopCM = (ir->comm_mode != ecmNO && do_per_step(step, ir->nstcomm));
773
774         /* Determine whether or not to do Neighbour Searching */
775         bNS = (bFirstStep || bNStList || bExchanged || bNeedRepartition);
776
777         /* Note that the stopHandler will cause termination at nstglobalcomm
778          * steps. Since this concides with nstcalcenergy, nsttcouple and/or
779          * nstpcouple steps, we have computed the half-step kinetic energy
780          * of the previous step and can always output energies at the last step.
781          */
782         bLastStep = bLastStep || stopHandler->stoppingAfterCurrentStep(bNS);
783
784         /* do_log triggers energy and virial calculation. Because this leads
785          * to different code paths, forces can be different. Thus for exact
786          * continuation we should avoid extra log output.
787          * Note that the || bLastStep can result in non-exact continuation
788          * beyond the last step. But we don't consider that to be an issue.
789          */
790         do_log     = (do_per_step(step, ir->nstlog)
791                   || (bFirstStep && startingBehavior == StartingBehavior::NewSimulation) || bLastStep);
792         do_verbose = mdrunOptions.verbose
793                      && (step % mdrunOptions.verboseStepPrintInterval == 0 || bFirstStep || bLastStep);
794
795         if (useGpuForUpdate && !bFirstStep && bNS)
796         {
797             // Copy velocities from the GPU on search steps to keep a copy on host (device buffers are reinitialized).
798             stateGpu->copyVelocitiesFromGpu(state->v, AtomLocality::Local);
799             stateGpu->waitVelocitiesReadyOnHost(AtomLocality::Local);
800             // Copy coordinate from the GPU when needed at the search step.
801             // NOTE: The cases when coordinates needed on CPU for force evaluation are handled in sim_utils.
802             // NOTE: If the coordinates are to be written into output file they are also copied separately before the output.
803             stateGpu->copyCoordinatesFromGpu(state->x, AtomLocality::Local);
804             stateGpu->waitCoordinatesReadyOnHost(AtomLocality::Local);
805         }
806
807         if (bNS && !(bFirstStep && ir->bContinuation))
808         {
809             bMasterState = FALSE;
810             /* Correct the new box if it is too skewed */
811             if (inputrecDynamicBox(ir))
812             {
813                 if (correct_box(fplog, step, state->box))
814                 {
815                     bMasterState = TRUE;
816                     // If update is offloaded, it should be informed about the box size change
817                     if (useGpuForUpdate)
818                     {
819                         integrator->setPbc(PbcType::Xyz, state->box);
820                     }
821                 }
822             }
823             if (DOMAINDECOMP(cr) && bMasterState)
824             {
825                 dd_collect_state(cr->dd, state, state_global);
826             }
827
828             if (DOMAINDECOMP(cr))
829             {
830                 /* Repartition the domain decomposition */
831                 dd_partition_system(fplog, mdlog, step, cr, bMasterState, nstglobalcomm, state_global,
832                                     *top_global, ir, imdSession, pull_work, state, &f, mdAtoms, &top,
833                                     fr, vsite, constr, nrnb, wcycle, do_verbose && !bPMETunePrinting);
834                 shouldCheckNumberOfBondedInteractions = true;
835                 upd.setNumAtoms(state->natoms);
836             }
837         }
838
839         // Allocate or re-size GPU halo exchange object, if necessary
840         if (bNS && havePPDomainDecomposition(cr) && simulationWork.useGpuHaloExchange)
841         {
842             GMX_RELEASE_ASSERT(fr->deviceStreamManager != nullptr,
843                                "GPU device manager has to be initialized to use GPU "
844                                "version of halo exchange.");
845             constructGpuHaloExchange(mdlog, *cr, *fr->deviceStreamManager, wcycle);
846         }
847
848         if (MASTER(cr) && do_log)
849         {
850             gmx::EnergyOutput::printHeader(fplog, step,
851                                            t); /* can we improve the information printed here? */
852         }
853
854         if (ir->efep != efepNO)
855         {
856             update_mdatoms(mdatoms, state->lambda[efptMASS]);
857         }
858
859         if (bExchanged)
860         {
861             /* We need the kinetic energy at minus the half step for determining
862              * the full step kinetic energy and possibly for T-coupling.*/
863             /* This may not be quite working correctly yet . . . . */
864             compute_globals(gstat, cr, ir, fr, ekind, makeConstArrayRef(state->x),
865                             makeConstArrayRef(state->v), state->box, mdatoms, nrnb, &vcm, wcycle,
866                             enerd, nullptr, nullptr, nullptr, nullptr, constr, &nullSignaller,
867                             state->box, &totalNumberOfBondedInteractions, &bSumEkinhOld,
868                             CGLO_GSTAT | CGLO_TEMPERATURE | CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS);
869             checkNumberOfBondedInteractions(mdlog, cr, totalNumberOfBondedInteractions, top_global,
870                                             &top, makeConstArrayRef(state->x), state->box,
871                                             &shouldCheckNumberOfBondedInteractions);
872         }
873         clear_mat(force_vir);
874
875         checkpointHandler->decideIfCheckpointingThisStep(bNS, bFirstStep, bLastStep);
876
877         /* Determine the energy and pressure:
878          * at nstcalcenergy steps and at energy output steps (set below).
879          */
880         if (EI_VV(ir->eI) && (!bInitStep))
881         {
882             bCalcEnerStep = do_per_step(step, ir->nstcalcenergy);
883             bCalcVir      = bCalcEnerStep
884                        || (ir->epc != epcNO
885                            && (do_per_step(step, ir->nstpcouple) || do_per_step(step - 1, ir->nstpcouple)));
886         }
887         else
888         {
889             bCalcEnerStep = do_per_step(step, ir->nstcalcenergy);
890             bCalcVir = bCalcEnerStep || (ir->epc != epcNO && do_per_step(step, ir->nstpcouple));
891         }
892         bCalcEner = bCalcEnerStep;
893
894         do_ene = (do_per_step(step, ir->nstenergy) || bLastStep);
895
896         if (do_ene || do_log || bDoReplEx)
897         {
898             bCalcVir  = TRUE;
899             bCalcEner = TRUE;
900         }
901
902         /* Do we need global communication ? */
903         bGStat = (bCalcVir || bCalcEner || bStopCM || do_per_step(step, nstglobalcomm)
904                   || (EI_VV(ir->eI) && inputrecNvtTrotter(ir) && do_per_step(step - 1, nstglobalcomm)));
905
906         force_flags = (GMX_FORCE_STATECHANGED | ((inputrecDynamicBox(ir)) ? GMX_FORCE_DYNAMICBOX : 0)
907                        | GMX_FORCE_ALLFORCES | (bCalcVir ? GMX_FORCE_VIRIAL : 0)
908                        | (bCalcEner ? GMX_FORCE_ENERGY : 0) | (bDoFEP ? GMX_FORCE_DHDL : 0));
909         if (fr->useMts && !do_per_step(step, ir->nstfout))
910         {
911             force_flags |= GMX_FORCE_DO_NOT_NEED_NORMAL_FORCE;
912         }
913
914         if (shellfc)
915         {
916             /* Now is the time to relax the shells */
917             relax_shell_flexcon(fplog, cr, ms, mdrunOptions.verbose, enforcedRotation, step, ir,
918                                 imdSession, pull_work, bNS, force_flags, &top, constr, enerd,
919                                 state->natoms, state->x.arrayRefWithPadding(),
920                                 state->v.arrayRefWithPadding(), state->box, state->lambda,
921                                 &state->hist, &f.view(), force_vir, mdatoms, nrnb, wcycle, shellfc,
922                                 fr, runScheduleWork, t, mu_tot, vsite, ddBalanceRegionHandler);
923         }
924         else
925         {
926             /* The AWH history need to be saved _before_ doing force calculations where the AWH bias
927                is updated (or the AWH update will be performed twice for one step when continuing).
928                It would be best to call this update function from do_md_trajectory_writing but that
929                would occur after do_force. One would have to divide the update_awh function into one
930                function applying the AWH force and one doing the AWH bias update. The update AWH
931                bias function could then be called after do_md_trajectory_writing (then containing
932                update_awh_history). The checkpointing will in the future probably moved to the start
933                of the md loop which will rid of this issue. */
934             if (awh && checkpointHandler->isCheckpointingStep() && MASTER(cr))
935             {
936                 awh->updateHistory(state_global->awhHistory.get());
937             }
938
939             /* The coordinates (x) are shifted (to get whole molecules)
940              * in do_force.
941              * This is parallellized as well, and does communication too.
942              * Check comments in sim_util.c
943              */
944             do_force(fplog, cr, ms, ir, awh.get(), enforcedRotation, imdSession, pull_work, step,
945                      nrnb, wcycle, &top, state->box, state->x.arrayRefWithPadding(), &state->hist,
946                      &f.view(), force_vir, mdatoms, enerd, state->lambda, fr, runScheduleWork,
947                      vsite, mu_tot, t, ed ? ed->getLegacyED() : nullptr,
948                      (bNS ? GMX_FORCE_NS : 0) | force_flags, ddBalanceRegionHandler);
949         }
950
951         // VV integrators do not need the following velocity half step
952         // if it is the first step after starting from a checkpoint.
953         // That is, the half step is needed on all other steps, and
954         // also the first step when starting from a .tpr file.
955         if (EI_VV(ir->eI))
956         {
957             integrateVVFirstStep(step, bFirstStep, bInitStep, startingBehavior, nstglobalcomm, ir,
958                                  fr, cr, state, mdatoms, fcdata, &MassQ, &vcm, top_global, top, enerd,
959                                  ekind, gstat, &last_ekin, bCalcVir, total_vir, shake_vir, force_vir,
960                                  pres, M, do_log, do_ene, bCalcEner, bGStat, bStopCM, bTrotter,
961                                  bExchanged, &bSumEkinhOld, &shouldCheckNumberOfBondedInteractions,
962                                  &saved_conserved_quantity, &f, &upd, constr, &nullSignaller,
963                                  trotter_seq, nrnb, mdlog, fplog, wcycle);
964         }
965
966         /* ########  END FIRST UPDATE STEP  ############## */
967         /* ########  If doing VV, we now have v(dt) ###### */
968         if (bDoExpanded)
969         {
970             /* perform extended ensemble sampling in lambda - we don't
971                actually move to the new state before outputting
972                statistics, but if performing simulated tempering, we
973                do update the velocities and the tau_t. */
974
975             lamnew = ExpandedEnsembleDynamics(fplog, ir, enerd, state, &MassQ, state->fep_state,
976                                               state->dfhist, step, state->v.rvec_array(), mdatoms);
977             /* history is maintained in state->dfhist, but state_global is what is sent to trajectory and log output */
978             if (MASTER(cr))
979             {
980                 copy_df_history(state_global->dfhist, state->dfhist);
981             }
982         }
983
984         // Copy coordinate from the GPU for the output/checkpointing if the update is offloaded and
985         // coordinates have not already been copied for i) search or ii) CPU force tasks.
986         if (useGpuForUpdate && !bNS && !runScheduleWork->domainWork.haveCpuLocalForceWork
987             && (do_per_step(step, ir->nstxout) || do_per_step(step, ir->nstxout_compressed)
988                 || checkpointHandler->isCheckpointingStep()))
989         {
990             stateGpu->copyCoordinatesFromGpu(state->x, AtomLocality::Local);
991             stateGpu->waitCoordinatesReadyOnHost(AtomLocality::Local);
992         }
993         // Copy velocities if needed for the output/checkpointing.
994         // NOTE: Copy on the search steps is done at the beginning of the step.
995         if (useGpuForUpdate && !bNS
996             && (do_per_step(step, ir->nstvout) || checkpointHandler->isCheckpointingStep()))
997         {
998             stateGpu->copyVelocitiesFromGpu(state->v, AtomLocality::Local);
999             stateGpu->waitVelocitiesReadyOnHost(AtomLocality::Local);
1000         }
1001         // Copy forces for the output if the forces were reduced on the GPU (not the case on virial steps)
1002         // and update is offloaded hence forces are kept on the GPU for update and have not been
1003         // already transferred in do_force().
1004         // TODO: There should be an improved, explicit mechanism that ensures this copy is only executed
1005         //       when the forces are ready on the GPU -- the same synchronizer should be used as the one
1006         //       prior to GPU update.
1007         // TODO: When the output flags will be included in step workload, this copy can be combined with the
1008         //       copy call in do_force(...).
1009         // NOTE: The forces should not be copied here if the vsites are present, since they were modified
1010         //       on host after the D2H copy in do_force(...).
1011         if (runScheduleWork->stepWork.useGpuFBufferOps && (simulationWork.useGpuUpdate && !vsite)
1012             && do_per_step(step, ir->nstfout))
1013         {
1014             stateGpu->copyForcesFromGpu(f.view().force(), AtomLocality::Local);
1015             stateGpu->waitForcesReadyOnHost(AtomLocality::Local);
1016         }
1017         /* Now we have the energies and forces corresponding to the
1018          * coordinates at time t. We must output all of this before
1019          * the update.
1020          */
1021         do_md_trajectory_writing(fplog, cr, nfile, fnm, step, step_rel, t, ir, state, state_global,
1022                                  observablesHistory, top_global, fr, outf, energyOutput, ekind,
1023                                  f.view().force(), checkpointHandler->isCheckpointingStep(),
1024                                  bRerunMD, bLastStep, mdrunOptions.writeConfout, bSumEkinhOld);
1025         /* Check if IMD step and do IMD communication, if bIMD is TRUE. */
1026         bInteractiveMDstep = imdSession->run(step, bNS, state->box, state->x.rvec_array(), t);
1027
1028         /* kludge -- virial is lost with restart for MTTK NPT control. Must reload (saved earlier). */
1029         if (startingBehavior != StartingBehavior::NewSimulation && bFirstStep
1030             && (inputrecNptTrotter(ir) || inputrecNphTrotter(ir)))
1031         {
1032             copy_mat(state->svir_prev, shake_vir);
1033             copy_mat(state->fvir_prev, force_vir);
1034         }
1035
1036         stopHandler->setSignal();
1037         resetHandler->setSignal(walltime_accounting);
1038
1039         if (bGStat || !PAR(cr))
1040         {
1041             /* In parallel we only have to check for checkpointing in steps
1042              * where we do global communication,
1043              *  otherwise the other nodes don't know.
1044              */
1045             checkpointHandler->setSignal(walltime_accounting);
1046         }
1047
1048         /* #########   START SECOND UPDATE STEP ################# */
1049
1050         /* at the start of step, randomize or scale the velocities ((if vv. Restriction of Andersen
1051            controlled in preprocessing */
1052
1053         if (ETC_ANDERSEN(ir->etc)) /* keep this outside of update_tcouple because of the extra info required to pass */
1054         {
1055             gmx_bool bIfRandomize;
1056             bIfRandomize = update_randomize_velocities(ir, step, cr, mdatoms, state->v, &upd, constr);
1057             /* if we have constraints, we have to remove the kinetic energy parallel to the bonds */
1058             if (constr && bIfRandomize)
1059             {
1060                 constrain_velocities(constr, do_log, do_ene, step, state, nullptr, false, nullptr);
1061             }
1062         }
1063         /* Box is changed in update() when we do pressure coupling,
1064          * but we should still use the old box for energy corrections and when
1065          * writing it to the energy file, so it matches the trajectory files for
1066          * the same timestep above. Make a copy in a separate array.
1067          */
1068         copy_mat(state->box, lastbox);
1069
1070         dvdl_constr = 0;
1071
1072         wallcycle_start(wcycle, ewcUPDATE);
1073         /* UPDATE PRESSURE VARIABLES IN TROTTER FORMULATION WITH CONSTRAINTS */
1074         if (bTrotter)
1075         {
1076             trotter_update(ir, step, ekind, enerd, state, total_vir, mdatoms, &MassQ, trotter_seq, ettTSEQ3);
1077             /* We can only do Berendsen coupling after we have summed
1078              * the kinetic energy or virial. Since the happens
1079              * in global_state after update, we should only do it at
1080              * step % nstlist = 1 with bGStatEveryStep=FALSE.
1081              */
1082         }
1083         else
1084         {
1085             update_tcouple(step, ir, state, ekind, &MassQ, mdatoms);
1086             update_pcouple_before_coordinates(fplog, step, ir, state, pressureCouplingMu, M, bInitStep);
1087         }
1088
1089         /* With leap-frog type integrators we compute the kinetic energy
1090          * at a whole time step as the average of the half-time step kinetic
1091          * energies of two subsequent steps. Therefore we need to compute the
1092          * half step kinetic energy also if we need energies at the next step.
1093          */
1094         const bool needHalfStepKineticEnergy =
1095                 (!EI_VV(ir->eI) && (do_per_step(step + 1, nstglobalcomm) || step_rel + 1 == ir->nsteps));
1096
1097         // Parrinello-Rahman requires the pressure to be availible before the update to compute
1098         // the velocity scaling matrix. Hence, it runs one step after the nstpcouple step.
1099         const bool doParrinelloRahman = (ir->epc == epcPARRINELLORAHMAN
1100                                          && do_per_step(step + ir->nstpcouple - 1, ir->nstpcouple));
1101
1102         if (EI_VV(ir->eI))
1103         {
1104             GMX_ASSERT(!useGpuForUpdate, "GPU update is not supported with VVAK integrator.");
1105
1106             integrateVVSecondStep(step, ir, fr, cr, state, mdatoms, fcdata, &MassQ, &vcm, pull_work,
1107                                   enerd, ekind, gstat, &dvdl_constr, bCalcVir, total_vir, shake_vir,
1108                                   force_vir, pres, M, lastbox, do_log, do_ene, bGStat, &bSumEkinhOld,
1109                                   &f, &cbuf, &upd, constr, &nullSignaller, trotter_seq, nrnb, wcycle);
1110         }
1111         else
1112         {
1113             if (useGpuForUpdate)
1114             {
1115
1116                 wallcycle_stop(wcycle, ewcUPDATE);
1117
1118                 if (bNS && (bFirstStep || DOMAINDECOMP(cr)))
1119                 {
1120                     integrator->set(stateGpu->getCoordinates(), stateGpu->getVelocities(),
1121                                     stateGpu->getForces(), top.idef, *mdatoms, ekind->ngtc);
1122
1123                     // Copy data to the GPU after buffers might have being reinitialized
1124                     stateGpu->copyVelocitiesToGpu(state->v, AtomLocality::Local);
1125                     stateGpu->copyCoordinatesToGpu(state->x, AtomLocality::Local);
1126                 }
1127
1128                 if (simulationWork.useGpuPme && !runScheduleWork->simulationWork.useGpuPmePpCommunication
1129                     && !thisRankHasDuty(cr, DUTY_PME))
1130                 {
1131                     // The PME forces were recieved to the host, so have to be copied
1132                     stateGpu->copyForcesToGpu(f.view().force(), AtomLocality::All);
1133                 }
1134                 else if (!runScheduleWork->stepWork.useGpuFBufferOps)
1135                 {
1136                     // The buffer ops were not offloaded this step, so the forces are on the
1137                     // host and have to be copied
1138                     stateGpu->copyForcesToGpu(f.view().force(), AtomLocality::Local);
1139                 }
1140
1141                 const bool doTemperatureScaling =
1142                         (ir->etc != etcNO && do_per_step(step + ir->nsttcouple - 1, ir->nsttcouple));
1143
1144                 // This applies Leap-Frog, LINCS and SETTLE in succession
1145                 integrator->integrate(
1146                         stateGpu->getForcesReadyOnDeviceEvent(
1147                                 AtomLocality::Local, runScheduleWork->stepWork.useGpuFBufferOps),
1148                         ir->delta_t, true, bCalcVir, shake_vir, doTemperatureScaling, ekind->tcstat,
1149                         doParrinelloRahman, ir->nstpcouple * ir->delta_t, M);
1150
1151                 // Copy velocities D2H after update if:
1152                 // - Globals are computed this step (includes the energy output steps).
1153                 // - Temperature is needed for the next step.
1154                 if (bGStat || needHalfStepKineticEnergy)
1155                 {
1156                     stateGpu->copyVelocitiesFromGpu(state->v, AtomLocality::Local);
1157                     stateGpu->waitVelocitiesReadyOnHost(AtomLocality::Local);
1158                 }
1159             }
1160             else
1161             {
1162                 /* With multiple time stepping we need to do an additional normal
1163                  * update step to obtain the virial, as the actual MTS integration
1164                  * using an acceleration where the slow forces are multiplied by mtsFactor.
1165                  * Using that acceleration would result in a virial with the slow
1166                  * force contribution would be a factor mtsFactor too large.
1167                  */
1168                 if (fr->useMts && bCalcVir && constr != nullptr)
1169                 {
1170                     upd.update_for_constraint_virial(*ir, *mdatoms, *state,
1171                                                      f.view().forceWithPadding(), *ekind);
1172
1173                     constrain_coordinates(constr, do_log, do_ene, step, state,
1174                                           upd.xp()->arrayRefWithPadding(), &dvdl_constr, bCalcVir,
1175                                           shake_vir);
1176                 }
1177
1178                 ArrayRefWithPadding<const RVec> forceCombined =
1179                         (fr->useMts && step % ir->mtsLevels[1].stepFactor == 0)
1180                                 ? f.view().forceMtsCombinedWithPadding()
1181                                 : f.view().forceWithPadding();
1182                 upd.update_coords(*ir, step, mdatoms, state, forceCombined, fcdata, ekind, M,
1183                                   etrtPOSITION, cr, constr != nullptr);
1184
1185                 wallcycle_stop(wcycle, ewcUPDATE);
1186
1187                 constrain_coordinates(constr, do_log, do_ene, step, state,
1188                                       upd.xp()->arrayRefWithPadding(), &dvdl_constr,
1189                                       bCalcVir && !fr->useMts, shake_vir);
1190
1191                 upd.update_sd_second_half(*ir, step, &dvdl_constr, mdatoms, state, cr, nrnb, wcycle,
1192                                           constr, do_log, do_ene);
1193                 upd.finish_update(*ir, mdatoms, state, wcycle, constr != nullptr);
1194             }
1195
1196             if (ir->bPull && ir->pull->bSetPbcRefToPrevStepCOM)
1197             {
1198                 updatePrevStepPullCom(pull_work, state);
1199             }
1200
1201             enerd->term[F_DVDL_CONSTR] += dvdl_constr;
1202         }
1203
1204         if (vsite != nullptr)
1205         {
1206             wallcycle_start(wcycle, ewcVSITECONSTR);
1207             vsite->construct(state->x, ir->delta_t, state->v, state->box);
1208             wallcycle_stop(wcycle, ewcVSITECONSTR);
1209         }
1210
1211         /* ############## IF NOT VV, Calculate globals HERE  ############ */
1212         /* With Leap-Frog we can skip compute_globals at
1213          * non-communication steps, but we need to calculate
1214          * the kinetic energy one step before communication.
1215          */
1216         {
1217             // Organize to do inter-simulation signalling on steps if
1218             // and when algorithms require it.
1219             const bool doInterSimSignal = (simulationsShareState && do_per_step(step, nstSignalComm));
1220
1221             if (bGStat || needHalfStepKineticEnergy || doInterSimSignal)
1222             {
1223                 // Copy coordinates when needed to stop the CM motion.
1224                 if (useGpuForUpdate && !EI_VV(ir->eI) && bStopCM)
1225                 {
1226                     stateGpu->copyCoordinatesFromGpu(state->x, AtomLocality::Local);
1227                     stateGpu->waitCoordinatesReadyOnHost(AtomLocality::Local);
1228                 }
1229                 // Since we're already communicating at this step, we
1230                 // can propagate intra-simulation signals. Note that
1231                 // check_nstglobalcomm has the responsibility for
1232                 // choosing the value of nstglobalcomm that is one way
1233                 // bGStat becomes true, so we can't get into a
1234                 // situation where e.g. checkpointing can't be
1235                 // signalled.
1236                 bool                doIntraSimSignal = true;
1237                 SimulationSignaller signaller(&signals, cr, ms, doInterSimSignal, doIntraSimSignal);
1238
1239                 compute_globals(gstat, cr, ir, fr, ekind, makeConstArrayRef(state->x),
1240                                 makeConstArrayRef(state->v), state->box, mdatoms, nrnb, &vcm,
1241                                 wcycle, enerd, force_vir, shake_vir, total_vir, pres, constr,
1242                                 &signaller, lastbox, &totalNumberOfBondedInteractions, &bSumEkinhOld,
1243                                 (bGStat ? CGLO_GSTAT : 0) | (!EI_VV(ir->eI) && bCalcEner ? CGLO_ENERGY : 0)
1244                                         | (!EI_VV(ir->eI) && bStopCM ? CGLO_STOPCM : 0)
1245                                         | (!EI_VV(ir->eI) ? CGLO_TEMPERATURE : 0)
1246                                         | (!EI_VV(ir->eI) ? CGLO_PRESSURE : 0) | CGLO_CONSTRAINT
1247                                         | (shouldCheckNumberOfBondedInteractions ? CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS
1248                                                                                  : 0));
1249                 checkNumberOfBondedInteractions(mdlog, cr, totalNumberOfBondedInteractions,
1250                                                 top_global, &top, makeConstArrayRef(state->x),
1251                                                 state->box, &shouldCheckNumberOfBondedInteractions);
1252                 if (!EI_VV(ir->eI) && bStopCM)
1253                 {
1254                     process_and_stopcm_grp(fplog, &vcm, *mdatoms, makeArrayRef(state->x),
1255                                            makeArrayRef(state->v));
1256                     inc_nrnb(nrnb, eNR_STOPCM, mdatoms->homenr);
1257
1258                     // TODO: The special case of removing CM motion should be dealt more gracefully
1259                     if (useGpuForUpdate)
1260                     {
1261                         stateGpu->copyCoordinatesToGpu(state->x, AtomLocality::Local);
1262                         // Here we block until the H2D copy completes because event sync with the
1263                         // force kernels that use the coordinates on the next steps is not implemented
1264                         // (not because of a race on state->x being modified on the CPU while H2D is in progress).
1265                         stateGpu->waitCoordinatesCopiedToDevice(AtomLocality::Local);
1266                         // If the COM removal changed the velocities on the CPU, this has to be accounted for.
1267                         if (vcm.mode != ecmNO)
1268                         {
1269                             stateGpu->copyVelocitiesToGpu(state->v, AtomLocality::Local);
1270                         }
1271                     }
1272                 }
1273             }
1274         }
1275
1276         /* #############  END CALC EKIN AND PRESSURE ################# */
1277
1278         /* Note: this is OK, but there are some numerical precision issues with using the convergence of
1279            the virial that should probably be addressed eventually. state->veta has better properies,
1280            but what we actually need entering the new cycle is the new shake_vir value. Ideally, we could
1281            generate the new shake_vir, but test the veta value for convergence.  This will take some thought. */
1282
1283         if (ir->efep != efepNO && !EI_VV(ir->eI))
1284         {
1285             /* Sum up the foreign energy and dK/dl terms for md and sd.
1286                Currently done every step so that dH/dl is correct in the .edr */
1287             accumulateKineticLambdaComponents(enerd, state->lambda, *ir->fepvals);
1288         }
1289
1290         update_pcouple_after_coordinates(fplog, step, ir, mdatoms, pres, force_vir, shake_vir,
1291                                          pressureCouplingMu, state, nrnb, upd.deform(), !useGpuForUpdate);
1292
1293         const bool doBerendsenPressureCoupling =
1294                 (inputrec->epc == epcBERENDSEN && do_per_step(step, inputrec->nstpcouple));
1295         const bool doCRescalePressureCoupling =
1296                 (inputrec->epc == epcCRESCALE && do_per_step(step, inputrec->nstpcouple));
1297         if (useGpuForUpdate
1298             && (doBerendsenPressureCoupling || doCRescalePressureCoupling || doParrinelloRahman))
1299         {
1300             integrator->scaleCoordinates(pressureCouplingMu);
1301             if (doCRescalePressureCoupling)
1302             {
1303                 matrix pressureCouplingInvMu;
1304                 gmx::invertBoxMatrix(pressureCouplingMu, pressureCouplingInvMu);
1305                 integrator->scaleVelocities(pressureCouplingInvMu);
1306             }
1307             integrator->setPbc(PbcType::Xyz, state->box);
1308         }
1309
1310         /* ################# END UPDATE STEP 2 ################# */
1311         /* #### We now have r(t+dt) and v(t+dt/2)  ############# */
1312
1313         /* The coordinates (x) were unshifted in update */
1314         if (!bGStat)
1315         {
1316             /* We will not sum ekinh_old,
1317              * so signal that we still have to do it.
1318              */
1319             bSumEkinhOld = TRUE;
1320         }
1321
1322         if (bCalcEner)
1323         {
1324             /* #########  BEGIN PREPARING EDR OUTPUT  ###########  */
1325
1326             /* use the directly determined last velocity, not actually the averaged half steps */
1327             if (bTrotter && ir->eI == eiVV)
1328             {
1329                 enerd->term[F_EKIN] = last_ekin;
1330             }
1331             enerd->term[F_ETOT] = enerd->term[F_EPOT] + enerd->term[F_EKIN];
1332
1333             if (integratorHasConservedEnergyQuantity(ir))
1334             {
1335                 if (EI_VV(ir->eI))
1336                 {
1337                     enerd->term[F_ECONSERVED] = enerd->term[F_ETOT] + saved_conserved_quantity;
1338                 }
1339                 else
1340                 {
1341                     enerd->term[F_ECONSERVED] = enerd->term[F_ETOT] + NPT_energy(ir, state, &MassQ);
1342                 }
1343             }
1344             /* #########  END PREPARING EDR OUTPUT  ###########  */
1345         }
1346
1347         /* Output stuff */
1348         if (MASTER(cr))
1349         {
1350             if (fplog && do_log && bDoExpanded)
1351             {
1352                 /* only needed if doing expanded ensemble */
1353                 PrintFreeEnergyInfoToFile(fplog, ir->fepvals, ir->expandedvals,
1354                                           ir->bSimTemp ? ir->simtempvals : nullptr,
1355                                           state_global->dfhist, state->fep_state, ir->nstlog, step);
1356             }
1357             if (bCalcEner)
1358             {
1359                 energyOutput.addDataAtEnergyStep(
1360                         bDoDHDL, bCalcEnerStep, t, mdatoms->tmass, enerd, ir->fepvals,
1361                         ir->expandedvals, lastbox,
1362                         PTCouplingArrays{ state->boxv, state->nosehoover_xi, state->nosehoover_vxi,
1363                                           state->nhpres_xi, state->nhpres_vxi },
1364                         state->fep_state, shake_vir, force_vir, total_vir, pres, ekind, mu_tot, constr);
1365             }
1366             else
1367             {
1368                 energyOutput.recordNonEnergyStep();
1369             }
1370
1371             gmx_bool do_dr = do_per_step(step, ir->nstdisreout);
1372             gmx_bool do_or = do_per_step(step, ir->nstorireout);
1373
1374             if (doSimulatedAnnealing)
1375             {
1376                 gmx::EnergyOutput::printAnnealingTemperatures(do_log ? fplog : nullptr, groups,
1377                                                               &(ir->opts));
1378             }
1379             if (do_log || do_ene || do_dr || do_or)
1380             {
1381                 energyOutput.printStepToEnergyFile(mdoutf_get_fp_ene(outf), do_ene, do_dr, do_or,
1382                                                    do_log ? fplog : nullptr, step, t,
1383                                                    fr->fcdata.get(), awh.get());
1384             }
1385             if (do_log && ir->bDoAwh && awh->hasFepLambdaDimension())
1386             {
1387                 const bool isInitialOutput = false;
1388                 printLambdaStateToLog(fplog, state->lambda, isInitialOutput);
1389             }
1390
1391             if (ir->bPull)
1392             {
1393                 pull_print_output(pull_work, step, t);
1394             }
1395
1396             if (do_per_step(step, ir->nstlog))
1397             {
1398                 if (fflush(fplog) != 0)
1399                 {
1400                     gmx_fatal(FARGS, "Cannot flush logfile - maybe you are out of disk space?");
1401                 }
1402             }
1403         }
1404         if (bDoExpanded)
1405         {
1406             /* Have to do this part _after_ outputting the logfile and the edr file */
1407             /* Gets written into the state at the beginning of next loop*/
1408             state->fep_state = lamnew;
1409         }
1410         else if (ir->bDoAwh && awh->needForeignEnergyDifferences(step))
1411         {
1412             state->fep_state = awh->fepLambdaState();
1413         }
1414         /* Print the remaining wall clock time for the run */
1415         if (isMasterSimMasterRank(ms, MASTER(cr)) && (do_verbose || gmx_got_usr_signal()) && !bPMETunePrinting)
1416         {
1417             if (shellfc)
1418             {
1419                 fprintf(stderr, "\n");
1420             }
1421             print_time(stderr, walltime_accounting, step, ir, cr);
1422         }
1423
1424         /* Ion/water position swapping.
1425          * Not done in last step since trajectory writing happens before this call
1426          * in the MD loop and exchanges would be lost anyway. */
1427         bNeedRepartition = FALSE;
1428         if ((ir->eSwapCoords != eswapNO) && (step > 0) && !bLastStep && do_per_step(step, ir->swap->nstswap))
1429         {
1430             bNeedRepartition =
1431                     do_swapcoords(cr, step, t, ir, swap, wcycle, as_rvec_array(state->x.data()),
1432                                   state->box, MASTER(cr) && mdrunOptions.verbose, bRerunMD);
1433
1434             if (bNeedRepartition && DOMAINDECOMP(cr))
1435             {
1436                 dd_collect_state(cr->dd, state, state_global);
1437             }
1438         }
1439
1440         /* Replica exchange */
1441         bExchanged = FALSE;
1442         if (bDoReplEx)
1443         {
1444             bExchanged = replica_exchange(fplog, cr, ms, repl_ex, state_global, enerd, state, step, t);
1445         }
1446
1447         if ((bExchanged || bNeedRepartition) && DOMAINDECOMP(cr))
1448         {
1449             dd_partition_system(fplog, mdlog, step, cr, TRUE, 1, state_global, *top_global, ir,
1450                                 imdSession, pull_work, state, &f, mdAtoms, &top, fr, vsite, constr,
1451                                 nrnb, wcycle, FALSE);
1452             shouldCheckNumberOfBondedInteractions = true;
1453             upd.setNumAtoms(state->natoms);
1454         }
1455
1456         bFirstStep = FALSE;
1457         bInitStep  = FALSE;
1458
1459         /* #######  SET VARIABLES FOR NEXT ITERATION IF THEY STILL NEED IT ###### */
1460         /* With all integrators, except VV, we need to retain the pressure
1461          * at the current step for coupling at the next step.
1462          */
1463         if ((state->flags & (1U << estPRES_PREV))
1464             && (bGStatEveryStep || (ir->nstpcouple > 0 && step % ir->nstpcouple == 0)))
1465         {
1466             /* Store the pressure in t_state for pressure coupling
1467              * at the next MD step.
1468              */
1469             copy_mat(pres, state->pres_prev);
1470         }
1471
1472         /* #######  END SET VARIABLES FOR NEXT ITERATION ###### */
1473
1474         if ((membed != nullptr) && (!bLastStep))
1475         {
1476             rescale_membed(step_rel, membed, as_rvec_array(state_global->x.data()));
1477         }
1478
1479         cycles = wallcycle_stop(wcycle, ewcSTEP);
1480         if (DOMAINDECOMP(cr) && wcycle)
1481         {
1482             dd_cycles_add(cr->dd, cycles, ddCyclStep);
1483         }
1484
1485         /* increase the MD step number */
1486         step++;
1487         step_rel++;
1488
1489 #if GMX_FAHCORE
1490         if (MASTER(cr))
1491         {
1492             fcReportProgress(ir->nsteps + ir->init_step, step);
1493         }
1494 #endif
1495
1496         resetHandler->resetCounters(step, step_rel, mdlog, fplog, cr, fr->nbv.get(), nrnb,
1497                                     fr->pmedata, pme_loadbal, wcycle, walltime_accounting);
1498
1499         /* If bIMD is TRUE, the master updates the IMD energy record and sends positions to VMD client */
1500         imdSession->updateEnergyRecordAndSendPositionsAndEnergies(bInteractiveMDstep, step, bCalcEner);
1501     }
1502     /* End of main MD loop */
1503
1504     /* Closing TNG files can include compressing data. Therefore it is good to do that
1505      * before stopping the time measurements. */
1506     mdoutf_tng_close(outf);
1507
1508     /* Stop measuring walltime */
1509     walltime_accounting_end_time(walltime_accounting);
1510
1511     if (!thisRankHasDuty(cr, DUTY_PME))
1512     {
1513         /* Tell the PME only node to finish */
1514         gmx_pme_send_finish(cr);
1515     }
1516
1517     if (MASTER(cr))
1518     {
1519         if (ir->nstcalcenergy > 0)
1520         {
1521             gmx::EnergyOutput::printAnnealingTemperatures(fplog, groups, &(ir->opts));
1522             energyOutput.printAverages(fplog, groups);
1523         }
1524     }
1525     done_mdoutf(outf);
1526
1527     if (bPMETune)
1528     {
1529         pme_loadbal_done(pme_loadbal, fplog, mdlog, fr->nbv->useGpu());
1530     }
1531
1532     done_shellfc(fplog, shellfc, step_rel);
1533
1534     if (useReplicaExchange && MASTER(cr))
1535     {
1536         print_replica_exchange_statistics(fplog, repl_ex);
1537     }
1538
1539     walltime_accounting_set_nsteps_done(walltime_accounting, step_rel);
1540
1541     global_stat_destroy(gstat);
1542 }