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.
47 #include "gromacs/domdec/domdec_struct.h"
48 #include "gromacs/gmxlib/nrnb.h"
49 #include "gromacs/math/functions.h"
50 #include "gromacs/math/invertmatrix.h"
51 #include "gromacs/math/units.h"
52 #include "gromacs/math/vec.h"
53 #include "gromacs/math/vecdump.h"
54 #include "gromacs/mdlib/boxdeformation.h"
55 #include "gromacs/mdlib/expanded.h"
56 #include "gromacs/mdlib/gmx_omp_nthreads.h"
57 #include "gromacs/mdlib/stat.h"
58 #include "gromacs/mdlib/update.h"
59 #include "gromacs/mdtypes/commrec.h"
60 #include "gromacs/mdtypes/enerdata.h"
61 #include "gromacs/mdtypes/group.h"
62 #include "gromacs/mdtypes/inputrec.h"
63 #include "gromacs/mdtypes/md_enums.h"
64 #include "gromacs/mdtypes/mdatom.h"
65 #include "gromacs/mdtypes/state.h"
66 #include "gromacs/pbcutil/boxutilities.h"
67 #include "gromacs/pbcutil/pbc.h"
68 #include "gromacs/random/gammadistribution.h"
69 #include "gromacs/random/normaldistribution.h"
70 #include "gromacs/random/tabulatednormaldistribution.h"
71 #include "gromacs/random/threefry.h"
72 #include "gromacs/random/uniformrealdistribution.h"
73 #include "gromacs/utility/cstringutil.h"
74 #include "gromacs/utility/fatalerror.h"
75 #include "gromacs/utility/pleasecite.h"
76 #include "gromacs/utility/smalloc.h"
78 #define NTROTTERPARTS 3
80 /* Suzuki-Yoshida Constants, for n=3 and n=5, for symplectic integration */
82 /* for n=3, w0 = w2 = 1/(2-2^-(1/3)), w1 = 1-2*w0 */
83 /* for n=5, w0 = w1 = w3 = w4 = 1/(4-4^-(1/3)), w1 = 1-4*w0 */
85 #define MAX_SUZUKI_YOSHIDA_NUM 5
86 #define SUZUKI_YOSHIDA_NUM 5
88 static const double sy_const_1[] = { 1. };
89 static const double sy_const_3[] = { 0.828981543588751, -0.657963087177502, 0.828981543588751 };
90 static const double sy_const_5[] = { 0.2967324292201065,
96 static const double* sy_const[] = { nullptr, sy_const_1, nullptr, sy_const_3, nullptr, sy_const_5 };
99 void update_tcouple(int64_t step,
100 const t_inputrec* inputrec,
102 gmx_ekindata_t* ekind,
103 const t_extmass* MassQ,
107 // This condition was explicitly checked in previous version, but should have never been satisfied
108 GMX_ASSERT(!(EI_VV(inputrec->eI)
109 && (inputrecNvtTrotter(inputrec) || inputrecNptTrotter(inputrec)
110 || inputrecNphTrotter(inputrec))),
111 "Temperature coupling was requested with velocity verlet and trotter");
113 bool doTemperatureCoupling = false;
115 // For VV temperature coupling parameters are updated on the current
116 // step, for the others - one step before.
117 if (inputrec->etc == TemperatureCoupling::No)
119 doTemperatureCoupling = false;
121 else if (EI_VV(inputrec->eI))
123 doTemperatureCoupling = do_per_step(step, inputrec->nsttcouple);
127 doTemperatureCoupling = do_per_step(step + inputrec->nsttcouple - 1, inputrec->nsttcouple);
130 if (doTemperatureCoupling)
132 real dttc = inputrec->nsttcouple * inputrec->delta_t;
134 // TODO: berendsen_tcoupl(...), nosehoover_tcoupl(...) and vrescale_tcoupl(...) update
135 // temperature coupling parameters, which should be reflected in the name of these
137 switch (inputrec->etc)
139 case TemperatureCoupling::No:
140 case TemperatureCoupling::Andersen:
141 case TemperatureCoupling::AndersenMassive: break;
142 case TemperatureCoupling::Berendsen:
143 berendsen_tcoupl(inputrec, ekind, dttc, state->therm_integral);
145 case TemperatureCoupling::NoseHoover:
146 nosehoover_tcoupl(&(inputrec->opts),
149 state->nosehoover_xi.data(),
150 state->nosehoover_vxi.data(),
153 case TemperatureCoupling::VRescale:
154 vrescale_tcoupl(inputrec, step, ekind, dttc, state->therm_integral.data());
156 default: gmx_fatal(FARGS, "Unknown temperature coupling algorithm");
158 /* rescale in place here */
159 if (EI_VV(inputrec->eI))
161 rescale_velocities(ekind, md, 0, md->homenr, state->v.rvec_array());
166 // Set the T scaling lambda to 1 to have no scaling
167 // TODO: Do we have to do it on every non-t-couple step?
168 for (int i = 0; (i < inputrec->opts.ngtc); i++)
170 ekind->tcstat[i].lambda = 1.0;
175 void update_pcouple_before_coordinates(FILE* fplog,
177 const t_inputrec* inputrec,
179 matrix parrinellorahmanMu,
183 /* Berendsen P-coupling is completely handled after the coordinate update.
184 * Trotter P-coupling is handled by separate calls to trotter_update().
186 if (inputrec->epc == PressureCoupling::ParrinelloRahman
187 && do_per_step(step + inputrec->nstpcouple - 1, inputrec->nstpcouple))
189 real dtpc = inputrec->nstpcouple * inputrec->delta_t;
191 parrinellorahman_pcoupl(
192 fplog, step, inputrec, dtpc, state->pres_prev, state->box, state->box_rel, state->boxv, M, parrinellorahmanMu, bInitStep);
196 void update_pcouple_after_coordinates(FILE* fplog,
198 const t_inputrec* inputrec,
200 const matrix pressure,
201 const matrix forceVirial,
202 const matrix constraintVirial,
203 matrix pressureCouplingMu,
206 gmx::BoxDeformation* boxDeformation,
207 const bool scaleCoordinates)
210 int homenr = md->homenr;
212 /* Cast to real for faster code, no loss in precision (see comment above) */
213 real dt = inputrec->delta_t;
216 /* now update boxes */
217 switch (inputrec->epc)
219 case (PressureCoupling::No): break;
220 case (PressureCoupling::Berendsen):
221 if (do_per_step(step, inputrec->nstpcouple))
223 real dtpc = inputrec->nstpcouple * dt;
224 pressureCouplingCalculateScalingMatrix<PressureCoupling::Berendsen>(fplog,
233 &state->baros_integral);
234 pressureCouplingScaleBoxAndCoordinates<PressureCoupling::Berendsen>(inputrec,
240 state->x.rvec_array(),
247 case (PressureCoupling::CRescale):
248 if (do_per_step(step, inputrec->nstpcouple))
250 real dtpc = inputrec->nstpcouple * dt;
251 pressureCouplingCalculateScalingMatrix<PressureCoupling::CRescale>(fplog,
260 &state->baros_integral);
261 pressureCouplingScaleBoxAndCoordinates<PressureCoupling::CRescale>(
268 state->x.rvec_array(),
269 state->v.rvec_array(),
275 case (PressureCoupling::ParrinelloRahman):
276 if (do_per_step(step + inputrec->nstpcouple - 1, inputrec->nstpcouple))
278 /* The box velocities were updated in do_pr_pcoupl,
279 * but we dont change the box vectors until we get here
280 * since we need to be able to shift/unshift above.
282 real dtpc = inputrec->nstpcouple * dt;
283 for (int i = 0; i < DIM; i++)
285 for (int m = 0; m <= i; m++)
287 state->box[i][m] += dtpc * state->boxv[i][m];
290 preserve_box_shape(inputrec, state->box_rel, state->box);
292 /* Scale the coordinates */
293 if (scaleCoordinates)
295 auto x = state->x.rvec_array();
296 for (int n = start; n < start + homenr; n++)
298 tmvmul_ur0(pressureCouplingMu, x[n], x[n]);
303 case (PressureCoupling::Mttk):
304 switch (inputrec->epct)
306 case (PressureCouplingType::Isotropic):
307 /* DIM * eta = ln V. so DIM*eta_new = DIM*eta_old + DIM*dt*veta =>
308 ln V_new = ln V_old + 3*dt*veta => V_new = V_old*exp(3*dt*veta) =>
309 Side length scales as exp(veta*dt) */
311 msmul(state->box, std::exp(state->veta * dt), state->box);
313 /* Relate veta to boxv. veta = d(eta)/dT = (1/DIM)*1/V dV/dT.
314 o If we assume isotropic scaling, and box length scaling
315 factor L, then V = L^DIM (det(M)). So dV/dt = DIM
316 L^(DIM-1) dL/dt det(M), and veta = (1/L) dL/dt. The
317 determinant of B is L^DIM det(M), and the determinant
318 of dB/dt is (dL/dT)^DIM det (M). veta will be
319 (det(dB/dT)/det(B))^(1/3). Then since M =
320 B_new*(vol_new)^(1/3), dB/dT_new = (veta_new)*B(new). */
322 msmul(state->box, state->veta, state->boxv);
332 auto localX = makeArrayRef(state->x).subArray(start, homenr);
333 boxDeformation->apply(localX, state->box, step);
337 extern gmx_bool update_randomize_velocities(const t_inputrec* ir,
341 gmx::ArrayRef<gmx::RVec> v,
342 const gmx::Update* upd,
343 const gmx::Constraints* constr)
346 real rate = (ir->delta_t) / ir->opts.tau_t[0];
348 if (ir->etc == TemperatureCoupling::Andersen && constr != nullptr)
350 /* Currently, Andersen thermostat does not support constrained
351 systems. Functionality exists in the andersen_tcoupl
352 function in GROMACS 4.5.7 to allow this combination. That
353 code could be ported to the current random-number
354 generation approach, but has not yet been done because of
355 lack of time and resources. */
357 "Normal Andersen is currently not supported with constraints, use massive "
361 /* proceed with andersen if 1) it's fixed probability per
362 particle andersen or 2) it's massive andersen and it's tau_t/dt */
363 if ((ir->etc == TemperatureCoupling::Andersen) || do_per_step(step, gmx::roundToInt(1.0 / rate)))
366 ir, step, cr, md, v, rate, upd->getAndersenRandomizeGroup(), upd->getBoltzmanFactor());
373 static const double sy_const[MAX_SUZUKI_YOSHIDA_NUM+1][MAX_SUZUKI_YOSHIDA_NUM+1] = {
377 {0.828981543588751,-0.657963087177502,0.828981543588751},
379 {0.2967324292201065,0.2967324292201065,-0.186929716880426,0.2967324292201065,0.2967324292201065}
382 /* these integration routines are only referenced inside this file */
383 static void NHC_trotter(const t_grpopts* opts,
385 const gmx_ekindata_t* ekind,
391 const t_extmass* MassQ,
392 gmx_bool bEkinAveVel)
395 /* general routine for both barostat and thermostat nose hoover chains */
398 double Ekin, Efac, reft, kT, nd;
403 int mstepsi, mstepsj;
404 int ns = SUZUKI_YOSHIDA_NUM; /* set the degree of integration in the types/state.h file */
405 int nh = opts->nhchainlength;
408 mstepsi = mstepsj = ns;
410 /* if scalefac is NULL, we are doing the NHC of the barostat */
413 if (scalefac == nullptr)
418 for (i = 0; i < nvar; i++)
421 /* make it easier to iterate by selecting
422 out the sub-array that corresponds to this T group */
426 gmx::ArrayRef<const double> iQinv;
429 iQinv = gmx::arrayRefFromArray(&MassQ->QPinv[i * nh], nh);
430 nd = 1.0; /* THIS WILL CHANGE IF NOT ISOTROPIC */
431 reft = std::max<real>(0, opts->ref_t[0]);
432 Ekin = gmx::square(*veta) / MassQ->Winv;
436 iQinv = gmx::arrayRefFromArray(&MassQ->Qinv[i * nh], nh);
437 const t_grp_tcstat* tcstat = &ekind->tcstat[i];
439 reft = std::max<real>(0, opts->ref_t[i]);
442 Ekin = 2 * trace(tcstat->ekinf) * tcstat->ekinscalef_nhc;
446 Ekin = 2 * trace(tcstat->ekinh) * tcstat->ekinscaleh_nhc;
449 kT = gmx::c_boltz * reft;
451 for (mi = 0; mi < mstepsi; mi++)
453 for (mj = 0; mj < mstepsj; mj++)
455 /* weighting for this step using Suzuki-Yoshida integration - fixed at 5 */
456 dt = sy_const[ns][mj] * dtfull / mstepsi;
458 /* compute the thermal forces */
459 GQ[0] = iQinv[0] * (Ekin - nd * kT);
461 for (j = 0; j < nh - 1; j++)
463 if (iQinv[j + 1] > 0)
465 /* we actually don't need to update here if we save the
466 state of the GQ, but it's easier to just recompute*/
467 GQ[j + 1] = iQinv[j + 1] * ((gmx::square(ivxi[j]) / iQinv[j]) - kT);
475 ivxi[nh - 1] += 0.25 * dt * GQ[nh - 1];
476 for (j = nh - 1; j > 0; j--)
478 Efac = exp(-0.125 * dt * ivxi[j]);
479 ivxi[j - 1] = Efac * (ivxi[j - 1] * Efac + 0.25 * dt * GQ[j - 1]);
482 Efac = exp(-0.5 * dt * ivxi[0]);
491 Ekin *= (Efac * Efac);
493 /* Issue - if the KE is an average of the last and the current temperatures, then we
494 might not be able to scale the kinetic energy directly with this factor. Might
495 take more bookkeeping -- have to think about this a bit more . . . */
497 GQ[0] = iQinv[0] * (Ekin - nd * kT);
499 /* update thermostat positions */
500 for (j = 0; j < nh; j++)
502 ixi[j] += 0.5 * dt * ivxi[j];
505 for (j = 0; j < nh - 1; j++)
507 Efac = exp(-0.125 * dt * ivxi[j + 1]);
508 ivxi[j] = Efac * (ivxi[j] * Efac + 0.25 * dt * GQ[j]);
509 if (iQinv[j + 1] > 0)
511 GQ[j + 1] = iQinv[j + 1] * ((gmx::square(ivxi[j]) / iQinv[j]) - kT);
518 ivxi[nh - 1] += 0.25 * dt * GQ[nh - 1];
525 static void boxv_trotter(const t_inputrec* ir,
529 const gmx_ekindata_t* ekind,
532 const t_extmass* MassQ)
539 tensor ekinmod, localpres;
541 /* The heat bath is coupled to a separate barostat, the last temperature group. In the
542 2006 Tuckerman et al paper., the order is iL_{T_baro} iL {T_part}
545 if (ir->epct == PressureCouplingType::SemiIsotropic)
554 /* eta is in pure units. veta is in units of ps^-1. GW is in
555 units of ps^-2. However, eta has a reference of 1 nm^3, so care must be
556 taken to use only RATIOS of eta in updating the volume. */
558 /* we take the partial pressure tensors, modify the
559 kinetic energy tensor, and recovert to pressure */
561 if (ir->opts.nrdf[0] == 0)
563 gmx_fatal(FARGS, "Barostat is coupled to a T-group with no degrees of freedom\n");
565 /* alpha factor for phase space volume, then multiply by the ekin scaling factor. */
566 alpha = 1.0 + DIM / (static_cast<double>(ir->opts.nrdf[0]));
567 alpha *= ekind->tcstat[0].ekinscalef_nhc;
568 msmul(ekind->ekin, alpha, ekinmod);
569 /* for now, we use Elr = 0, because if you want to get it right, you
570 really should be using PME. Maybe print a warning? */
572 pscal = calc_pres(ir->pbcType, nwall, box, ekinmod, vir, localpres) + pcorr;
575 GW = (vol * (MassQ->Winv / gmx::c_presfac))
576 * (DIM * pscal - trace(ir->ref_p)); /* W is in ps^2 * bar * nm^3 */
578 *veta += 0.5 * dt * GW;
582 * This file implements temperature and pressure coupling algorithms:
583 * For now only the Weak coupling and the modified weak coupling.
585 * Furthermore computation of pressure and temperature is done here
589 real calc_pres(PbcType pbcType, int nwall, const matrix box, const tensor ekin, const tensor vir, tensor pres)
594 if (pbcType == PbcType::No || (pbcType == PbcType::XY && nwall != 2))
600 /* Uitzoeken welke ekin hier van toepassing is, zie Evans & Morris - E.
601 * Wrs. moet de druktensor gecorrigeerd worden voor de netto stroom in
605 fac = gmx::c_presfac * 2.0 / det(box);
606 for (n = 0; (n < DIM); n++)
608 for (m = 0; (m < DIM); m++)
610 pres[n][m] = (ekin[n][m] - vir[n][m]) * fac;
616 pr_rvecs(debug, 0, "PC: pres", pres, DIM);
617 pr_rvecs(debug, 0, "PC: ekin", ekin, DIM);
618 pr_rvecs(debug, 0, "PC: vir ", vir, DIM);
619 pr_rvecs(debug, 0, "PC: box ", box, DIM);
622 return trace(pres) / DIM;
625 real calc_temp(real ekin, real nrdf)
629 return (2.0 * ekin) / (nrdf * gmx::c_boltz);
637 /*! \brief Sets 1/mass for Parrinello-Rahman in wInv; NOTE: c_presfac is not included, so not in GROMACS units! */
638 static void calcParrinelloRahmanInvMass(const t_inputrec* ir, const matrix box, tensor wInv)
642 /* TODO: See if we can make the mass independent of the box size */
643 maxBoxLength = std::max(box[XX][XX], box[YY][YY]);
644 maxBoxLength = std::max(maxBoxLength, box[ZZ][ZZ]);
646 for (int d = 0; d < DIM; d++)
648 for (int n = 0; n < DIM; n++)
650 wInv[d][n] = (4 * M_PI * M_PI * ir->compress[d][n]) / (3 * ir->tau_p * ir->tau_p * maxBoxLength);
655 void parrinellorahman_pcoupl(FILE* fplog,
657 const t_inputrec* ir,
667 /* This doesn't do any coordinate updating. It just
668 * integrates the box vector equations from the calculated
669 * acceleration due to pressure difference. We also compute
670 * the tensor M which is used in update to couple the particle
671 * coordinates to the box vectors.
673 * In Nose and Klein (Mol.Phys 50 (1983) no 5., p 1055) this is
676 * M_nk = (h') * (h' * h + h' h) * h
678 * with the dots denoting time derivatives and h is the transformation from
679 * the scaled frame to the real frame, i.e. the TRANSPOSE of the box.
680 * This also goes for the pressure and M tensors - they are transposed relative
681 * to ours. Our equation thus becomes:
684 * M_gmx = M_nk' = b * (b * b' + b * b') * b'
686 * where b is the gromacs box matrix.
687 * Our box accelerations are given by
689 * b = vol/W inv(box') * (P-ref_P) (=h')
692 real vol = box[XX][XX] * box[YY][YY] * box[ZZ][ZZ];
693 real atot, arel, change;
694 tensor invbox, pdiff, t1, t2;
696 gmx::invertBoxMatrix(box, invbox);
700 /* Note that c_presfac does not occur here.
701 * The pressure and compressibility always occur as a product,
702 * therefore the pressure unit drops out.
705 calcParrinelloRahmanInvMass(ir, box, winv);
707 m_sub(pres, ir->ref_p, pdiff);
709 if (ir->epct == PressureCouplingType::SurfaceTension)
711 /* Unlike Berendsen coupling it might not be trivial to include a z
712 * pressure correction here? On the other hand we don't scale the
713 * box momentarily, but change accelerations, so it might not be crucial.
715 real xy_pressure = 0.5 * (pres[XX][XX] + pres[YY][YY]);
716 for (int d = 0; d < ZZ; d++)
718 pdiff[d][d] = (xy_pressure - (pres[ZZ][ZZ] - ir->ref_p[d][d] / box[d][d]));
722 tmmul(invbox, pdiff, t1);
723 /* Move the off-diagonal elements of the 'force' to one side to ensure
724 * that we obey the box constraints.
726 for (int d = 0; d < DIM; d++)
728 for (int n = 0; n < d; n++)
730 t1[d][n] += t1[n][d];
737 case PressureCouplingType::Anisotropic:
738 for (int d = 0; d < DIM; d++)
740 for (int n = 0; n <= d; n++)
742 t1[d][n] *= winv[d][n] * vol;
746 case PressureCouplingType::Isotropic:
747 /* calculate total volume acceleration */
748 atot = box[XX][XX] * box[YY][YY] * t1[ZZ][ZZ] + box[XX][XX] * t1[YY][YY] * box[ZZ][ZZ]
749 + t1[XX][XX] * box[YY][YY] * box[ZZ][ZZ];
750 arel = atot / (3 * vol);
751 /* set all RELATIVE box accelerations equal, and maintain total V
753 for (int d = 0; d < DIM; d++)
755 for (int n = 0; n <= d; n++)
757 t1[d][n] = winv[0][0] * vol * arel * box[d][n];
761 case PressureCouplingType::SemiIsotropic:
762 case PressureCouplingType::SurfaceTension:
763 /* Note the correction to pdiff above for surftens. coupling */
765 /* calculate total XY volume acceleration */
766 atot = box[XX][XX] * t1[YY][YY] + t1[XX][XX] * box[YY][YY];
767 arel = atot / (2 * box[XX][XX] * box[YY][YY]);
768 /* set RELATIVE XY box accelerations equal, and maintain total V
769 * change speed. Dont change the third box vector accelerations */
770 for (int d = 0; d < ZZ; d++)
772 for (int n = 0; n <= d; n++)
774 t1[d][n] = winv[d][n] * vol * arel * box[d][n];
777 for (int n = 0; n < DIM; n++)
779 t1[ZZ][n] *= winv[ZZ][n] * vol;
784 "Parrinello-Rahman pressure coupling type %s "
785 "not supported yet\n",
786 enumValueToString(ir->epct));
790 for (int d = 0; d < DIM; d++)
792 for (int n = 0; n <= d; n++)
794 boxv[d][n] += dt * t1[d][n];
796 /* We do NOT update the box vectors themselves here, since
797 * we need them for shifting later. It is instead done last
798 * in the update() routine.
801 /* Calculate the change relative to diagonal elements-
802 since it's perfectly ok for the off-diagonal ones to
803 be zero it doesn't make sense to check the change relative
807 change = std::fabs(dt * boxv[d][n] / box[d][d]);
809 if (change > maxchange)
816 if (maxchange > 0.01 && fplog)
820 "\nStep %s Warning: Pressure scaling more than 1%%. "
821 "This may mean your system\n is not yet equilibrated. "
822 "Use of Parrinello-Rahman pressure coupling during\n"
823 "equilibration can lead to simulation instability, "
824 "and is discouraged.\n",
825 gmx_step_str(step, buf));
829 preserve_box_shape(ir, box_rel, boxv);
831 mtmul(boxv, box, t1); /* t1=boxv * b' */
832 mmul(invbox, t1, t2);
833 mtmul(t2, invbox, M);
835 /* Determine the scaling matrix mu for the coordinates */
836 for (int d = 0; d < DIM; d++)
838 for (int n = 0; n <= d; n++)
840 t1[d][n] = box[d][n] + dt * boxv[d][n];
843 preserve_box_shape(ir, box_rel, t1);
844 /* t1 is the box at t+dt, determine mu as the relative change */
845 mmul_ur0(invbox, t1, mu);
848 //! Return compressibility factor for entry (i,j) of Berendsen / C-rescale scaling matrix
849 static inline real compressibilityFactor(int i, int j, const t_inputrec* ir, real dt)
851 return ir->compress[i][j] * dt / ir->tau_p;
854 //! Details of Berendsen / C-rescale scaling matrix calculation
855 template<PressureCoupling pressureCouplingType>
856 static void calculateScalingMatrixImplDetail(const t_inputrec* ir,
861 real scalar_pressure,
865 //! Calculate Berendsen / C-rescale scaling matrix
866 template<PressureCoupling pressureCouplingType>
867 static void calculateScalingMatrixImpl(const t_inputrec* ir,
874 real scalar_pressure = 0;
875 real xy_pressure = 0;
876 for (int d = 0; d < DIM; d++)
878 scalar_pressure += pres[d][d] / DIM;
881 xy_pressure += pres[d][d] / (DIM - 1);
885 calculateScalingMatrixImplDetail<pressureCouplingType>(
886 ir, mu, dt, pres, box, scalar_pressure, xy_pressure, step);
890 void calculateScalingMatrixImplDetail<PressureCoupling::Berendsen>(const t_inputrec* ir,
895 real scalar_pressure,
897 int64_t gmx_unused step)
902 case PressureCouplingType::Isotropic:
903 for (int d = 0; d < DIM; d++)
905 mu[d][d] = 1.0 - compressibilityFactor(d, d, ir, dt) * (ir->ref_p[d][d] - scalar_pressure) / DIM;
908 case PressureCouplingType::SemiIsotropic:
909 for (int d = 0; d < ZZ; d++)
911 mu[d][d] = 1.0 - compressibilityFactor(d, d, ir, dt) * (ir->ref_p[d][d] - xy_pressure) / DIM;
914 1.0 - compressibilityFactor(ZZ, ZZ, ir, dt) * (ir->ref_p[ZZ][ZZ] - pres[ZZ][ZZ]) / DIM;
916 case PressureCouplingType::Anisotropic:
917 for (int d = 0; d < DIM; d++)
919 for (int n = 0; n < DIM; n++)
921 mu[d][n] = (d == n ? 1.0 : 0.0)
922 - compressibilityFactor(d, n, ir, dt) * (ir->ref_p[d][n] - pres[d][n]) / DIM;
926 case PressureCouplingType::SurfaceTension:
927 /* ir->ref_p[0/1] is the reference surface-tension times *
928 * the number of surfaces */
929 if (ir->compress[ZZ][ZZ] != 0.0F)
931 p_corr_z = dt / ir->tau_p * (ir->ref_p[ZZ][ZZ] - pres[ZZ][ZZ]);
935 /* when the compressibity is zero, set the pressure correction *
936 * in the z-direction to zero to get the correct surface tension */
939 mu[ZZ][ZZ] = 1.0 - ir->compress[ZZ][ZZ] * p_corr_z;
940 for (int d = 0; d < DIM - 1; d++)
943 + compressibilityFactor(d, d, ir, dt)
944 * (ir->ref_p[d][d] / (mu[ZZ][ZZ] * box[ZZ][ZZ])
945 - (pres[ZZ][ZZ] + p_corr_z - xy_pressure))
951 "Berendsen pressure coupling type %s not supported yet\n",
952 enumValueToString(ir->epct));
957 void calculateScalingMatrixImplDetail<PressureCoupling::CRescale>(const t_inputrec* ir,
962 real scalar_pressure,
966 gmx::ThreeFry2x64<64> rng(ir->ld_seed, gmx::RandomDomain::Barostat);
967 gmx::NormalDistribution<real> normalDist;
968 rng.restart(step, 0);
970 for (int d = 0; d < DIM; d++)
976 real kt = ir->opts.ref_t[0] * gmx::c_boltz;
984 case PressureCouplingType::Isotropic:
985 gauss = normalDist(rng);
986 for (int d = 0; d < DIM; d++)
988 const real factor = compressibilityFactor(d, d, ir, dt);
989 mu[d][d] = std::exp(-factor * (ir->ref_p[d][d] - scalar_pressure) / DIM
990 + std::sqrt(2.0 * kt * factor * gmx::c_presfac / vol) * gauss / DIM);
993 case PressureCouplingType::SemiIsotropic:
994 gauss = normalDist(rng);
995 gauss2 = normalDist(rng);
996 for (int d = 0; d < ZZ; d++)
998 const real factor = compressibilityFactor(d, d, ir, dt);
999 mu[d][d] = std::exp(-factor * (ir->ref_p[d][d] - xy_pressure) / DIM
1000 + std::sqrt((DIM - 1) * 2.0 * kt * factor * gmx::c_presfac / vol / DIM)
1001 / (DIM - 1) * gauss);
1004 const real factor = compressibilityFactor(ZZ, ZZ, ir, dt);
1005 mu[ZZ][ZZ] = std::exp(-factor * (ir->ref_p[ZZ][ZZ] - pres[ZZ][ZZ]) / DIM
1006 + std::sqrt(2.0 * kt * factor * gmx::c_presfac / vol / DIM) * gauss2);
1009 case PressureCouplingType::SurfaceTension:
1010 gauss = normalDist(rng);
1011 gauss2 = normalDist(rng);
1012 for (int d = 0; d < ZZ; d++)
1014 const real factor = compressibilityFactor(d, d, ir, dt);
1015 /* Notice: we here use ref_p[ZZ][ZZ] as isotropic pressure and ir->ref_p[d][d] as surface tension */
1016 mu[d][d] = std::exp(
1017 -factor * (ir->ref_p[ZZ][ZZ] - ir->ref_p[d][d] / box[ZZ][ZZ] - xy_pressure) / DIM
1018 + std::sqrt(4.0 / 3.0 * kt * factor * gmx::c_presfac / vol) / (DIM - 1) * gauss);
1021 const real factor = compressibilityFactor(ZZ, ZZ, ir, dt);
1022 mu[ZZ][ZZ] = std::exp(-factor * (ir->ref_p[ZZ][ZZ] - pres[ZZ][ZZ]) / DIM
1023 + std::sqrt(2.0 / 3.0 * kt * factor * gmx::c_presfac / vol) * gauss2);
1028 "C-rescale pressure coupling type %s not supported yet\n",
1029 enumValueToString(ir->epct));
1033 template<PressureCoupling pressureCouplingType>
1034 void pressureCouplingCalculateScalingMatrix(FILE* fplog,
1036 const t_inputrec* ir,
1040 const matrix force_vir,
1041 const matrix constraint_vir,
1043 double* baros_integral)
1045 static_assert(pressureCouplingType == PressureCoupling::Berendsen
1046 || pressureCouplingType == PressureCoupling::CRescale,
1047 "pressureCouplingCalculateScalingMatrix is only implemented for Berendsen and "
1048 "C-rescale pressure coupling");
1050 calculateScalingMatrixImpl<pressureCouplingType>(ir, mu, dt, pres, box, step);
1052 /* To fulfill the orientation restrictions on triclinic boxes
1053 * we will set mu_yx, mu_zx and mu_zy to 0 and correct
1054 * the other elements of mu to first order.
1056 mu[YY][XX] += mu[XX][YY];
1057 mu[ZZ][XX] += mu[XX][ZZ];
1058 mu[ZZ][YY] += mu[YY][ZZ];
1063 /* Keep track of the work the barostat applies on the system.
1064 * Without constraints force_vir tells us how Epot changes when scaling.
1065 * With constraints constraint_vir gives us the constraint contribution
1066 * to both Epot and Ekin. Although we are not scaling velocities, scaling
1067 * the coordinates leads to scaling of distances involved in constraints.
1068 * This in turn changes the angular momentum (even if the constrained
1069 * distances are corrected at the next step). The kinetic component
1070 * of the constraint virial captures the angular momentum change.
1072 for (int d = 0; d < DIM; d++)
1074 for (int n = 0; n <= d; n++)
1077 2 * (mu[d][n] - (n == d ? 1 : 0)) * (force_vir[d][n] + constraint_vir[d][n]);
1083 pr_rvecs(debug, 0, "PC: pres ", pres, 3);
1084 pr_rvecs(debug, 0, "PC: mu ", mu, 3);
1087 if (mu[XX][XX] < 0.99 || mu[XX][XX] > 1.01 || mu[YY][YY] < 0.99 || mu[YY][YY] > 1.01
1088 || mu[ZZ][ZZ] < 0.99 || mu[ZZ][ZZ] > 1.01)
1093 "\nStep %s Warning: pressure scaling more than 1%%, "
1095 gmx_step_str(step, buf2),
1101 fprintf(fplog, "%s", buf);
1103 fprintf(stderr, "%s", buf);
1107 template<PressureCoupling pressureCouplingType>
1108 void pressureCouplingScaleBoxAndCoordinates(const t_inputrec* ir,
1116 const unsigned short cFREEZE[],
1118 const bool scaleCoordinates)
1120 static_assert(pressureCouplingType == PressureCoupling::Berendsen
1121 || pressureCouplingType == PressureCoupling::CRescale,
1122 "pressureCouplingScaleBoxAndCoordinates is only implemented for Berendsen and "
1123 "C-rescale pressure coupling");
1125 ivec* nFreeze = ir->opts.nFreeze;
1127 if (pressureCouplingType == PressureCoupling::CRescale)
1129 gmx::invertBoxMatrix(mu, inv_mu);
1132 /* Scale the positions and the velocities */
1133 if (scaleCoordinates)
1135 const int gmx_unused numThreads = gmx_omp_nthreads_get(emntUpdate);
1136 #pragma omp parallel for num_threads(numThreads) schedule(static)
1137 for (int n = start; n < start + nr_atoms; n++)
1139 // Trivial OpenMP region that does not throw
1141 if (cFREEZE != nullptr)
1146 if (!nFreeze[g][XX])
1148 x[n][XX] = mu[XX][XX] * x[n][XX] + mu[YY][XX] * x[n][YY] + mu[ZZ][XX] * x[n][ZZ];
1149 if (pressureCouplingType == PressureCoupling::CRescale)
1151 v[n][XX] = inv_mu[XX][XX] * v[n][XX] + inv_mu[YY][XX] * v[n][YY]
1152 + inv_mu[ZZ][XX] * v[n][ZZ];
1155 if (!nFreeze[g][YY])
1157 x[n][YY] = mu[YY][YY] * x[n][YY] + mu[ZZ][YY] * x[n][ZZ];
1158 if (pressureCouplingType == PressureCoupling::CRescale)
1160 v[n][YY] = inv_mu[YY][YY] * v[n][YY] + inv_mu[ZZ][YY] * v[n][ZZ];
1163 if (!nFreeze[g][ZZ])
1165 x[n][ZZ] = mu[ZZ][ZZ] * x[n][ZZ];
1166 if (pressureCouplingType == PressureCoupling::CRescale)
1168 v[n][ZZ] = inv_mu[ZZ][ZZ] * v[n][ZZ];
1173 /* compute final boxlengths */
1174 for (int d = 0; d < DIM; d++)
1176 box[d][XX] = mu[XX][XX] * box[d][XX] + mu[YY][XX] * box[d][YY] + mu[ZZ][XX] * box[d][ZZ];
1177 box[d][YY] = mu[YY][YY] * box[d][YY] + mu[ZZ][YY] * box[d][ZZ];
1178 box[d][ZZ] = mu[ZZ][ZZ] * box[d][ZZ];
1181 preserve_box_shape(ir, box_rel, box);
1183 /* (un)shifting should NOT be done after this,
1184 * since the box vectors might have changed
1186 inc_nrnb(nrnb, eNR_PCOUPL, nr_atoms);
1189 void berendsen_tcoupl(const t_inputrec* ir, gmx_ekindata_t* ekind, real dt, std::vector<double>& therm_integral)
1191 const t_grpopts* opts = &ir->opts;
1193 for (int i = 0; (i < opts->ngtc); i++)
1197 if (ir->eI == IntegrationAlgorithm::VV)
1199 Ek = trace(ekind->tcstat[i].ekinf);
1200 T = ekind->tcstat[i].T;
1204 Ek = trace(ekind->tcstat[i].ekinh);
1205 T = ekind->tcstat[i].Th;
1208 if ((opts->tau_t[i] > 0) && (T > 0.0))
1210 real reft = std::max<real>(0, opts->ref_t[i]);
1211 real lll = std::sqrt(1.0 + (dt / opts->tau_t[i]) * (reft / T - 1.0));
1212 ekind->tcstat[i].lambda = std::max<real>(std::min<real>(lll, 1.25), 0.8);
1216 ekind->tcstat[i].lambda = 1.0;
1219 /* Keep track of the amount of energy we are adding to the system */
1220 therm_integral[i] -= (gmx::square(ekind->tcstat[i].lambda) - 1) * Ek;
1224 fprintf(debug, "TC: group %d: T: %g, Lambda: %g\n", i, T, ekind->tcstat[i].lambda);
1229 void andersen_tcoupl(const t_inputrec* ir,
1231 const t_commrec* cr,
1232 const t_mdatoms* md,
1233 gmx::ArrayRef<gmx::RVec> v,
1235 const std::vector<bool>& randomize,
1236 gmx::ArrayRef<const real> boltzfac)
1238 const int* gatindex = (DOMAINDECOMP(cr) ? cr->dd->globalAtomIndices.data() : nullptr);
1241 gmx::ThreeFry2x64<0> rng(ir->andersen_seed, gmx::RandomDomain::Thermostat);
1242 gmx::UniformRealDistribution<real> uniformDist;
1243 gmx::TabulatedNormalDistribution<real, 14> normalDist;
1245 /* randomize the velocities of the selected particles */
1247 for (i = 0; i < md->homenr; i++) /* now loop over the list of atoms */
1249 int ng = gatindex ? gatindex[i] : i;
1250 gmx_bool bRandomize;
1252 rng.restart(step, ng);
1256 gc = md->cTC[i]; /* assign the atom to a temperature group if there are more than one */
1260 if (ir->etc == TemperatureCoupling::AndersenMassive)
1262 /* Randomize particle always */
1267 /* Randomize particle probabilistically */
1268 uniformDist.reset();
1269 bRandomize = uniformDist(rng) < rate;
1276 scal = std::sqrt(boltzfac[gc] * md->invmass[i]);
1280 for (d = 0; d < DIM; d++)
1282 v[i][d] = scal * normalDist(rng);
1290 void nosehoover_tcoupl(const t_grpopts* opts,
1291 const gmx_ekindata_t* ekind,
1295 const t_extmass* MassQ)
1300 /* note that this routine does not include Nose-hoover chains yet. Should be easy to add. */
1302 for (i = 0; (i < opts->ngtc); i++)
1304 reft = std::max<real>(0, opts->ref_t[i]);
1306 vxi[i] += dt * MassQ->Qinv[i] * (ekind->tcstat[i].Th - reft);
1307 xi[i] += dt * (oldvxi + vxi[i]) * 0.5;
1311 void trotter_update(const t_inputrec* ir,
1313 gmx_ekindata_t* ekind,
1314 const gmx_enerdata_t* enerd,
1317 const t_mdatoms* md,
1318 const t_extmass* MassQ,
1319 gmx::ArrayRef<std::vector<int>> trotter_seqlist,
1323 int n, i, d, ngtc, gc = 0, t;
1324 t_grp_tcstat* tcstat;
1325 const t_grpopts* opts;
1328 double * scalefac, dtc;
1329 rvec sumv = { 0, 0, 0 };
1332 if (trotter_seqno <= ettTSEQ2)
1334 step_eff = step - 1; /* the velocity verlet calls are actually out of order -- the first
1335 half step is actually the last half step from the previous step.
1336 Thus the first half step actually corresponds to the n-1 step*/
1343 bCouple = (ir->nsttcouple == 1 || do_per_step(step_eff + ir->nsttcouple, ir->nsttcouple));
1345 const gmx::ArrayRef<const int> trotter_seq = trotter_seqlist[trotter_seqno];
1347 if ((trotter_seq[0] == etrtSKIPALL) || (!bCouple))
1351 dtc = ir->nsttcouple * ir->delta_t; /* This is OK for NPT, because nsttcouple == nstpcouple is enforcesd */
1352 opts = &(ir->opts); /* just for ease of referencing */
1355 snew(scalefac, opts->ngtc);
1356 for (i = 0; i < ngtc; i++)
1360 /* execute the series of trotter updates specified in the trotterpart array */
1362 for (i = 0; i < NTROTTERPARTS; i++)
1364 /* allow for doubled intgrators by doubling dt instead of making 2 calls */
1365 if ((trotter_seq[i] == etrtBAROV2) || (trotter_seq[i] == etrtBARONHC2)
1366 || (trotter_seq[i] == etrtNHC2))
1375 auto v = makeArrayRef(state->v);
1376 switch (trotter_seq[i])
1380 boxv_trotter(ir, &(state->veta), dt, state->box, ekind, vir, enerd->term[F_PDISPCORR], MassQ);
1388 state->nhpres_xi.data(),
1389 state->nhpres_vxi.data(),
1401 state->nosehoover_xi.data(),
1402 state->nosehoover_vxi.data(),
1406 (ir->eI == IntegrationAlgorithm::VV));
1407 /* need to rescale the kinetic energies and velocities here. Could
1408 scale the velocities later, but we need them scaled in order to
1409 produce the correct outputs, so we'll scale them here. */
1411 for (t = 0; t < ngtc; t++)
1413 tcstat = &ekind->tcstat[t];
1414 tcstat->vscale_nhc = scalefac[t];
1415 tcstat->ekinscaleh_nhc *= (scalefac[t] * scalefac[t]);
1416 tcstat->ekinscalef_nhc *= (scalefac[t] * scalefac[t]);
1418 /* now that we've scaled the groupwise velocities, we can add them up to get the total */
1419 /* but do we actually need the total? */
1421 /* modify the velocities as well */
1422 for (n = 0; n < md->homenr; n++)
1424 if (md->cTC) /* does this conditional need to be here? is this always true?*/
1428 for (d = 0; d < DIM; d++)
1430 v[n][d] *= scalefac[gc];
1435 for (d = 0; d < DIM; d++)
1437 sumv[d] += (v[n][d]) / md->invmass[n];
1445 /* check for conserved momentum -- worth looking at this again eventually, but not working right now.*/
1450 extern void init_npt_masses(const t_inputrec* ir, t_state* state, t_extmass* MassQ, gmx_bool bInit)
1452 int n, i, j, d, ngtc, nh;
1453 const t_grpopts* opts;
1454 real reft, kT, ndj, nd;
1456 opts = &(ir->opts); /* just for ease of referencing */
1457 ngtc = ir->opts.ngtc;
1458 nh = state->nhchainlength;
1460 if (ir->eI == IntegrationAlgorithm::MD)
1464 MassQ->Qinv.resize(ngtc);
1466 for (i = 0; (i < ngtc); i++)
1468 if ((opts->tau_t[i] > 0) && (opts->ref_t[i] > 0))
1470 MassQ->Qinv[i] = 1.0 / (gmx::square(opts->tau_t[i] / M_2PI) * opts->ref_t[i]);
1474 MassQ->Qinv[i] = 0.0;
1478 else if (EI_VV(ir->eI))
1480 /* Set pressure variables */
1484 if (state->vol0 == 0)
1486 state->vol0 = det(state->box);
1487 /* because we start by defining a fixed
1488 compressibility, we need the volume at this
1489 compressibility to solve the problem. */
1493 /* units are nm^3 * ns^2 / (nm^3 * bar / kJ/mol) = kJ/mol */
1494 /* Consider evaluating eventually if this the right mass to use. All are correct, some might be more stable */
1495 MassQ->Winv = (gmx::c_presfac * trace(ir->compress) * gmx::c_boltz * opts->ref_t[0])
1496 / (DIM * state->vol0 * gmx::square(ir->tau_p / M_2PI));
1497 /* An alternate mass definition, from Tuckerman et al. */
1498 /* MassQ->Winv = 1.0/(gmx::square(ir->tau_p/M_2PI)*(opts->nrdf[0]+DIM)*c_boltz*opts->ref_t[0]); */
1499 for (d = 0; d < DIM; d++)
1501 for (n = 0; n < DIM; n++)
1503 MassQ->Winvm[d][n] = gmx::c_presfac * ir->compress[d][n]
1504 / (state->vol0 * gmx::square(ir->tau_p / M_2PI));
1505 /* not clear this is correct yet for the anisotropic case. Will need to reevaluate
1506 before using MTTK for anisotropic states.*/
1509 /* Allocate space for thermostat variables */
1512 MassQ->Qinv.resize(ngtc * nh);
1515 /* now, set temperature variables */
1516 for (i = 0; i < ngtc; i++)
1518 if (opts->tau_t[i] > 0 && opts->ref_t[i] > 0 && opts->nrdf[i] > 0)
1520 reft = std::max<real>(0, opts->ref_t[i]);
1522 kT = gmx::c_boltz * reft;
1523 for (j = 0; j < nh; j++)
1533 MassQ->Qinv[i * nh + j] = 1.0 / (gmx::square(opts->tau_t[i] / M_2PI) * ndj * kT);
1538 for (j = 0; j < nh; j++)
1540 MassQ->Qinv[i * nh + j] = 0.0;
1547 std::array<std::vector<int>, ettTSEQMAX>
1548 init_npt_vars(const t_inputrec* ir, t_state* state, t_extmass* MassQ, gmx_bool bTrotter)
1550 int i, j, nnhpres, nh;
1551 const t_grpopts* opts;
1552 real bmass, qmass, reft, kT;
1554 opts = &(ir->opts); /* just for ease of referencing */
1555 nnhpres = state->nnhpres;
1556 nh = state->nhchainlength;
1558 if (EI_VV(ir->eI) && (ir->epc == PressureCoupling::Mttk) && (ir->etc != TemperatureCoupling::NoseHoover))
1560 gmx_fatal(FARGS, "Cannot do MTTK pressure coupling without Nose-Hoover temperature control");
1563 init_npt_masses(ir, state, MassQ, TRUE);
1565 /* first, initialize clear all the trotter calls */
1566 std::array<std::vector<int>, ettTSEQMAX> trotter_seq;
1567 for (i = 0; i < ettTSEQMAX; i++)
1569 trotter_seq[i].resize(NTROTTERPARTS, etrtNONE);
1570 trotter_seq[i][0] = etrtSKIPALL;
1575 /* no trotter calls, so we never use the values in the array.
1576 * We access them (so we need to define them, but ignore
1582 /* compute the kinetic energy by using the half step velocities or
1583 * the kinetic energies, depending on the order of the trotter calls */
1585 if (ir->eI == IntegrationAlgorithm::VV)
1587 if (inputrecNptTrotter(ir))
1589 /* This is the complicated version - there are 4 possible calls, depending on ordering.
1590 We start with the initial one. */
1591 /* first, a round that estimates veta. */
1592 trotter_seq[0][0] = etrtBAROV;
1594 /* trotter_seq[1] is etrtNHC for 1/2 step velocities - leave zero */
1596 /* The first half trotter update */
1597 trotter_seq[2][0] = etrtBAROV;
1598 trotter_seq[2][1] = etrtNHC;
1599 trotter_seq[2][2] = etrtBARONHC;
1601 /* The second half trotter update */
1602 trotter_seq[3][0] = etrtBARONHC;
1603 trotter_seq[3][1] = etrtNHC;
1604 trotter_seq[3][2] = etrtBAROV;
1606 /* trotter_seq[4] is etrtNHC for second 1/2 step velocities - leave zero */
1608 else if (inputrecNvtTrotter(ir))
1610 /* This is the easy version - there are only two calls, both the same.
1611 Otherwise, even easier -- no calls */
1612 trotter_seq[2][0] = etrtNHC;
1613 trotter_seq[3][0] = etrtNHC;
1615 else if (inputrecNphTrotter(ir))
1617 /* This is the complicated version - there are 4 possible calls, depending on ordering.
1618 We start with the initial one. */
1619 /* first, a round that estimates veta. */
1620 trotter_seq[0][0] = etrtBAROV;
1622 /* trotter_seq[1] is etrtNHC for 1/2 step velocities - leave zero */
1624 /* The first half trotter update */
1625 trotter_seq[2][0] = etrtBAROV;
1626 trotter_seq[2][1] = etrtBARONHC;
1628 /* The second half trotter update */
1629 trotter_seq[3][0] = etrtBARONHC;
1630 trotter_seq[3][1] = etrtBAROV;
1632 /* trotter_seq[4] is etrtNHC for second 1/2 step velocities - leave zero */
1635 else if (ir->eI == IntegrationAlgorithm::VVAK)
1637 if (inputrecNptTrotter(ir))
1639 /* This is the complicated version - there are 4 possible calls, depending on ordering.
1640 We start with the initial one. */
1641 /* first, a round that estimates veta. */
1642 trotter_seq[0][0] = etrtBAROV;
1644 /* The first half trotter update, part 1 -- double update, because it commutes */
1645 trotter_seq[1][0] = etrtNHC;
1647 /* The first half trotter update, part 2 */
1648 trotter_seq[2][0] = etrtBAROV;
1649 trotter_seq[2][1] = etrtBARONHC;
1651 /* The second half trotter update, part 1 */
1652 trotter_seq[3][0] = etrtBARONHC;
1653 trotter_seq[3][1] = etrtBAROV;
1655 /* The second half trotter update */
1656 trotter_seq[4][0] = etrtNHC;
1658 else if (inputrecNvtTrotter(ir))
1660 /* This is the easy version - there is only one call, both the same.
1661 Otherwise, even easier -- no calls */
1662 trotter_seq[1][0] = etrtNHC;
1663 trotter_seq[4][0] = etrtNHC;
1665 else if (inputrecNphTrotter(ir))
1667 /* This is the complicated version - there are 4 possible calls, depending on ordering.
1668 We start with the initial one. */
1669 /* first, a round that estimates veta. */
1670 trotter_seq[0][0] = etrtBAROV;
1672 /* The first half trotter update, part 1 -- leave zero */
1673 trotter_seq[1][0] = etrtNHC;
1675 /* The first half trotter update, part 2 */
1676 trotter_seq[2][0] = etrtBAROV;
1677 trotter_seq[2][1] = etrtBARONHC;
1679 /* The second half trotter update, part 1 */
1680 trotter_seq[3][0] = etrtBARONHC;
1681 trotter_seq[3][1] = etrtBAROV;
1683 /* The second half trotter update -- blank for now */
1689 case PressureCouplingType::Isotropic:
1690 default: bmass = DIM * DIM; /* recommended mass parameters for isotropic barostat */
1693 MassQ->QPinv.resize(nnhpres * opts->nhchainlength);
1695 /* barostat temperature */
1696 if ((ir->tau_p > 0) && (opts->ref_t[0] > 0))
1698 reft = std::max<real>(0, opts->ref_t[0]);
1699 kT = gmx::c_boltz * reft;
1700 for (i = 0; i < nnhpres; i++)
1702 for (j = 0; j < nh; j++)
1712 MassQ->QPinv[i * opts->nhchainlength + j] =
1713 1.0 / (gmx::square(opts->tau_t[0] / M_2PI) * qmass * kT);
1719 for (i = 0; i < nnhpres; i++)
1721 for (j = 0; j < nh; j++)
1723 MassQ->QPinv[i * nh + j] = 0.0;
1730 static real energyNoseHoover(const t_inputrec* ir, const t_state* state, const t_extmass* MassQ)
1734 int nh = state->nhchainlength;
1736 for (int i = 0; i < ir->opts.ngtc; i++)
1738 const double* ixi = &state->nosehoover_xi[i * nh];
1739 const double* ivxi = &state->nosehoover_vxi[i * nh];
1740 const double* iQinv = &(MassQ->Qinv[i * nh]);
1742 real nd = ir->opts.nrdf[i];
1743 real reft = std::max<real>(ir->opts.ref_t[i], 0);
1744 real kT = gmx::c_boltz * reft;
1748 if (inputrecNvtTrotter(ir) || inputrecNptTrotter(ir))
1750 /* contribution from the thermal momenta of the NH chain */
1751 for (int j = 0; j < nh; j++)
1755 energy += 0.5 * gmx::square(ivxi[j]) / iQinv[j];
1756 /* contribution from the thermal variable of the NH chain */
1766 energy += ndj * ixi[j] * kT;
1770 else /* Other non Trotter temperature NH control -- no chains yet. */
1772 energy += 0.5 * gmx::c_boltz * nd * gmx::square(ivxi[0]) / iQinv[0];
1773 energy += nd * ixi[0] * kT;
1781 /* Returns the energy from the barostat thermostat chain */
1782 static real energyPressureMTTK(const t_inputrec* ir, const t_state* state, const t_extmass* MassQ)
1786 int nh = state->nhchainlength;
1788 for (int i = 0; i < state->nnhpres; i++)
1790 /* note -- assumes only one degree of freedom that is thermostatted in barostat */
1791 real reft = std::max<real>(ir->opts.ref_t[0], 0.0); /* using 'System' temperature */
1792 real kT = gmx::c_boltz * reft;
1794 for (int j = 0; j < nh; j++)
1796 double iQinv = MassQ->QPinv[i * nh + j];
1799 energy += 0.5 * gmx::square(state->nhpres_vxi[i * nh + j]) / iQinv;
1800 /* contribution from the thermal variable of the NH chain */
1801 energy += state->nhpres_xi[i * nh + j] * kT;
1806 "P-T-group: %10d Chain %4d ThermV: %15.8f ThermX: %15.8f",
1809 state->nhpres_vxi[i * nh + j],
1810 state->nhpres_xi[i * nh + j]);
1818 /* Returns the energy accumulated by the V-rescale or Berendsen thermostat */
1819 static real energyVrescale(const t_inputrec* ir, const t_state* state)
1822 for (int i = 0; i < ir->opts.ngtc; i++)
1824 energy += state->therm_integral[i];
1830 real NPT_energy(const t_inputrec* ir, const t_state* state, const t_extmass* MassQ)
1834 if (ir->epc != PressureCoupling::No)
1836 /* Compute the contribution of the pressure to the conserved quantity*/
1838 real vol = det(state->box);
1842 case PressureCoupling::ParrinelloRahman:
1844 /* contribution from the pressure momenta */
1846 calcParrinelloRahmanInvMass(ir, state->box, invMass);
1847 for (int d = 0; d < DIM; d++)
1849 for (int n = 0; n <= d; n++)
1851 if (invMass[d][n] > 0)
1853 energyNPT += 0.5 * gmx::square(state->boxv[d][n])
1854 / (invMass[d][n] * gmx::c_presfac);
1859 /* Contribution from the PV term.
1860 * Not that with non-zero off-diagonal reference pressures,
1861 * i.e. applied shear stresses, there are additional terms.
1862 * We don't support this here, since that requires keeping
1863 * track of unwrapped box diagonal elements. This case is
1864 * excluded in integratorHasConservedEnergyQuantity().
1866 energyNPT += vol * trace(ir->ref_p) / (DIM * gmx::c_presfac);
1869 case PressureCoupling::Mttk:
1870 /* contribution from the pressure momenta */
1871 energyNPT += 0.5 * gmx::square(state->veta) / MassQ->Winv;
1873 /* contribution from the PV term */
1874 energyNPT += vol * trace(ir->ref_p) / (DIM * gmx::c_presfac);
1876 if (ir->epc == PressureCoupling::Mttk)
1878 /* contribution from the MTTK chain */
1879 energyNPT += energyPressureMTTK(ir, state, MassQ);
1882 case PressureCoupling::Berendsen:
1883 case PressureCoupling::CRescale: energyNPT += state->baros_integral; break;
1887 "Conserved energy quantity for pressure coupling is not handled. A case "
1888 "should be added with either the conserved quantity added or nothing added "
1889 "and an exclusion added to integratorHasConservedEnergyQuantity().");
1895 case TemperatureCoupling::No: break;
1896 case TemperatureCoupling::VRescale:
1897 case TemperatureCoupling::Berendsen: energyNPT += energyVrescale(ir, state); break;
1898 case TemperatureCoupling::NoseHoover:
1899 energyNPT += energyNoseHoover(ir, state, MassQ);
1901 case TemperatureCoupling::Andersen:
1902 case TemperatureCoupling::AndersenMassive:
1903 // Not supported, excluded in integratorHasConservedEnergyQuantity()
1908 "Conserved energy quantity for temperature coupling is not handled. A case "
1909 "should be added with either the conserved quantity added or nothing added and "
1910 "an exclusion added to integratorHasConservedEnergyQuantity().");
1917 static real vrescale_sumnoises(real nn, gmx::ThreeFry2x64<>* rng, gmx::NormalDistribution<real>* normalDist)
1920 * Returns the sum of nn independent gaussian noises squared
1921 * (i.e. equivalent to summing the square of the return values
1922 * of nn calls to a normal distribution).
1924 const real ndeg_tol = 0.0001;
1926 gmx::GammaDistribution<real> gammaDist(0.5 * nn, 1.0);
1928 if (nn < 2 + ndeg_tol)
1933 nn_int = gmx::roundToInt(nn);
1935 if (nn - nn_int < -ndeg_tol || nn - nn_int > ndeg_tol)
1938 "The v-rescale thermostat was called with a group with #DOF=%f, but for "
1939 "#DOF<3 only integer #DOF are supported",
1944 for (i = 0; i < nn_int; i++)
1946 gauss = (*normalDist)(*rng);
1952 /* Use a gamma distribution for any real nn > 2 */
1953 r = 2.0 * gammaDist(*rng);
1959 real vrescale_resamplekin(real kk, real sigma, real ndeg, real taut, int64_t step, int64_t seed)
1962 * Generates a new value for the kinetic energy,
1963 * according to Bussi et al JCP (2007), Eq. (A7)
1964 * kk: present value of the kinetic energy of the atoms to be thermalized (in arbitrary units)
1965 * sigma: target average value of the kinetic energy (ndeg k_b T/2) (in the same units as kk)
1966 * ndeg: number of degrees of freedom of the atoms to be thermalized
1967 * taut: relaxation time of the thermostat, in units of 'how often this routine is called'
1969 real factor, rr, ekin_new;
1970 gmx::ThreeFry2x64<64> rng(seed, gmx::RandomDomain::Thermostat);
1971 gmx::NormalDistribution<real> normalDist;
1975 factor = exp(-1.0 / taut);
1982 rng.restart(step, 0);
1984 rr = normalDist(rng);
1988 * (sigma * (vrescale_sumnoises(ndeg - 1, &rng, &normalDist) + rr * rr) / ndeg - kk)
1989 + 2.0 * rr * std::sqrt(kk * sigma / ndeg * (1.0 - factor) * factor);
1994 void vrescale_tcoupl(const t_inputrec* ir, int64_t step, gmx_ekindata_t* ekind, real dt, double therm_integral[])
1996 const t_grpopts* opts;
1998 real Ek, Ek_ref1, Ek_ref, Ek_new;
2002 for (i = 0; (i < opts->ngtc); i++)
2004 if (ir->eI == IntegrationAlgorithm::VV)
2006 Ek = trace(ekind->tcstat[i].ekinf);
2010 Ek = trace(ekind->tcstat[i].ekinh);
2013 if (opts->tau_t[i] >= 0 && opts->nrdf[i] > 0 && Ek > 0)
2015 Ek_ref1 = 0.5 * opts->ref_t[i] * gmx::c_boltz;
2016 Ek_ref = Ek_ref1 * opts->nrdf[i];
2018 Ek_new = vrescale_resamplekin(Ek, Ek_ref, opts->nrdf[i], opts->tau_t[i] / dt, step, ir->ld_seed);
2020 /* Analytically Ek_new>=0, but we check for rounding errors */
2023 ekind->tcstat[i].lambda = 0.0;
2027 ekind->tcstat[i].lambda = std::sqrt(Ek_new / Ek);
2030 therm_integral[i] -= Ek_new - Ek;
2035 "TC: group %d: Ekr %g, Ek %g, Ek_new %g, Lambda: %g\n",
2040 ekind->tcstat[i].lambda);
2045 ekind->tcstat[i].lambda = 1.0;
2050 void rescale_velocities(const gmx_ekindata_t* ekind, const t_mdatoms* mdatoms, int start, int end, rvec v[])
2052 const unsigned short* cTC = mdatoms->cTC;
2053 gmx::ArrayRef<const t_grp_tcstat> tcstat = ekind->tcstat;
2055 for (int n = start; n < end; n++)
2062 const real lg = tcstat[gt].lambda;
2063 for (int d = 0; d < DIM; d++)
2070 //! Check whether we're doing simulated annealing
2071 bool doSimulatedAnnealing(const t_inputrec* ir)
2073 for (int i = 0; i < ir->opts.ngtc; i++)
2075 /* set bSimAnn if any group is being annealed */
2076 if (ir->opts.annealing[i] != SimulatedAnnealing::No)
2084 // TODO If we keep simulated annealing, make a proper module that
2085 // does not rely on changing inputrec.
2086 bool initSimulatedAnnealing(t_inputrec* ir, gmx::Update* upd)
2088 bool doSimAnnealing = doSimulatedAnnealing(ir);
2091 update_annealing_target_temp(ir, ir->init_t, upd);
2093 return doSimAnnealing;
2096 /* set target temperatures if we are annealing */
2097 void update_annealing_target_temp(t_inputrec* ir, real t, gmx::Update* upd)
2099 int i, j, n, npoints;
2100 real pert, thist = 0, x;
2102 for (i = 0; i < ir->opts.ngtc; i++)
2104 npoints = ir->opts.anneal_npoints[i];
2105 switch (ir->opts.annealing[i])
2107 case SimulatedAnnealing::No: continue;
2108 case SimulatedAnnealing::Periodic:
2109 /* calculate time modulo the period */
2110 pert = ir->opts.anneal_time[i][npoints - 1];
2111 n = static_cast<int>(t / pert);
2112 thist = t - n * pert; /* modulo time */
2113 /* Make sure rounding didn't get us outside the interval */
2114 if (std::fabs(thist - pert) < GMX_REAL_EPS * 100)
2119 case SimulatedAnnealing::Single: thist = t; break;
2122 "Death horror in update_annealing_target_temp (i=%d/%d npoints=%d)",
2127 /* We are doing annealing for this group if we got here,
2128 * and we have the (relative) time as thist.
2129 * calculate target temp */
2131 while ((j < npoints - 1) && (thist > (ir->opts.anneal_time[i][j + 1])))
2135 if (j < npoints - 1)
2137 /* Found our position between points j and j+1.
2138 * Interpolate: x is the amount from j+1, (1-x) from point j
2139 * First treat possible jumps in temperature as a special case.
2141 if ((ir->opts.anneal_time[i][j + 1] - ir->opts.anneal_time[i][j]) < GMX_REAL_EPS * 100)
2143 ir->opts.ref_t[i] = ir->opts.anneal_temp[i][j + 1];
2147 x = ((thist - ir->opts.anneal_time[i][j])
2148 / (ir->opts.anneal_time[i][j + 1] - ir->opts.anneal_time[i][j]));
2150 x * ir->opts.anneal_temp[i][j + 1] + (1 - x) * ir->opts.anneal_temp[i][j];
2155 ir->opts.ref_t[i] = ir->opts.anneal_temp[i][npoints - 1];
2159 upd->update_temperature_constants(*ir);
2162 void pleaseCiteCouplingAlgorithms(FILE* fplog, const t_inputrec& ir)
2164 if (EI_DYNAMICS(ir.eI))
2166 if (ir.etc == TemperatureCoupling::Berendsen)
2168 please_cite(fplog, "Berendsen84a");
2170 if (ir.etc == TemperatureCoupling::VRescale)
2172 please_cite(fplog, "Bussi2007a");
2174 if (ir.epc == PressureCoupling::CRescale)
2176 please_cite(fplog, "Bernetti2020");
2178 // TODO this is actually an integrator, not a coupling algorithm
2179 if (ir.eI == IntegrationAlgorithm::SD1)
2181 please_cite(fplog, "Goga2012");