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"
48 #include "gromacs/domdec/domdec.h"
49 #include "gromacs/gmxlib/nrnb.h"
50 #include "gromacs/math/units.h"
51 #include "gromacs/math/vec.h"
52 #include "gromacs/mdlib/constr.h"
53 #include "gromacs/mdlib/coupling.h"
54 #include "gromacs/mdlib/enerdata_utils.h"
55 #include "gromacs/mdlib/mdatoms.h"
56 #include "gromacs/mdlib/md_support.h"
57 #include "gromacs/mdlib/stat.h"
58 #include "gromacs/mdlib/tgroup.h"
59 #include "gromacs/mdlib/update.h"
60 #include "gromacs/mdtypes/commrec.h"
61 #include "gromacs/mdtypes/enerdata.h"
62 #include "gromacs/mdtypes/fcdata.h"
63 #include "gromacs/mdtypes/forcebuffers.h"
64 #include "gromacs/mdtypes/forcerec.h"
65 #include "gromacs/mdtypes/group.h"
66 #include "gromacs/mdtypes/inputrec.h"
67 #include "gromacs/mdtypes/mdatom.h"
68 #include "gromacs/mdtypes/state.h"
69 #include "gromacs/pulling/pull.h"
70 #include "gromacs/timing/wallcycle.h"
71 #include "gromacs/topology/topology.h"
73 void integrateVVFirstStep(int64_t step,
76 gmx::StartingBehavior startingBehavior,
83 const t_fcdata& fcdata,
86 const gmx_mtop_t& top_global,
87 const gmx_localtop_t& top,
88 gmx_enerdata_t* enerd,
89 gmx_ekindata_t* ekind,
90 gmx_global_stat* gstat,
106 real* saved_conserved_quantity,
107 gmx::ForceBuffers* f,
109 gmx::Constraints* constr,
110 gmx::SimulationSignaller* nullSignaller,
111 std::array<std::vector<int>, ettTSEQMAX> trotter_seq,
113 const gmx::MDLogger& mdlog,
115 gmx_wallcycle* wcycle)
117 if (!bFirstStep || startingBehavior == gmx::StartingBehavior::NewSimulation)
119 /* ############### START FIRST UPDATE HALF-STEP FOR VV METHODS############### */
120 rvec* vbuf = nullptr;
122 wallcycle_start(wcycle, WallCycleCounter::Update);
123 if (ir->eI == IntegrationAlgorithm::VV && bInitStep)
125 /* if using velocity verlet with full time step Ekin,
126 * take the first half step only to compute the
127 * virial for the first step. From there,
128 * revert back to the initial coordinates
129 * so that the input is actually the initial step.
131 snew(vbuf, state->natoms);
132 copy_rvecn(state->v.rvec_array(), vbuf, 0, state->natoms); /* should make this better for parallelizing? */
136 /* this is for NHC in the Ekin(t+dt/2) version of vv */
137 trotter_update(ir, step, ekind, enerd, state, total_vir, mdatoms, MassQ, trotter_seq, ettTSEQ1);
140 upd->update_coords(*ir,
143 mdatoms->havePartiallyFrozenAtoms,
144 gmx::arrayRefFromArray(mdatoms->ptype, mdatoms->nr),
145 gmx::arrayRefFromArray(mdatoms->invmass, mdatoms->nr),
146 gmx::arrayRefFromArray(mdatoms->invMassPerDim, mdatoms->nr),
148 f->view().forceWithPadding(),
156 wallcycle_stop(wcycle, WallCycleCounter::Update);
157 constrain_velocities(constr, do_log, do_ene, step, state, nullptr, bCalcVir, shake_vir);
158 wallcycle_start(wcycle, WallCycleCounter::Update);
159 /* if VV, compute the pressure and constraints */
160 /* For VV2, we strictly only need this if using pressure
161 * control, but we really would like to have accurate pressures
163 * Think about ways around this in the future?
164 * For now, keep this choice in comments.
166 /*bPres = (ir->eI==IntegrationAlgorithm::VV || inputrecNptTrotter(ir)); */
167 /*bTemp = ((ir->eI==IntegrationAlgorithm::VV &&(!bInitStep)) || (ir->eI==IntegrationAlgorithm::VVAK && inputrecNptTrotter(ir)));*/
169 bool bTemp = ((ir->eI == IntegrationAlgorithm::VV && (!bInitStep))
170 || (ir->eI == IntegrationAlgorithm::VVAK));
171 if (bCalcEner && ir->eI == IntegrationAlgorithm::VVAK)
173 *bSumEkinhOld = TRUE;
175 /* for vv, the first half of the integration actually corresponds to the previous step.
176 So we need information from the last step in the first half of the integration */
177 if (bGStat || do_per_step(step - 1, nstglobalcomm))
179 wallcycle_stop(wcycle, WallCycleCounter::Update);
181 ((bGStat ? CGLO_GSTAT : 0) | (bCalcEner ? CGLO_ENERGY : 0)
182 | (bTemp ? CGLO_TEMPERATURE : 0) | (bPres ? CGLO_PRESSURE : 0)
183 | (bPres ? CGLO_CONSTRAINT : 0) | (bStopCM ? CGLO_STOPCM : 0) | CGLO_SCALEEKIN);
184 if (DOMAINDECOMP(cr) && shouldCheckNumberOfBondedInteractions(*cr->dd))
186 cglo_flags |= CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS;
188 compute_globals(gstat,
193 makeConstArrayRef(state->x),
194 makeConstArrayRef(state->v),
205 (bCalcEner && constr != nullptr) ? constr->rmsdData() : gmx::ArrayRef<real>{},
210 /* explanation of above:
211 a) We compute Ekin at the full time step
212 if 1) we are using the AveVel Ekin, and it's not the
213 initial step, or 2) if we are using AveEkin, but need the full
214 time step kinetic energy for the pressure (always true now, since we want accurate statistics).
215 b) If we are using EkinAveEkin for the kinetic energy for the temperature control, we still feed in
216 EkinAveVel because it's needed for the pressure */
217 if (DOMAINDECOMP(cr))
219 checkNumberOfBondedInteractions(
220 mdlog, cr, top_global, &top, makeConstArrayRef(state->x), state->box);
224 process_and_stopcm_grp(
225 fplog, vcm, *mdatoms, makeArrayRef(state->x), makeArrayRef(state->v));
226 inc_nrnb(nrnb, eNR_STOPCM, mdatoms->homenr);
228 wallcycle_start(wcycle, WallCycleCounter::Update);
230 /* temperature scaling and pressure scaling to produce the extended variables at t+dt */
235 m_add(force_vir, shake_vir, total_vir); /* we need the un-dispersion corrected total vir here */
236 trotter_update(ir, step, ekind, enerd, state, total_vir, mdatoms, MassQ, trotter_seq, ettTSEQ2);
238 /* TODO This is only needed when we're about to write
239 * a checkpoint, because we use it after the restart
240 * (in a kludge?). But what should we be doing if
241 * the startingBehavior is NewSimulation or bInitStep are true? */
242 if (inputrecNptTrotter(ir) || inputrecNphTrotter(ir))
244 copy_mat(shake_vir, state->svir_prev);
245 copy_mat(force_vir, state->fvir_prev);
247 if ((inputrecNptTrotter(ir) || inputrecNvtTrotter(ir)) && ir->eI == IntegrationAlgorithm::VV)
249 /* update temperature and kinetic energy now that step is over - this is the v(t+dt) point */
250 enerd->term[F_TEMP] = sum_ekin(
251 &(ir->opts), ekind, nullptr, (ir->eI == IntegrationAlgorithm::VV), FALSE);
252 enerd->term[F_EKIN] = trace(ekind->ekin);
257 wallcycle_stop(wcycle, WallCycleCounter::Update);
258 /* We need the kinetic energy at minus the half step for determining
259 * the full step kinetic energy and possibly for T-coupling.*/
260 /* This may not be quite working correctly yet . . . . */
261 compute_globals(gstat,
266 makeConstArrayRef(state->x),
267 makeConstArrayRef(state->v),
278 gmx::ArrayRef<real>{},
282 CGLO_GSTAT | CGLO_TEMPERATURE);
283 wallcycle_start(wcycle, WallCycleCounter::Update);
286 /* if it's the initial step, we performed this first step just to get the constraint virial */
287 if (ir->eI == IntegrationAlgorithm::VV && bInitStep)
289 copy_rvecn(vbuf, state->v.rvec_array(), 0, state->natoms);
292 wallcycle_stop(wcycle, WallCycleCounter::Update);
295 /* compute the conserved quantity */
296 *saved_conserved_quantity = NPT_energy(ir, state, MassQ);
297 if (ir->eI == IntegrationAlgorithm::VV)
299 *last_ekin = enerd->term[F_EKIN];
301 if ((ir->eDispCorr != DispersionCorrectionType::EnerPres)
302 && (ir->eDispCorr != DispersionCorrectionType::AllEnerPres))
304 *saved_conserved_quantity -= enerd->term[F_DISPCORR];
306 /* sum up the foreign kinetic energy and dK/dl terms for vv. currently done every step so that dhdl is correct in the .edr */
307 if (ir->efep != FreeEnergyPerturbationType::No)
309 accumulateKineticLambdaComponents(enerd, state->lambda, *ir->fepvals);
313 void integrateVVSecondStep(int64_t step,
314 const t_inputrec* ir,
319 const t_fcdata& fcdata,
323 gmx_enerdata_t* enerd,
324 gmx_ekindata_t* ekind,
325 gmx_global_stat* gstat,
338 gmx::ForceBuffers* f,
339 std::vector<gmx::RVec>* cbuf,
341 gmx::Constraints* constr,
342 gmx::SimulationSignaller* nullSignaller,
343 std::array<std::vector<int>, ettTSEQMAX> trotter_seq,
345 gmx_wallcycle* wcycle)
347 /* velocity half-step update */
348 upd->update_coords(*ir,
351 mdatoms->havePartiallyFrozenAtoms,
352 gmx::arrayRefFromArray(mdatoms->ptype, mdatoms->nr),
353 gmx::arrayRefFromArray(mdatoms->invmass, mdatoms->nr),
354 gmx::arrayRefFromArray(mdatoms->invMassPerDim, mdatoms->nr),
356 f->view().forceWithPadding(),
365 /* Above, initialize just copies ekinh into ekin,
366 * it doesn't copy position (for VV),
367 * and entire integrator for MD.
370 if (ir->eI == IntegrationAlgorithm::VVAK)
372 cbuf->resize(state->x.size());
373 std::copy(state->x.begin(), state->x.end(), cbuf->begin());
376 if (ir->bPull && ir->pull->bSetPbcRefToPrevStepCOM)
378 updatePrevStepPullCom(pull_work, state);
381 upd->update_coords(*ir,
384 mdatoms->havePartiallyFrozenAtoms,
385 gmx::arrayRefFromArray(mdatoms->ptype, mdatoms->nr),
386 gmx::arrayRefFromArray(mdatoms->invmass, mdatoms->nr),
387 gmx::arrayRefFromArray(mdatoms->invMassPerDim, mdatoms->nr),
389 f->view().forceWithPadding(),
397 wallcycle_stop(wcycle, WallCycleCounter::Update);
399 constrain_coordinates(
400 constr, do_log, do_ene, step, state, upd->xp()->arrayRefWithPadding(), dvdl_constr, bCalcVir, shake_vir);
402 upd->update_sd_second_half(*ir,
406 gmx::arrayRefFromArray(mdatoms->ptype, mdatoms->nr),
407 gmx::arrayRefFromArray(mdatoms->invmass, mdatoms->nr),
415 upd->finish_update(*ir, mdatoms, state, wcycle, constr != nullptr);
417 if (ir->eI == IntegrationAlgorithm::VVAK)
419 /* erase F_EKIN and F_TEMP here? */
420 /* just compute the kinetic energy at the half step to perform a trotter step */
421 compute_globals(gstat,
426 makeConstArrayRef(state->x),
427 makeConstArrayRef(state->v),
438 gmx::ArrayRef<real>{},
442 (bGStat ? CGLO_GSTAT : 0) | CGLO_TEMPERATURE);
443 wallcycle_start(wcycle, WallCycleCounter::Update);
444 trotter_update(ir, step, ekind, enerd, state, total_vir, mdatoms, MassQ, trotter_seq, ettTSEQ4);
445 /* now we know the scaling, we can compute the positions again */
446 std::copy(cbuf->begin(), cbuf->end(), state->x.begin());
448 upd->update_coords(*ir,
451 mdatoms->havePartiallyFrozenAtoms,
452 gmx::arrayRefFromArray(mdatoms->ptype, mdatoms->nr),
453 gmx::arrayRefFromArray(mdatoms->invmass, mdatoms->nr),
454 gmx::arrayRefFromArray(mdatoms->invMassPerDim, mdatoms->nr),
456 f->view().forceWithPadding(),
463 wallcycle_stop(wcycle, WallCycleCounter::Update);
465 /* do we need an extra constraint here? just need to copy out of as_rvec_array(state->v.data()) to upd->xp? */
466 /* are the small terms in the shake_vir here due
467 * to numerical errors, or are they important
468 * physically? I'm thinking they are just errors, but not completely sure.
469 * For now, will call without actually constraining, constr=NULL*/
470 upd->finish_update(*ir, mdatoms, state, wcycle, false);
472 /* this factor or 2 correction is necessary
473 because half of the constraint force is removed
474 in the vv step, so we have to double it. See
475 the Issue #1255. It is not yet clear
476 if the factor of 2 is exact, or just a very
477 good approximation, and this will be
478 investigated. The next step is to see if this
479 can be done adding a dhdl contribution from the
480 rattle step, but this is somewhat more
481 complicated with the current code. Will be
482 investigated, hopefully for 4.6.3. However,
483 this current solution is much better than
484 having it completely wrong.
486 enerd->term[F_DVDL_CONSTR] += 2 * *dvdl_constr;