2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
7 * Copyright (c) 2018,2019,2020,2021, by the GROMACS development team, led by
8 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
9 * and including many others, as listed in the AUTHORS file in the
10 * top-level source directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
40 #include "update_vv.h"
46 #include "gromacs/domdec/domdec.h"
47 #include "gromacs/domdec/localtopologychecker.h"
48 #include "gromacs/gmxlib/nrnb.h"
49 #include "gromacs/math/vec.h"
50 #include "gromacs/mdlib/constr.h"
51 #include "gromacs/mdlib/coupling.h"
52 #include "gromacs/mdlib/enerdata_utils.h"
53 #include "gromacs/mdlib/mdatoms.h"
54 #include "gromacs/mdlib/md_support.h"
55 #include "gromacs/mdlib/stat.h"
56 #include "gromacs/mdlib/tgroup.h"
57 #include "gromacs/mdlib/update.h"
58 #include "gromacs/mdrunutility/handlerestart.h"
59 #include "gromacs/mdtypes/commrec.h"
60 #include "gromacs/mdtypes/enerdata.h"
61 #include "gromacs/mdtypes/fcdata.h"
62 #include "gromacs/mdtypes/forcebuffers.h"
63 #include "gromacs/mdtypes/forcerec.h"
64 #include "gromacs/mdtypes/group.h"
65 #include "gromacs/mdtypes/inputrec.h"
66 #include "gromacs/mdtypes/mdatom.h"
67 #include "gromacs/mdtypes/state.h"
68 #include "gromacs/pulling/pull.h"
69 #include "gromacs/timing/wallcycle.h"
70 #include "gromacs/topology/topology.h"
72 void integrateVVFirstStep(int64_t step,
75 gmx::StartingBehavior startingBehavior,
85 const gmx_localtop_t& top,
86 gmx_enerdata_t* enerd,
87 gmx_ekindata_t* ekind,
88 gmx_global_stat* gstat,
104 real* saved_conserved_quantity,
105 gmx::ForceBuffers* f,
107 gmx::Constraints* constr,
108 gmx::SimulationSignaller* nullSignaller,
109 gmx::EnumerationArray<TrotterSequence, std::vector<int>> trotter_seq,
112 gmx_wallcycle* wcycle)
114 if (!bFirstStep || startingBehavior == gmx::StartingBehavior::NewSimulation)
116 /* ############### START FIRST UPDATE HALF-STEP FOR VV METHODS############### */
117 rvec* vbuf = nullptr;
119 wallcycle_start(wcycle, WallCycleCounter::Update);
120 if (ir->eI == IntegrationAlgorithm::VV && bInitStep)
122 /* if using velocity verlet with full time step Ekin,
123 * take the first half step only to compute the
124 * virial for the first step. From there,
125 * revert back to the initial coordinates
126 * so that the input is actually the initial step.
128 snew(vbuf, state->natoms);
129 copy_rvecn(state->v.rvec_array(), vbuf, 0, state->natoms); /* should make this better for parallelizing? */
133 /* this is for NHC in the Ekin(t+dt/2) version of vv */
141 mdatoms->cTC ? gmx::arrayRefFromArray(mdatoms->cTC, mdatoms->nr)
142 : gmx::ArrayRef<const unsigned short>(),
143 gmx::arrayRefFromArray(mdatoms->invmass, mdatoms->nr),
146 TrotterSequence::One);
149 upd->update_coords(*ir,
152 mdatoms->havePartiallyFrozenAtoms,
153 gmx::arrayRefFromArray(mdatoms->ptype, mdatoms->nr),
154 gmx::arrayRefFromArray(mdatoms->invmass, mdatoms->nr),
155 gmx::arrayRefFromArray(mdatoms->invMassPerDim, mdatoms->nr),
157 f->view().forceWithPadding(),
165 wallcycle_stop(wcycle, WallCycleCounter::Update);
166 constrain_velocities(constr, do_log, do_ene, step, state, nullptr, bCalcVir, shake_vir);
167 wallcycle_start(wcycle, WallCycleCounter::Update);
168 /* if VV, compute the pressure and constraints */
169 /* For VV2, we strictly only need this if using pressure
170 * control, but we really would like to have accurate pressures
172 * Think about ways around this in the future?
173 * For now, keep this choice in comments.
175 /*bPres = (ir->eI==IntegrationAlgorithm::VV || inputrecNptTrotter(ir)); */
176 /*bTemp = ((ir->eI==IntegrationAlgorithm::VV &&(!bInitStep)) || (ir->eI==IntegrationAlgorithm::VVAK && inputrecNptTrotter(ir)));*/
178 bool bTemp = ((ir->eI == IntegrationAlgorithm::VV && (!bInitStep))
179 || (ir->eI == IntegrationAlgorithm::VVAK));
180 if (bCalcEner && ir->eI == IntegrationAlgorithm::VVAK)
182 *bSumEkinhOld = TRUE;
184 /* for vv, the first half of the integration actually corresponds to the previous step.
185 So we need information from the last step in the first half of the integration */
186 if (bGStat || do_per_step(step - 1, nstglobalcomm))
188 wallcycle_stop(wcycle, WallCycleCounter::Update);
190 ((bGStat ? CGLO_GSTAT : 0) | (bCalcEner ? CGLO_ENERGY : 0)
191 | (bTemp ? CGLO_TEMPERATURE : 0) | (bPres ? CGLO_PRESSURE : 0)
192 | (bPres ? CGLO_CONSTRAINT : 0) | (bStopCM ? CGLO_STOPCM : 0) | CGLO_SCALEEKIN);
193 if (DOMAINDECOMP(cr) && dd_localTopologyChecker(*cr->dd).shouldCheckNumberOfBondedInteractions())
195 cglo_flags |= CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS;
197 compute_globals(gstat,
202 makeConstArrayRef(state->x),
203 makeConstArrayRef(state->v),
214 (bCalcEner && constr != nullptr) ? constr->rmsdData() : gmx::ArrayRef<real>{},
219 /* explanation of above:
220 a) We compute Ekin at the full time step
221 if 1) we are using the AveVel Ekin, and it's not the
222 initial step, or 2) if we are using AveEkin, but need the full
223 time step kinetic energy for the pressure (always true now, since we want accurate statistics).
224 b) If we are using EkinAveEkin for the kinetic energy for the temperature control, we still feed in
225 EkinAveVel because it's needed for the pressure */
226 if (DOMAINDECOMP(cr))
228 dd_localTopologyChecker(cr->dd)->checkNumberOfBondedInteractions(
229 &top, makeConstArrayRef(state->x), state->box);
233 process_and_stopcm_grp(
234 fplog, vcm, *mdatoms, makeArrayRef(state->x), makeArrayRef(state->v));
235 inc_nrnb(nrnb, eNR_STOPCM, mdatoms->homenr);
237 wallcycle_start(wcycle, WallCycleCounter::Update);
239 /* temperature scaling and pressure scaling to produce the extended variables at t+dt */
244 m_add(force_vir, shake_vir, total_vir); /* we need the un-dispersion corrected total vir here */
252 mdatoms->cTC ? gmx::arrayRefFromArray(mdatoms->cTC, mdatoms->nr)
253 : gmx::ArrayRef<const unsigned short>(),
254 gmx::arrayRefFromArray(mdatoms->invmass, mdatoms->nr),
257 TrotterSequence::Two);
259 /* TODO This is only needed when we're about to write
260 * a checkpoint, because we use it after the restart
261 * (in a kludge?). But what should we be doing if
262 * the startingBehavior is NewSimulation or bInitStep are true? */
263 if (inputrecNptTrotter(ir) || inputrecNphTrotter(ir))
265 copy_mat(shake_vir, state->svir_prev);
266 copy_mat(force_vir, state->fvir_prev);
268 if ((inputrecNptTrotter(ir) || inputrecNvtTrotter(ir)) && ir->eI == IntegrationAlgorithm::VV)
270 /* update temperature and kinetic energy now that step is over - this is the v(t+dt) point */
271 enerd->term[F_TEMP] = sum_ekin(
272 &(ir->opts), ekind, nullptr, (ir->eI == IntegrationAlgorithm::VV), FALSE);
273 enerd->term[F_EKIN] = trace(ekind->ekin);
278 wallcycle_stop(wcycle, WallCycleCounter::Update);
279 /* We need the kinetic energy at minus the half step for determining
280 * the full step kinetic energy and possibly for T-coupling.*/
281 /* This may not be quite working correctly yet . . . . */
282 compute_globals(gstat,
287 makeConstArrayRef(state->x),
288 makeConstArrayRef(state->v),
299 gmx::ArrayRef<real>{},
303 CGLO_GSTAT | CGLO_TEMPERATURE);
304 wallcycle_start(wcycle, WallCycleCounter::Update);
307 /* if it's the initial step, we performed this first step just to get the constraint virial */
308 if (ir->eI == IntegrationAlgorithm::VV && bInitStep)
310 copy_rvecn(vbuf, state->v.rvec_array(), 0, state->natoms);
313 wallcycle_stop(wcycle, WallCycleCounter::Update);
316 /* compute the conserved quantity */
317 *saved_conserved_quantity = NPT_energy(ir, state, MassQ);
318 if (ir->eI == IntegrationAlgorithm::VV)
320 *last_ekin = enerd->term[F_EKIN];
322 if ((ir->eDispCorr != DispersionCorrectionType::EnerPres)
323 && (ir->eDispCorr != DispersionCorrectionType::AllEnerPres))
325 *saved_conserved_quantity -= enerd->term[F_DISPCORR];
327 /* sum up the foreign kinetic energy and dK/dl terms for vv. currently done every step so that dhdl is correct in the .edr */
328 if (ir->efep != FreeEnergyPerturbationType::No)
330 accumulateKineticLambdaComponents(enerd, state->lambda, *ir->fepvals);
334 void integrateVVSecondStep(int64_t step,
335 const t_inputrec* ir,
344 gmx_enerdata_t* enerd,
345 gmx_ekindata_t* ekind,
346 gmx_global_stat* gstat,
359 gmx::ForceBuffers* f,
360 std::vector<gmx::RVec>* cbuf,
362 gmx::Constraints* constr,
363 gmx::SimulationSignaller* nullSignaller,
364 gmx::EnumerationArray<TrotterSequence, std::vector<int>> trotter_seq,
366 gmx_wallcycle* wcycle)
368 /* velocity half-step update */
369 upd->update_coords(*ir,
372 mdatoms->havePartiallyFrozenAtoms,
373 gmx::arrayRefFromArray(mdatoms->ptype, mdatoms->nr),
374 gmx::arrayRefFromArray(mdatoms->invmass, mdatoms->nr),
375 gmx::arrayRefFromArray(mdatoms->invMassPerDim, mdatoms->nr),
377 f->view().forceWithPadding(),
386 /* Above, initialize just copies ekinh into ekin,
387 * it doesn't copy position (for VV),
388 * and entire integrator for MD.
391 if (ir->eI == IntegrationAlgorithm::VVAK)
393 cbuf->resize(state->x.size());
394 std::copy(state->x.begin(), state->x.end(), cbuf->begin());
397 if (ir->bPull && ir->pull->bSetPbcRefToPrevStepCOM)
399 updatePrevStepPullCom(pull_work, state);
402 upd->update_coords(*ir,
405 mdatoms->havePartiallyFrozenAtoms,
406 gmx::arrayRefFromArray(mdatoms->ptype, mdatoms->nr),
407 gmx::arrayRefFromArray(mdatoms->invmass, mdatoms->nr),
408 gmx::arrayRefFromArray(mdatoms->invMassPerDim, mdatoms->nr),
410 f->view().forceWithPadding(),
418 wallcycle_stop(wcycle, WallCycleCounter::Update);
420 constrain_coordinates(
421 constr, do_log, do_ene, step, state, upd->xp()->arrayRefWithPadding(), dvdl_constr, bCalcVir, shake_vir);
423 upd->update_sd_second_half(*ir,
427 gmx::arrayRefFromArray(mdatoms->ptype, mdatoms->nr),
428 gmx::arrayRefFromArray(mdatoms->invmass, mdatoms->nr),
437 *ir, mdatoms->havePartiallyFrozenAtoms, mdatoms->homenr, state, wcycle, constr != nullptr);
439 if (ir->eI == IntegrationAlgorithm::VVAK)
441 /* erase F_EKIN and F_TEMP here? */
442 /* just compute the kinetic energy at the half step to perform a trotter step */
443 compute_globals(gstat,
448 makeConstArrayRef(state->x),
449 makeConstArrayRef(state->v),
460 gmx::ArrayRef<real>{},
464 (bGStat ? CGLO_GSTAT : 0) | CGLO_TEMPERATURE);
465 wallcycle_start(wcycle, WallCycleCounter::Update);
473 mdatoms->cTC ? gmx::arrayRefFromArray(mdatoms->cTC, mdatoms->nr)
474 : gmx::ArrayRef<const unsigned short>(),
475 gmx::arrayRefFromArray(mdatoms->invmass, mdatoms->nr),
478 TrotterSequence::Four);
479 /* now we know the scaling, we can compute the positions again */
480 std::copy(cbuf->begin(), cbuf->end(), state->x.begin());
482 upd->update_coords(*ir,
485 mdatoms->havePartiallyFrozenAtoms,
486 gmx::arrayRefFromArray(mdatoms->ptype, mdatoms->nr),
487 gmx::arrayRefFromArray(mdatoms->invmass, mdatoms->nr),
488 gmx::arrayRefFromArray(mdatoms->invMassPerDim, mdatoms->nr),
490 f->view().forceWithPadding(),
497 wallcycle_stop(wcycle, WallCycleCounter::Update);
499 /* do we need an extra constraint here? just need to copy out of as_rvec_array(state->v.data()) to upd->xp? */
500 /* are the small terms in the shake_vir here due
501 * to numerical errors, or are they important
502 * physically? I'm thinking they are just errors, but not completely sure.
503 * For now, will call without actually constraining, constr=NULL*/
504 upd->finish_update(*ir, mdatoms->havePartiallyFrozenAtoms, mdatoms->homenr, state, wcycle, false);
506 /* this factor or 2 correction is necessary
507 because half of the constraint force is removed
508 in the vv step, so we have to double it. See
509 the Issue #1255. It is not yet clear
510 if the factor of 2 is exact, or just a very
511 good approximation, and this will be
512 investigated. The next step is to see if this
513 can be done adding a dhdl contribution from the
514 rattle step, but this is somewhat more
515 complicated with the current code. Will be
516 investigated, hopefully for 4.6.3. However,
517 this current solution is much better than
518 having it completely wrong.
520 enerd->term[F_DVDL_CONSTR] += 2 * *dvdl_constr;