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/state.h"
65 #include "gromacs/pbcutil/boxutilities.h"
66 #include "gromacs/pbcutil/pbc.h"
67 #include "gromacs/random/gammadistribution.h"
68 #include "gromacs/random/normaldistribution.h"
69 #include "gromacs/random/tabulatednormaldistribution.h"
70 #include "gromacs/random/threefry.h"
71 #include "gromacs/random/uniformrealdistribution.h"
72 #include "gromacs/utility/cstringutil.h"
73 #include "gromacs/utility/fatalerror.h"
74 #include "gromacs/utility/pleasecite.h"
75 #include "gromacs/utility/smalloc.h"
77 #define NTROTTERPARTS 3
79 /* Suzuki-Yoshida Constants, for n=3 and n=5, for symplectic integration */
81 /* for n=3, w0 = w2 = 1/(2-2^-(1/3)), w1 = 1-2*w0 */
82 /* for n=5, w0 = w1 = w3 = w4 = 1/(4-4^-(1/3)), w1 = 1-4*w0 */
84 #define SUZUKI_YOSHIDA_NUM 5
86 static const double sy_const_1[] = { 1. };
87 static const double sy_const_3[] = { 0.828981543588751, -0.657963087177502, 0.828981543588751 };
88 static const double sy_const_5[] = { 0.2967324292201065,
94 static constexpr std::array<const double*, 6> sy_const = { nullptr, sy_const_1, nullptr,
95 sy_const_3, nullptr, sy_const_5 };
98 void update_tcouple(int64_t step,
99 const t_inputrec* inputrec,
101 gmx_ekindata_t* ekind,
102 const t_extmass* MassQ,
104 gmx::ArrayRef<const unsigned short> cTC)
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:
147 &(inputrec->opts), ekind, dttc, state->nosehoover_xi, state->nosehoover_vxi, MassQ);
149 case TemperatureCoupling::VRescale:
150 vrescale_tcoupl(inputrec, step, ekind, dttc, state->therm_integral);
152 default: gmx_fatal(FARGS, "Unknown temperature coupling algorithm");
154 /* rescale in place here */
155 if (EI_VV(inputrec->eI))
157 rescale_velocities(ekind, cTC, 0, homenr, state->v);
162 // Set the T scaling lambda to 1 to have no scaling
163 // TODO: Do we have to do it on every non-t-couple step?
164 for (int i = 0; (i < inputrec->opts.ngtc); i++)
166 ekind->tcstat[i].lambda = 1.0;
171 void update_pcouple_before_coordinates(FILE* fplog,
173 const t_inputrec* inputrec,
175 matrix parrinellorahmanMu,
179 /* Berendsen P-coupling is completely handled after the coordinate update.
180 * Trotter P-coupling is handled by separate calls to trotter_update().
182 if (inputrec->epc == PressureCoupling::ParrinelloRahman
183 && do_per_step(step + inputrec->nstpcouple - 1, inputrec->nstpcouple))
185 real dtpc = inputrec->nstpcouple * inputrec->delta_t;
187 parrinellorahman_pcoupl(
188 fplog, step, inputrec, dtpc, state->pres_prev, state->box, state->box_rel, state->boxv, M, parrinellorahmanMu, bInitStep);
192 void update_pcouple_after_coordinates(FILE* fplog,
194 const t_inputrec* inputrec,
196 gmx::ArrayRef<const unsigned short> cFREEZE,
197 const matrix pressure,
198 const matrix forceVirial,
199 const matrix constraintVirial,
200 matrix pressureCouplingMu,
203 gmx::BoxDeformation* boxDeformation,
204 const bool scaleCoordinates)
208 /* Cast to real for faster code, no loss in precision (see comment above) */
209 real dt = inputrec->delta_t;
212 /* now update boxes */
213 switch (inputrec->epc)
215 case (PressureCoupling::No): break;
216 case (PressureCoupling::Berendsen):
217 if (do_per_step(step, inputrec->nstpcouple))
219 real dtpc = inputrec->nstpcouple * dt;
220 pressureCouplingCalculateScalingMatrix<PressureCoupling::Berendsen>(fplog,
229 &state->baros_integral);
230 pressureCouplingScaleBoxAndCoordinates<PressureCoupling::Berendsen>(
238 gmx::ArrayRef<gmx::RVec>(),
244 case (PressureCoupling::CRescale):
245 if (do_per_step(step, inputrec->nstpcouple))
247 real dtpc = inputrec->nstpcouple * dt;
248 pressureCouplingCalculateScalingMatrix<PressureCoupling::CRescale>(fplog,
257 &state->baros_integral);
258 pressureCouplingScaleBoxAndCoordinates<PressureCoupling::CRescale>(inputrec,
271 case (PressureCoupling::ParrinelloRahman):
272 if (do_per_step(step + inputrec->nstpcouple - 1, inputrec->nstpcouple))
274 /* The box velocities were updated in do_pr_pcoupl,
275 * but we dont change the box vectors until we get here
276 * since we need to be able to shift/unshift above.
278 real dtpc = inputrec->nstpcouple * dt;
279 for (int i = 0; i < DIM; i++)
281 for (int m = 0; m <= i; m++)
283 state->box[i][m] += dtpc * state->boxv[i][m];
286 preserve_box_shape(inputrec, state->box_rel, state->box);
288 /* Scale the coordinates */
289 if (scaleCoordinates)
291 auto* x = state->x.rvec_array();
292 for (int n = start; n < start + homenr; n++)
294 tmvmul_ur0(pressureCouplingMu, x[n], x[n]);
299 case (PressureCoupling::Mttk):
300 switch (inputrec->epct)
302 case (PressureCouplingType::Isotropic):
303 /* DIM * eta = ln V. so DIM*eta_new = DIM*eta_old + DIM*dt*veta =>
304 ln V_new = ln V_old + 3*dt*veta => V_new = V_old*exp(3*dt*veta) =>
305 Side length scales as exp(veta*dt) */
307 msmul(state->box, std::exp(state->veta * dt), state->box);
309 /* Relate veta to boxv. veta = d(eta)/dT = (1/DIM)*1/V dV/dT.
310 o If we assume isotropic scaling, and box length scaling
311 factor L, then V = L^DIM (det(M)). So dV/dt = DIM
312 L^(DIM-1) dL/dt det(M), and veta = (1/L) dL/dt. The
313 determinant of B is L^DIM det(M), and the determinant
314 of dB/dt is (dL/dT)^DIM det (M). veta will be
315 (det(dB/dT)/det(B))^(1/3). Then since M =
316 B_new*(vol_new)^(1/3), dB/dT_new = (veta_new)*B(new). */
318 msmul(state->box, state->veta, state->boxv);
328 auto localX = makeArrayRef(state->x).subArray(start, homenr);
329 boxDeformation->apply(localX, state->box, step);
333 extern bool update_randomize_velocities(const t_inputrec* ir,
337 gmx::ArrayRef<const unsigned short> cTC,
338 gmx::ArrayRef<const real> invMass,
339 gmx::ArrayRef<gmx::RVec> v,
340 const gmx::Update* upd,
341 const gmx::Constraints* constr)
344 real rate = (ir->delta_t) / ir->opts.tau_t[0];
346 if (ir->etc == TemperatureCoupling::Andersen && constr != nullptr)
348 /* Currently, Andersen thermostat does not support constrained
349 systems. Functionality exists in the andersen_tcoupl
350 function in GROMACS 4.5.7 to allow this combination. That
351 code could be ported to the current random-number
352 generation approach, but has not yet been done because of
353 lack of time and resources. */
355 "Normal Andersen is currently not supported with constraints, use massive "
359 /* proceed with andersen if 1) it's fixed probability per
360 particle andersen or 2) it's massive andersen and it's tau_t/dt */
361 if ((ir->etc == TemperatureCoupling::Andersen) || do_per_step(step, gmx::roundToInt(1.0 / rate)))
364 ir, step, cr, homenr, cTC, invMass, v, rate, upd->getAndersenRandomizeGroup(), upd->getBoltzmanFactor());
370 /* these integration routines are only referenced inside this file */
371 static void NHC_trotter(const t_grpopts* opts,
373 const gmx_ekindata_t* ekind,
379 const t_extmass* MassQ,
383 /* general routine for both barostat and thermostat nose hoover chains */
386 double Ekin, Efac, reft, kT, nd;
391 int mstepsi, mstepsj;
392 int ns = SUZUKI_YOSHIDA_NUM; /* set the degree of integration in the types/state.h file */
393 int nh = opts->nhchainlength;
396 mstepsi = mstepsj = ns;
398 /* if scalefac is NULL, we are doing the NHC of the barostat */
401 if (scalefac == nullptr)
406 for (i = 0; i < nvar; i++)
409 /* make it easier to iterate by selecting
410 out the sub-array that corresponds to this T group */
414 gmx::ArrayRef<const double> iQinv;
417 iQinv = gmx::arrayRefFromArray(&MassQ->QPinv[i * nh], nh);
418 nd = 1.0; /* THIS WILL CHANGE IF NOT ISOTROPIC */
419 reft = std::max<real>(0, opts->ref_t[0]);
420 Ekin = gmx::square(*veta) / MassQ->Winv;
424 iQinv = gmx::arrayRefFromArray(&MassQ->Qinv[i * nh], nh);
425 const t_grp_tcstat* tcstat = &ekind->tcstat[i];
427 reft = std::max<real>(0, opts->ref_t[i]);
430 Ekin = 2 * trace(tcstat->ekinf) * tcstat->ekinscalef_nhc;
434 Ekin = 2 * trace(tcstat->ekinh) * tcstat->ekinscaleh_nhc;
437 kT = gmx::c_boltz * reft;
439 for (mi = 0; mi < mstepsi; mi++)
441 for (mj = 0; mj < mstepsj; mj++)
443 /* weighting for this step using Suzuki-Yoshida integration - fixed at 5 */
444 dt = sy_const[ns][mj] * dtfull / mstepsi;
446 /* compute the thermal forces */
447 GQ[0] = iQinv[0] * (Ekin - nd * kT);
449 for (j = 0; j < nh - 1; j++)
451 if (iQinv[j + 1] > 0)
453 /* we actually don't need to update here if we save the
454 state of the GQ, but it's easier to just recompute*/
455 GQ[j + 1] = iQinv[j + 1] * ((gmx::square(ivxi[j]) / iQinv[j]) - kT);
463 ivxi[nh - 1] += 0.25 * dt * GQ[nh - 1];
464 for (j = nh - 1; j > 0; j--)
466 Efac = exp(-0.125 * dt * ivxi[j]);
467 ivxi[j - 1] = Efac * (ivxi[j - 1] * Efac + 0.25 * dt * GQ[j - 1]);
470 Efac = exp(-0.5 * dt * ivxi[0]);
479 Ekin *= (Efac * Efac);
481 /* Issue - if the KE is an average of the last and the current temperatures, then we
482 might not be able to scale the kinetic energy directly with this factor. Might
483 take more bookkeeping -- have to think about this a bit more . . . */
485 GQ[0] = iQinv[0] * (Ekin - nd * kT);
487 /* update thermostat positions */
488 for (j = 0; j < nh; j++)
490 ixi[j] += 0.5 * dt * ivxi[j];
493 for (j = 0; j < nh - 1; j++)
495 Efac = exp(-0.125 * dt * ivxi[j + 1]);
496 ivxi[j] = Efac * (ivxi[j] * Efac + 0.25 * dt * GQ[j]);
497 if (iQinv[j + 1] > 0)
499 GQ[j + 1] = iQinv[j + 1] * ((gmx::square(ivxi[j]) / iQinv[j]) - kT);
506 ivxi[nh - 1] += 0.25 * dt * GQ[nh - 1];
513 static void boxv_trotter(const t_inputrec* ir,
517 const gmx_ekindata_t* ekind,
520 const t_extmass* MassQ)
527 tensor ekinmod, localpres;
529 /* The heat bath is coupled to a separate barostat, the last temperature group. In the
530 2006 Tuckerman et al paper., the order is iL_{T_baro} iL {T_part}
533 if (ir->epct == PressureCouplingType::SemiIsotropic)
542 /* eta is in pure units. veta is in units of ps^-1. GW is in
543 units of ps^-2. However, eta has a reference of 1 nm^3, so care must be
544 taken to use only RATIOS of eta in updating the volume. */
546 /* we take the partial pressure tensors, modify the
547 kinetic energy tensor, and recovert to pressure */
549 if (ir->opts.nrdf[0] == 0)
551 gmx_fatal(FARGS, "Barostat is coupled to a T-group with no degrees of freedom\n");
553 /* alpha factor for phase space volume, then multiply by the ekin scaling factor. */
554 alpha = 1.0 + DIM / (static_cast<double>(ir->opts.nrdf[0]));
555 alpha *= ekind->tcstat[0].ekinscalef_nhc;
556 msmul(ekind->ekin, alpha, ekinmod);
557 /* for now, we use Elr = 0, because if you want to get it right, you
558 really should be using PME. Maybe print a warning? */
560 pscal = calc_pres(ir->pbcType, nwall, box, ekinmod, vir, localpres) + pcorr;
563 GW = (vol * (MassQ->Winv / gmx::c_presfac))
564 * (DIM * pscal - trace(ir->ref_p)); /* W is in ps^2 * bar * nm^3 */
566 *veta += 0.5 * dt * GW;
570 * This file implements temperature and pressure coupling algorithms:
571 * For now only the Weak coupling and the modified weak coupling.
573 * Furthermore computation of pressure and temperature is done here
577 real calc_pres(PbcType pbcType, int nwall, const matrix box, const tensor ekin, const tensor vir, tensor pres)
582 if (pbcType == PbcType::No || (pbcType == PbcType::XY && nwall != 2))
588 /* Uitzoeken welke ekin hier van toepassing is, zie Evans & Morris - E.
589 * Wrs. moet de druktensor gecorrigeerd worden voor de netto stroom in
593 fac = gmx::c_presfac * 2.0 / det(box);
594 for (n = 0; (n < DIM); n++)
596 for (m = 0; (m < DIM); m++)
598 pres[n][m] = (ekin[n][m] - vir[n][m]) * fac;
604 pr_rvecs(debug, 0, "PC: pres", pres, DIM);
605 pr_rvecs(debug, 0, "PC: ekin", ekin, DIM);
606 pr_rvecs(debug, 0, "PC: vir ", vir, DIM);
607 pr_rvecs(debug, 0, "PC: box ", box, DIM);
610 return trace(pres) / DIM;
613 real calc_temp(real ekin, real nrdf)
617 return (2.0 * ekin) / (nrdf * gmx::c_boltz);
625 /*! \brief Sets 1/mass for Parrinello-Rahman in wInv; NOTE: c_presfac is not included, so not in GROMACS units! */
626 static void calcParrinelloRahmanInvMass(const t_inputrec* ir, const matrix box, tensor wInv)
630 /* TODO: See if we can make the mass independent of the box size */
631 maxBoxLength = std::max(box[XX][XX], box[YY][YY]);
632 maxBoxLength = std::max(maxBoxLength, box[ZZ][ZZ]);
634 for (int d = 0; d < DIM; d++)
636 for (int n = 0; n < DIM; n++)
638 wInv[d][n] = (4 * M_PI * M_PI * ir->compress[d][n]) / (3 * ir->tau_p * ir->tau_p * maxBoxLength);
643 void parrinellorahman_pcoupl(FILE* fplog,
645 const t_inputrec* ir,
655 /* This doesn't do any coordinate updating. It just
656 * integrates the box vector equations from the calculated
657 * acceleration due to pressure difference. We also compute
658 * the tensor M which is used in update to couple the particle
659 * coordinates to the box vectors.
661 * In Nose and Klein (Mol.Phys 50 (1983) no 5., p 1055) this is
664 * M_nk = (h') * (h' * h + h' h) * h
666 * with the dots denoting time derivatives and h is the transformation from
667 * the scaled frame to the real frame, i.e. the TRANSPOSE of the box.
668 * This also goes for the pressure and M tensors - they are transposed relative
669 * to ours. Our equation thus becomes:
672 * M_gmx = M_nk' = b * (b * b' + b * b') * b'
674 * where b is the gromacs box matrix.
675 * Our box accelerations are given by
677 * b = vol/W inv(box') * (P-ref_P) (=h')
680 real vol = box[XX][XX] * box[YY][YY] * box[ZZ][ZZ];
681 real atot, arel, change;
682 tensor invbox, pdiff, t1, t2;
684 gmx::invertBoxMatrix(box, invbox);
688 /* Note that c_presfac does not occur here.
689 * The pressure and compressibility always occur as a product,
690 * therefore the pressure unit drops out.
693 calcParrinelloRahmanInvMass(ir, box, winv);
695 m_sub(pres, ir->ref_p, pdiff);
697 if (ir->epct == PressureCouplingType::SurfaceTension)
699 /* Unlike Berendsen coupling it might not be trivial to include a z
700 * pressure correction here? On the other hand we don't scale the
701 * box momentarily, but change accelerations, so it might not be crucial.
703 real xy_pressure = 0.5 * (pres[XX][XX] + pres[YY][YY]);
704 for (int d = 0; d < ZZ; d++)
706 pdiff[d][d] = (xy_pressure - (pres[ZZ][ZZ] - ir->ref_p[d][d] / box[d][d]));
710 tmmul(invbox, pdiff, t1);
711 /* Move the off-diagonal elements of the 'force' to one side to ensure
712 * that we obey the box constraints.
714 for (int d = 0; d < DIM; d++)
716 for (int n = 0; n < d; n++)
718 t1[d][n] += t1[n][d];
725 case PressureCouplingType::Anisotropic:
726 for (int d = 0; d < DIM; d++)
728 for (int n = 0; n <= d; n++)
730 t1[d][n] *= winv[d][n] * vol;
734 case PressureCouplingType::Isotropic:
735 /* calculate total volume acceleration */
736 atot = box[XX][XX] * box[YY][YY] * t1[ZZ][ZZ] + box[XX][XX] * t1[YY][YY] * box[ZZ][ZZ]
737 + t1[XX][XX] * box[YY][YY] * box[ZZ][ZZ];
738 arel = atot / (3 * vol);
739 /* set all RELATIVE box accelerations equal, and maintain total V
741 for (int d = 0; d < DIM; d++)
743 for (int n = 0; n <= d; n++)
745 t1[d][n] = winv[0][0] * vol * arel * box[d][n];
749 case PressureCouplingType::SemiIsotropic:
750 case PressureCouplingType::SurfaceTension:
751 /* Note the correction to pdiff above for surftens. coupling */
753 /* calculate total XY volume acceleration */
754 atot = box[XX][XX] * t1[YY][YY] + t1[XX][XX] * box[YY][YY];
755 arel = atot / (2 * box[XX][XX] * box[YY][YY]);
756 /* set RELATIVE XY box accelerations equal, and maintain total V
757 * change speed. Dont change the third box vector accelerations */
758 for (int d = 0; d < ZZ; d++)
760 for (int n = 0; n <= d; n++)
762 t1[d][n] = winv[d][n] * vol * arel * box[d][n];
765 for (int n = 0; n < DIM; n++)
767 t1[ZZ][n] *= winv[ZZ][n] * vol;
772 "Parrinello-Rahman pressure coupling type %s "
773 "not supported yet\n",
774 enumValueToString(ir->epct));
778 for (int d = 0; d < DIM; d++)
780 for (int n = 0; n <= d; n++)
782 boxv[d][n] += dt * t1[d][n];
784 /* We do NOT update the box vectors themselves here, since
785 * we need them for shifting later. It is instead done last
786 * in the update() routine.
789 /* Calculate the change relative to diagonal elements-
790 since it's perfectly ok for the off-diagonal ones to
791 be zero it doesn't make sense to check the change relative
795 change = std::fabs(dt * boxv[d][n] / box[d][d]);
797 if (change > maxchange)
804 if (maxchange > 0.01 && fplog)
808 "\nStep %s Warning: Pressure scaling more than 1%%. "
809 "This may mean your system\n is not yet equilibrated. "
810 "Use of Parrinello-Rahman pressure coupling during\n"
811 "equilibration can lead to simulation instability, "
812 "and is discouraged.\n",
813 gmx_step_str(step, buf));
817 preserve_box_shape(ir, box_rel, boxv);
819 mtmul(boxv, box, t1); /* t1=boxv * b' */
820 mmul(invbox, t1, t2);
821 mtmul(t2, invbox, M);
823 /* Determine the scaling matrix mu for the coordinates */
824 for (int d = 0; d < DIM; d++)
826 for (int n = 0; n <= d; n++)
828 t1[d][n] = box[d][n] + dt * boxv[d][n];
831 preserve_box_shape(ir, box_rel, t1);
832 /* t1 is the box at t+dt, determine mu as the relative change */
833 mmul_ur0(invbox, t1, mu);
836 //! Return compressibility factor for entry (i,j) of Berendsen / C-rescale scaling matrix
837 static inline real compressibilityFactor(int i, int j, const t_inputrec* ir, real dt)
839 return ir->compress[i][j] * dt / ir->tau_p;
842 //! Details of Berendsen / C-rescale scaling matrix calculation
843 template<PressureCoupling pressureCouplingType>
844 static void calculateScalingMatrixImplDetail(const t_inputrec* ir,
849 real scalar_pressure,
853 //! Calculate Berendsen / C-rescale scaling matrix
854 template<PressureCoupling pressureCouplingType>
855 static void calculateScalingMatrixImpl(const t_inputrec* ir,
862 real scalar_pressure = 0;
863 real xy_pressure = 0;
864 for (int d = 0; d < DIM; d++)
866 scalar_pressure += pres[d][d] / DIM;
869 xy_pressure += pres[d][d] / (DIM - 1);
873 calculateScalingMatrixImplDetail<pressureCouplingType>(
874 ir, mu, dt, pres, box, scalar_pressure, xy_pressure, step);
878 void calculateScalingMatrixImplDetail<PressureCoupling::Berendsen>(const t_inputrec* ir,
883 real scalar_pressure,
885 int64_t gmx_unused step)
890 case PressureCouplingType::Isotropic:
891 for (int d = 0; d < DIM; d++)
893 mu[d][d] = 1.0 - compressibilityFactor(d, d, ir, dt) * (ir->ref_p[d][d] - scalar_pressure) / DIM;
896 case PressureCouplingType::SemiIsotropic:
897 for (int d = 0; d < ZZ; d++)
899 mu[d][d] = 1.0 - compressibilityFactor(d, d, ir, dt) * (ir->ref_p[d][d] - xy_pressure) / DIM;
902 1.0 - compressibilityFactor(ZZ, ZZ, ir, dt) * (ir->ref_p[ZZ][ZZ] - pres[ZZ][ZZ]) / DIM;
904 case PressureCouplingType::Anisotropic:
905 for (int d = 0; d < DIM; d++)
907 for (int n = 0; n < DIM; n++)
909 mu[d][n] = (d == n ? 1.0 : 0.0)
910 - compressibilityFactor(d, n, ir, dt) * (ir->ref_p[d][n] - pres[d][n]) / DIM;
914 case PressureCouplingType::SurfaceTension:
915 /* ir->ref_p[0/1] is the reference surface-tension times *
916 * the number of surfaces */
917 if (ir->compress[ZZ][ZZ] != 0.0F)
919 p_corr_z = dt / ir->tau_p * (ir->ref_p[ZZ][ZZ] - pres[ZZ][ZZ]);
923 /* when the compressibity is zero, set the pressure correction *
924 * in the z-direction to zero to get the correct surface tension */
927 mu[ZZ][ZZ] = 1.0 - ir->compress[ZZ][ZZ] * p_corr_z;
928 for (int d = 0; d < DIM - 1; d++)
931 + compressibilityFactor(d, d, ir, dt)
932 * (ir->ref_p[d][d] / (mu[ZZ][ZZ] * box[ZZ][ZZ])
933 - (pres[ZZ][ZZ] + p_corr_z - xy_pressure))
939 "Berendsen pressure coupling type %s not supported yet\n",
940 enumValueToString(ir->epct));
945 void calculateScalingMatrixImplDetail<PressureCoupling::CRescale>(const t_inputrec* ir,
950 real scalar_pressure,
954 gmx::ThreeFry2x64<64> rng(ir->ld_seed, gmx::RandomDomain::Barostat);
955 gmx::NormalDistribution<real> normalDist;
956 rng.restart(step, 0);
958 for (int d = 0; d < DIM; d++)
964 real kt = ir->opts.ref_t[0] * gmx::c_boltz;
972 case PressureCouplingType::Isotropic:
973 gauss = normalDist(rng);
974 for (int d = 0; d < DIM; d++)
976 const real factor = compressibilityFactor(d, d, ir, dt);
977 mu[d][d] = std::exp(-factor * (ir->ref_p[d][d] - scalar_pressure) / DIM
978 + std::sqrt(2.0 * kt * factor * gmx::c_presfac / vol) * gauss / DIM);
981 case PressureCouplingType::SemiIsotropic:
982 gauss = normalDist(rng);
983 gauss2 = normalDist(rng);
984 for (int d = 0; d < ZZ; d++)
986 const real factor = compressibilityFactor(d, d, ir, dt);
987 mu[d][d] = std::exp(-factor * (ir->ref_p[d][d] - xy_pressure) / DIM
988 + std::sqrt((DIM - 1) * 2.0 * kt * factor * gmx::c_presfac / vol / DIM)
989 / (DIM - 1) * gauss);
992 const real factor = compressibilityFactor(ZZ, ZZ, ir, dt);
993 mu[ZZ][ZZ] = std::exp(-factor * (ir->ref_p[ZZ][ZZ] - pres[ZZ][ZZ]) / DIM
994 + std::sqrt(2.0 * kt * factor * gmx::c_presfac / vol / DIM) * gauss2);
997 case PressureCouplingType::SurfaceTension:
998 gauss = normalDist(rng);
999 gauss2 = normalDist(rng);
1000 for (int d = 0; d < ZZ; d++)
1002 const real factor = compressibilityFactor(d, d, ir, dt);
1003 /* Notice: we here use ref_p[ZZ][ZZ] as isotropic pressure and ir->ref_p[d][d] as surface tension */
1004 mu[d][d] = std::exp(
1005 -factor * (ir->ref_p[ZZ][ZZ] - ir->ref_p[d][d] / box[ZZ][ZZ] - xy_pressure) / DIM
1006 + std::sqrt(4.0 / 3.0 * kt * factor * gmx::c_presfac / vol) / (DIM - 1) * gauss);
1009 const real factor = compressibilityFactor(ZZ, ZZ, ir, dt);
1010 mu[ZZ][ZZ] = std::exp(-factor * (ir->ref_p[ZZ][ZZ] - pres[ZZ][ZZ]) / DIM
1011 + std::sqrt(2.0 / 3.0 * kt * factor * gmx::c_presfac / vol) * gauss2);
1016 "C-rescale pressure coupling type %s not supported yet\n",
1017 enumValueToString(ir->epct));
1021 template<PressureCoupling pressureCouplingType>
1022 void pressureCouplingCalculateScalingMatrix(FILE* fplog,
1024 const t_inputrec* ir,
1028 const matrix force_vir,
1029 const matrix constraint_vir,
1031 double* baros_integral)
1033 // If the support here increases, we need to also add the template declarations
1034 // for new cases below.
1035 static_assert(pressureCouplingType == PressureCoupling::Berendsen
1036 || pressureCouplingType == PressureCoupling::CRescale,
1037 "pressureCouplingCalculateScalingMatrix is only implemented for Berendsen and "
1038 "C-rescale pressure coupling");
1040 calculateScalingMatrixImpl<pressureCouplingType>(ir, mu, dt, pres, box, step);
1042 /* To fulfill the orientation restrictions on triclinic boxes
1043 * we will set mu_yx, mu_zx and mu_zy to 0 and correct
1044 * the other elements of mu to first order.
1046 mu[YY][XX] += mu[XX][YY];
1047 mu[ZZ][XX] += mu[XX][ZZ];
1048 mu[ZZ][YY] += mu[YY][ZZ];
1053 /* Keep track of the work the barostat applies on the system.
1054 * Without constraints force_vir tells us how Epot changes when scaling.
1055 * With constraints constraint_vir gives us the constraint contribution
1056 * to both Epot and Ekin. Although we are not scaling velocities, scaling
1057 * the coordinates leads to scaling of distances involved in constraints.
1058 * This in turn changes the angular momentum (even if the constrained
1059 * distances are corrected at the next step). The kinetic component
1060 * of the constraint virial captures the angular momentum change.
1062 for (int d = 0; d < DIM; d++)
1064 for (int n = 0; n <= d; n++)
1067 2 * (mu[d][n] - (n == d ? 1 : 0)) * (force_vir[d][n] + constraint_vir[d][n]);
1073 pr_rvecs(debug, 0, "PC: pres ", pres, 3);
1074 pr_rvecs(debug, 0, "PC: mu ", mu, 3);
1077 if (mu[XX][XX] < 0.99 || mu[XX][XX] > 1.01 || mu[YY][YY] < 0.99 || mu[YY][YY] > 1.01
1078 || mu[ZZ][ZZ] < 0.99 || mu[ZZ][ZZ] > 1.01)
1083 "\nStep %s Warning: pressure scaling more than 1%%, "
1085 gmx_step_str(step, buf2),
1091 fprintf(fplog, "%s", buf);
1093 fprintf(stderr, "%s", buf);
1097 template void pressureCouplingCalculateScalingMatrix<PressureCoupling::CRescale>(FILE*,
1108 template void pressureCouplingCalculateScalingMatrix<PressureCoupling::Berendsen>(FILE*,
1119 template<PressureCoupling pressureCouplingType>
1120 void pressureCouplingScaleBoxAndCoordinates(const t_inputrec* ir,
1126 gmx::ArrayRef<gmx::RVec> x,
1127 gmx::ArrayRef<gmx::RVec> v,
1128 gmx::ArrayRef<const unsigned short> cFREEZE,
1130 const bool scaleCoordinates)
1132 // If the support here increases, we need to also add the template declarations
1133 // for new cases below.
1134 static_assert(pressureCouplingType == PressureCoupling::Berendsen
1135 || pressureCouplingType == PressureCoupling::CRescale,
1136 "pressureCouplingScaleBoxAndCoordinates is only implemented for Berendsen and "
1137 "C-rescale pressure coupling");
1139 ivec* nFreeze = ir->opts.nFreeze;
1141 if (pressureCouplingType == PressureCoupling::CRescale)
1143 gmx::invertBoxMatrix(mu, inv_mu);
1146 /* Scale the positions and the velocities */
1147 if (scaleCoordinates)
1149 const int gmx_unused numThreads = gmx_omp_nthreads_get(ModuleMultiThread::Update);
1150 #pragma omp parallel for num_threads(numThreads) schedule(static)
1151 for (int n = start; n < start + nr_atoms; n++)
1153 // Trivial OpenMP region that does not throw
1155 if (!cFREEZE.empty())
1160 if (!nFreeze[g][XX])
1162 x[n][XX] = mu[XX][XX] * x[n][XX] + mu[YY][XX] * x[n][YY] + mu[ZZ][XX] * x[n][ZZ];
1163 if (pressureCouplingType == PressureCoupling::CRescale)
1165 v[n][XX] = inv_mu[XX][XX] * v[n][XX] + inv_mu[YY][XX] * v[n][YY]
1166 + inv_mu[ZZ][XX] * v[n][ZZ];
1169 if (!nFreeze[g][YY])
1171 x[n][YY] = mu[YY][YY] * x[n][YY] + mu[ZZ][YY] * x[n][ZZ];
1172 if (pressureCouplingType == PressureCoupling::CRescale)
1174 v[n][YY] = inv_mu[YY][YY] * v[n][YY] + inv_mu[ZZ][YY] * v[n][ZZ];
1177 if (!nFreeze[g][ZZ])
1179 x[n][ZZ] = mu[ZZ][ZZ] * x[n][ZZ];
1180 if (pressureCouplingType == PressureCoupling::CRescale)
1182 v[n][ZZ] = inv_mu[ZZ][ZZ] * v[n][ZZ];
1187 /* compute final boxlengths */
1188 for (int d = 0; d < DIM; d++)
1190 box[d][XX] = mu[XX][XX] * box[d][XX] + mu[YY][XX] * box[d][YY] + mu[ZZ][XX] * box[d][ZZ];
1191 box[d][YY] = mu[YY][YY] * box[d][YY] + mu[ZZ][YY] * box[d][ZZ];
1192 box[d][ZZ] = mu[ZZ][ZZ] * box[d][ZZ];
1195 preserve_box_shape(ir, box_rel, box);
1197 /* (un)shifting should NOT be done after this,
1198 * since the box vectors might have changed
1200 inc_nrnb(nrnb, eNR_PCOUPL, nr_atoms);
1204 pressureCouplingScaleBoxAndCoordinates<PressureCoupling::Berendsen>(const t_inputrec*,
1210 gmx::ArrayRef<gmx::RVec>,
1211 gmx::ArrayRef<gmx::RVec>,
1212 gmx::ArrayRef<const unsigned short>,
1218 pressureCouplingScaleBoxAndCoordinates<PressureCoupling::CRescale>(const t_inputrec*,
1224 gmx::ArrayRef<gmx::RVec>,
1225 gmx::ArrayRef<gmx::RVec>,
1226 gmx::ArrayRef<const unsigned short>,
1230 void berendsen_tcoupl(const t_inputrec* ir, gmx_ekindata_t* ekind, real dt, std::vector<double>& therm_integral)
1232 const t_grpopts* opts = &ir->opts;
1234 for (int i = 0; (i < opts->ngtc); i++)
1238 if (ir->eI == IntegrationAlgorithm::VV)
1240 Ek = trace(ekind->tcstat[i].ekinf);
1241 T = ekind->tcstat[i].T;
1245 Ek = trace(ekind->tcstat[i].ekinh);
1246 T = ekind->tcstat[i].Th;
1249 if ((opts->tau_t[i] > 0) && (T > 0.0))
1251 real reft = std::max<real>(0, opts->ref_t[i]);
1252 real lll = std::sqrt(1.0 + (dt / opts->tau_t[i]) * (reft / T - 1.0));
1253 ekind->tcstat[i].lambda = std::max<real>(std::min<real>(lll, 1.25), 0.8);
1257 ekind->tcstat[i].lambda = 1.0;
1260 /* Keep track of the amount of energy we are adding to the system */
1261 therm_integral[i] -= (gmx::square(ekind->tcstat[i].lambda) - 1) * Ek;
1265 fprintf(debug, "TC: group %d: T: %g, Lambda: %g\n", i, T, ekind->tcstat[i].lambda);
1270 void andersen_tcoupl(const t_inputrec* ir,
1272 const t_commrec* cr,
1274 gmx::ArrayRef<const unsigned short> cTC,
1275 gmx::ArrayRef<const real> invMass,
1276 gmx::ArrayRef<gmx::RVec> v,
1278 const std::vector<bool>& randomize,
1279 gmx::ArrayRef<const real> boltzfac)
1281 const int* gatindex = (haveDDAtomOrdering(*cr) ? cr->dd->globalAtomIndices.data() : nullptr);
1284 gmx::ThreeFry2x64<0> rng(ir->andersen_seed, gmx::RandomDomain::Thermostat);
1285 gmx::UniformRealDistribution<real> uniformDist;
1286 gmx::TabulatedNormalDistribution<real, 14> normalDist;
1288 /* randomize the velocities of the selected particles */
1290 for (i = 0; i < homenr; i++) /* now loop over the list of atoms */
1292 int ng = gatindex ? gatindex[i] : i;
1295 rng.restart(step, ng);
1299 gc = cTC[i]; /* assign the atom to a temperature group if there are more than one */
1303 if (ir->etc == TemperatureCoupling::AndersenMassive)
1305 /* Randomize particle always */
1310 /* Randomize particle probabilistically */
1311 uniformDist.reset();
1312 bRandomize = uniformDist(rng) < rate;
1319 scal = std::sqrt(boltzfac[gc] * invMass[i]);
1323 for (d = 0; d < DIM; d++)
1325 v[i][d] = scal * normalDist(rng);
1333 void nosehoover_tcoupl(const t_grpopts* opts,
1334 const gmx_ekindata_t* ekind,
1336 gmx::ArrayRef<double> xi,
1337 gmx::ArrayRef<double> vxi,
1338 const t_extmass* MassQ)
1343 /* note that this routine does not include Nose-hoover chains yet. Should be easy to add. */
1345 for (i = 0; (i < opts->ngtc); i++)
1347 reft = std::max<real>(0, opts->ref_t[i]);
1349 vxi[i] += dt * MassQ->Qinv[i] * (ekind->tcstat[i].Th - reft);
1350 xi[i] += dt * (oldvxi + vxi[i]) * 0.5;
1354 void trotter_update(const t_inputrec* ir,
1356 gmx_ekindata_t* ekind,
1357 const gmx_enerdata_t* enerd,
1361 gmx::ArrayRef<const unsigned short> cTC,
1362 gmx::ArrayRef<const real> invMass,
1363 const t_extmass* MassQ,
1364 gmx::ArrayRef<std::vector<int>> trotter_seqlist,
1365 TrotterSequence trotter_seqno)
1368 int n, i, d, ngtc, gc = 0, t;
1369 t_grp_tcstat* tcstat;
1370 const t_grpopts* opts;
1373 double * scalefac, dtc;
1374 rvec sumv = { 0, 0, 0 };
1377 if (trotter_seqno <= TrotterSequence::Two)
1379 step_eff = step - 1; /* the velocity verlet calls are actually out of order -- the first
1380 half step is actually the last half step from the previous step.
1381 Thus the first half step actually corresponds to the n-1 step*/
1388 bCouple = (ir->nsttcouple == 1 || do_per_step(step_eff + ir->nsttcouple, ir->nsttcouple));
1390 const gmx::ArrayRef<const int> trotter_seq = trotter_seqlist[static_cast<int>(trotter_seqno)];
1392 if ((trotter_seq[0] == etrtSKIPALL) || (!bCouple))
1396 dtc = ir->nsttcouple * ir->delta_t; /* This is OK for NPT, because nsttcouple == nstpcouple is enforcesd */
1397 opts = &(ir->opts); /* just for ease of referencing */
1400 snew(scalefac, opts->ngtc);
1401 for (i = 0; i < ngtc; i++)
1405 /* execute the series of trotter updates specified in the trotterpart array */
1407 for (i = 0; i < NTROTTERPARTS; i++)
1409 /* allow for doubled intgrators by doubling dt instead of making 2 calls */
1410 if ((trotter_seq[i] == etrtBAROV2) || (trotter_seq[i] == etrtBARONHC2)
1411 || (trotter_seq[i] == etrtNHC2))
1420 auto v = makeArrayRef(state->v);
1421 switch (trotter_seq[i])
1425 boxv_trotter(ir, &(state->veta), dt, state->box, ekind, vir, enerd->term[F_PDISPCORR], MassQ);
1433 state->nhpres_xi.data(),
1434 state->nhpres_vxi.data(),
1446 state->nosehoover_xi.data(),
1447 state->nosehoover_vxi.data(),
1451 (ir->eI == IntegrationAlgorithm::VV));
1452 /* need to rescale the kinetic energies and velocities here. Could
1453 scale the velocities later, but we need them scaled in order to
1454 produce the correct outputs, so we'll scale them here. */
1456 for (t = 0; t < ngtc; t++)
1458 tcstat = &ekind->tcstat[t];
1459 tcstat->vscale_nhc = scalefac[t];
1460 tcstat->ekinscaleh_nhc *= (scalefac[t] * scalefac[t]);
1461 tcstat->ekinscalef_nhc *= (scalefac[t] * scalefac[t]);
1463 /* now that we've scaled the groupwise velocities, we can add them up to get the total */
1464 /* but do we actually need the total? */
1466 /* modify the velocities as well */
1467 for (n = 0; n < homenr; n++)
1469 if (!cTC.empty()) /* does this conditional need to be here? is this always true?*/
1473 for (d = 0; d < DIM; d++)
1475 v[n][d] *= scalefac[gc];
1480 for (d = 0; d < DIM; d++)
1482 sumv[d] += (v[n][d]) / invMass[n];
1490 /* check for conserved momentum -- worth looking at this again eventually, but not working right now.*/
1495 extern void init_npt_masses(const t_inputrec* ir, t_state* state, t_extmass* MassQ, bool bInit)
1497 int n, i, j, d, ngtc, nh;
1498 const t_grpopts* opts;
1499 real reft, kT, ndj, nd;
1501 opts = &(ir->opts); /* just for ease of referencing */
1502 ngtc = ir->opts.ngtc;
1503 nh = state->nhchainlength;
1505 if (ir->eI == IntegrationAlgorithm::MD)
1509 MassQ->Qinv.resize(ngtc);
1511 for (i = 0; (i < ngtc); i++)
1513 if ((opts->tau_t[i] > 0) && (opts->ref_t[i] > 0))
1515 MassQ->Qinv[i] = 1.0 / (gmx::square(opts->tau_t[i] / M_2PI) * opts->ref_t[i]);
1519 MassQ->Qinv[i] = 0.0;
1523 else if (EI_VV(ir->eI))
1525 /* Set pressure variables */
1529 if (state->vol0 == 0)
1531 state->vol0 = det(state->box);
1532 /* because we start by defining a fixed
1533 compressibility, we need the volume at this
1534 compressibility to solve the problem. */
1538 /* units are nm^3 * ns^2 / (nm^3 * bar / kJ/mol) = kJ/mol */
1539 /* Consider evaluating eventually if this the right mass to use. All are correct, some might be more stable */
1540 MassQ->Winv = (gmx::c_presfac * trace(ir->compress) * gmx::c_boltz * opts->ref_t[0])
1541 / (DIM * state->vol0 * gmx::square(ir->tau_p / M_2PI));
1542 /* An alternate mass definition, from Tuckerman et al. */
1543 /* MassQ->Winv = 1.0/(gmx::square(ir->tau_p/M_2PI)*(opts->nrdf[0]+DIM)*c_boltz*opts->ref_t[0]); */
1544 for (d = 0; d < DIM; d++)
1546 for (n = 0; n < DIM; n++)
1548 MassQ->Winvm[d][n] = gmx::c_presfac * ir->compress[d][n]
1549 / (state->vol0 * gmx::square(ir->tau_p / M_2PI));
1550 /* not clear this is correct yet for the anisotropic case. Will need to reevaluate
1551 before using MTTK for anisotropic states.*/
1554 /* Allocate space for thermostat variables */
1557 MassQ->Qinv.resize(ngtc * nh);
1560 /* now, set temperature variables */
1561 for (i = 0; i < ngtc; i++)
1563 if (opts->tau_t[i] > 0 && opts->ref_t[i] > 0 && opts->nrdf[i] > 0)
1565 reft = std::max<real>(0, opts->ref_t[i]);
1567 kT = gmx::c_boltz * reft;
1568 for (j = 0; j < nh; j++)
1578 MassQ->Qinv[i * nh + j] = 1.0 / (gmx::square(opts->tau_t[i] / M_2PI) * ndj * kT);
1583 for (j = 0; j < nh; j++)
1585 MassQ->Qinv[i * nh + j] = 0.0;
1592 gmx::EnumerationArray<TrotterSequence, std::vector<int>>
1593 init_npt_vars(const t_inputrec* ir, t_state* state, t_extmass* MassQ, bool bTrotter)
1595 int i, j, nnhpres, nh;
1596 const t_grpopts* opts;
1597 real bmass, qmass, reft, kT;
1599 opts = &(ir->opts); /* just for ease of referencing */
1600 nnhpres = state->nnhpres;
1601 nh = state->nhchainlength;
1603 if (EI_VV(ir->eI) && (ir->epc == PressureCoupling::Mttk) && (ir->etc != TemperatureCoupling::NoseHoover))
1605 gmx_fatal(FARGS, "Cannot do MTTK pressure coupling without Nose-Hoover temperature control");
1608 init_npt_masses(ir, state, MassQ, TRUE);
1610 /* first, initialize clear all the trotter calls */
1611 gmx::EnumerationArray<TrotterSequence, std::vector<int>> trotter_seq;
1612 for (i = 0; i < static_cast<int>(TrotterSequence::Count); i++)
1614 trotter_seq[i].resize(NTROTTERPARTS, etrtNONE);
1615 trotter_seq[i][0] = etrtSKIPALL;
1620 /* no trotter calls, so we never use the values in the array.
1621 * We access them (so we need to define them, but ignore
1627 /* compute the kinetic energy by using the half step velocities or
1628 * the kinetic energies, depending on the order of the trotter calls */
1630 if (ir->eI == IntegrationAlgorithm::VV)
1632 if (inputrecNptTrotter(ir))
1634 /* This is the complicated version - there are 4 possible calls, depending on ordering.
1635 We start with the initial one. */
1636 /* first, a round that estimates veta. */
1637 trotter_seq[0][0] = etrtBAROV;
1639 /* trotter_seq[1] is etrtNHC for 1/2 step velocities - leave zero */
1641 /* The first half trotter update */
1642 trotter_seq[2][0] = etrtBAROV;
1643 trotter_seq[2][1] = etrtNHC;
1644 trotter_seq[2][2] = etrtBARONHC;
1646 /* The second half trotter update */
1647 trotter_seq[3][0] = etrtBARONHC;
1648 trotter_seq[3][1] = etrtNHC;
1649 trotter_seq[3][2] = etrtBAROV;
1651 /* trotter_seq[4] is etrtNHC for second 1/2 step velocities - leave zero */
1653 else if (inputrecNvtTrotter(ir))
1655 /* This is the easy version - there are only two calls, both the same.
1656 Otherwise, even easier -- no calls */
1657 trotter_seq[2][0] = etrtNHC;
1658 trotter_seq[3][0] = etrtNHC;
1660 else if (inputrecNphTrotter(ir))
1662 /* This is the complicated version - there are 4 possible calls, depending on ordering.
1663 We start with the initial one. */
1664 /* first, a round that estimates veta. */
1665 trotter_seq[0][0] = etrtBAROV;
1667 /* trotter_seq[1] is etrtNHC for 1/2 step velocities - leave zero */
1669 /* The first half trotter update */
1670 trotter_seq[2][0] = etrtBAROV;
1671 trotter_seq[2][1] = etrtBARONHC;
1673 /* The second half trotter update */
1674 trotter_seq[3][0] = etrtBARONHC;
1675 trotter_seq[3][1] = etrtBAROV;
1677 /* trotter_seq[4] is etrtNHC for second 1/2 step velocities - leave zero */
1680 else if (ir->eI == IntegrationAlgorithm::VVAK)
1682 if (inputrecNptTrotter(ir))
1684 /* This is the complicated version - there are 4 possible calls, depending on ordering.
1685 We start with the initial one. */
1686 /* first, a round that estimates veta. */
1687 trotter_seq[0][0] = etrtBAROV;
1689 /* The first half trotter update, part 1 -- double update, because it commutes */
1690 trotter_seq[1][0] = etrtNHC;
1692 /* The first half trotter update, part 2 */
1693 trotter_seq[2][0] = etrtBAROV;
1694 trotter_seq[2][1] = etrtBARONHC;
1696 /* The second half trotter update, part 1 */
1697 trotter_seq[3][0] = etrtBARONHC;
1698 trotter_seq[3][1] = etrtBAROV;
1700 /* The second half trotter update */
1701 trotter_seq[4][0] = etrtNHC;
1703 else if (inputrecNvtTrotter(ir))
1705 /* This is the easy version - there is only one call, both the same.
1706 Otherwise, even easier -- no calls */
1707 trotter_seq[1][0] = etrtNHC;
1708 trotter_seq[4][0] = etrtNHC;
1710 else if (inputrecNphTrotter(ir))
1712 /* This is the complicated version - there are 4 possible calls, depending on ordering.
1713 We start with the initial one. */
1714 /* first, a round that estimates veta. */
1715 trotter_seq[0][0] = etrtBAROV;
1717 /* The first half trotter update, part 1 -- leave zero */
1718 trotter_seq[1][0] = etrtNHC;
1720 /* The first half trotter update, part 2 */
1721 trotter_seq[2][0] = etrtBAROV;
1722 trotter_seq[2][1] = etrtBARONHC;
1724 /* The second half trotter update, part 1 */
1725 trotter_seq[3][0] = etrtBARONHC;
1726 trotter_seq[3][1] = etrtBAROV;
1728 /* The second half trotter update -- blank for now */
1734 case PressureCouplingType::Isotropic:
1735 default: bmass = DIM * DIM; /* recommended mass parameters for isotropic barostat */
1738 MassQ->QPinv.resize(nnhpres * opts->nhchainlength);
1740 /* barostat temperature */
1741 if ((ir->tau_p > 0) && (opts->ref_t[0] > 0))
1743 reft = std::max<real>(0, opts->ref_t[0]);
1744 kT = gmx::c_boltz * reft;
1745 for (i = 0; i < nnhpres; i++)
1747 for (j = 0; j < nh; j++)
1757 MassQ->QPinv[i * opts->nhchainlength + j] =
1758 1.0 / (gmx::square(opts->tau_t[0] / M_2PI) * qmass * kT);
1764 for (i = 0; i < nnhpres; i++)
1766 for (j = 0; j < nh; j++)
1768 MassQ->QPinv[i * nh + j] = 0.0;
1775 static real energyNoseHoover(const t_inputrec* ir, const t_state* state, const t_extmass* MassQ)
1779 int nh = state->nhchainlength;
1781 for (int i = 0; i < ir->opts.ngtc; i++)
1783 const double* ixi = &state->nosehoover_xi[i * nh];
1784 const double* ivxi = &state->nosehoover_vxi[i * nh];
1785 const double* iQinv = &(MassQ->Qinv[i * nh]);
1787 real nd = ir->opts.nrdf[i];
1788 real reft = std::max<real>(ir->opts.ref_t[i], 0);
1789 real kT = gmx::c_boltz * reft;
1793 if (inputrecNvtTrotter(ir) || inputrecNptTrotter(ir))
1795 /* contribution from the thermal momenta of the NH chain */
1796 for (int j = 0; j < nh; j++)
1800 energy += 0.5 * gmx::square(ivxi[j]) / iQinv[j];
1801 /* contribution from the thermal variable of the NH chain */
1811 energy += ndj * ixi[j] * kT;
1815 else /* Other non Trotter temperature NH control -- no chains yet. */
1817 energy += 0.5 * gmx::c_boltz * nd * gmx::square(ivxi[0]) / iQinv[0];
1818 energy += nd * ixi[0] * kT;
1826 /* Returns the energy from the barostat thermostat chain */
1827 static real energyPressureMTTK(const t_inputrec* ir, const t_state* state, const t_extmass* MassQ)
1831 int nh = state->nhchainlength;
1833 for (int i = 0; i < state->nnhpres; i++)
1835 /* note -- assumes only one degree of freedom that is thermostatted in barostat */
1836 real reft = std::max<real>(ir->opts.ref_t[0], 0.0); /* using 'System' temperature */
1837 real kT = gmx::c_boltz * reft;
1839 for (int j = 0; j < nh; j++)
1841 double iQinv = MassQ->QPinv[i * nh + j];
1844 energy += 0.5 * gmx::square(state->nhpres_vxi[i * nh + j]) / iQinv;
1845 /* contribution from the thermal variable of the NH chain */
1846 energy += state->nhpres_xi[i * nh + j] * kT;
1851 "P-T-group: %10d Chain %4d ThermV: %15.8f ThermX: %15.8f",
1854 state->nhpres_vxi[i * nh + j],
1855 state->nhpres_xi[i * nh + j]);
1863 /* Returns the energy accumulated by the V-rescale or Berendsen thermostat */
1864 static real energyVrescale(const t_inputrec* ir, const t_state* state)
1867 for (int i = 0; i < ir->opts.ngtc; i++)
1869 energy += state->therm_integral[i];
1875 real NPT_energy(const t_inputrec* ir, const t_state* state, const t_extmass* MassQ)
1879 if (ir->epc != PressureCoupling::No)
1881 /* Compute the contribution of the pressure to the conserved quantity*/
1883 real vol = det(state->box);
1887 case PressureCoupling::ParrinelloRahman:
1889 /* contribution from the pressure momenta */
1891 calcParrinelloRahmanInvMass(ir, state->box, invMass);
1892 for (int d = 0; d < DIM; d++)
1894 for (int n = 0; n <= d; n++)
1896 if (invMass[d][n] > 0)
1898 energyNPT += 0.5 * gmx::square(state->boxv[d][n])
1899 / (invMass[d][n] * gmx::c_presfac);
1904 /* Contribution from the PV term.
1905 * Not that with non-zero off-diagonal reference pressures,
1906 * i.e. applied shear stresses, there are additional terms.
1907 * We don't support this here, since that requires keeping
1908 * track of unwrapped box diagonal elements. This case is
1909 * excluded in integratorHasConservedEnergyQuantity().
1911 energyNPT += vol * trace(ir->ref_p) / (DIM * gmx::c_presfac);
1914 case PressureCoupling::Mttk:
1915 /* contribution from the pressure momenta */
1916 energyNPT += 0.5 * gmx::square(state->veta) / MassQ->Winv;
1918 /* contribution from the PV term */
1919 energyNPT += vol * trace(ir->ref_p) / (DIM * gmx::c_presfac);
1921 if (ir->epc == PressureCoupling::Mttk)
1923 /* contribution from the MTTK chain */
1924 energyNPT += energyPressureMTTK(ir, state, MassQ);
1927 case PressureCoupling::Berendsen:
1928 case PressureCoupling::CRescale: energyNPT += state->baros_integral; break;
1932 "Conserved energy quantity for pressure coupling is not handled. A case "
1933 "should be added with either the conserved quantity added or nothing added "
1934 "and an exclusion added to integratorHasConservedEnergyQuantity().");
1940 case TemperatureCoupling::No: break;
1941 case TemperatureCoupling::VRescale:
1942 case TemperatureCoupling::Berendsen: energyNPT += energyVrescale(ir, state); break;
1943 case TemperatureCoupling::NoseHoover:
1944 energyNPT += energyNoseHoover(ir, state, MassQ);
1946 case TemperatureCoupling::Andersen:
1947 case TemperatureCoupling::AndersenMassive:
1948 // Not supported, excluded in integratorHasConservedEnergyQuantity()
1953 "Conserved energy quantity for temperature coupling is not handled. A case "
1954 "should be added with either the conserved quantity added or nothing added and "
1955 "an exclusion added to integratorHasConservedEnergyQuantity().");
1962 static real vrescale_sumnoises(real nn, gmx::ThreeFry2x64<>* rng, gmx::NormalDistribution<real>* normalDist)
1965 * Returns the sum of nn independent gaussian noises squared
1966 * (i.e. equivalent to summing the square of the return values
1967 * of nn calls to a normal distribution).
1969 const real ndeg_tol = 0.0001;
1971 gmx::GammaDistribution<real> gammaDist(0.5 * nn, 1.0);
1973 if (nn < 2 + ndeg_tol)
1978 nn_int = gmx::roundToInt(nn);
1980 if (nn - nn_int < -ndeg_tol || nn - nn_int > ndeg_tol)
1983 "The v-rescale thermostat was called with a group with #DOF=%f, but for "
1984 "#DOF<3 only integer #DOF are supported",
1989 for (i = 0; i < nn_int; i++)
1991 gauss = (*normalDist)(*rng);
1997 /* Use a gamma distribution for any real nn > 2 */
1998 r = 2.0 * gammaDist(*rng);
2004 real vrescale_resamplekin(real kk, real sigma, real ndeg, real taut, int64_t step, int64_t seed)
2007 * Generates a new value for the kinetic energy,
2008 * according to Bussi et al JCP (2007), Eq. (A7)
2009 * kk: present value of the kinetic energy of the atoms to be thermalized (in arbitrary units)
2010 * sigma: target average value of the kinetic energy (ndeg k_b T/2) (in the same units as kk)
2011 * ndeg: number of degrees of freedom of the atoms to be thermalized
2012 * taut: relaxation time of the thermostat, in units of 'how often this routine is called'
2014 real factor, rr, ekin_new;
2015 gmx::ThreeFry2x64<64> rng(seed, gmx::RandomDomain::Thermostat);
2016 gmx::NormalDistribution<real> normalDist;
2020 factor = exp(-1.0 / taut);
2027 rng.restart(step, 0);
2029 rr = normalDist(rng);
2033 * (sigma * (vrescale_sumnoises(ndeg - 1, &rng, &normalDist) + rr * rr) / ndeg - kk)
2034 + 2.0 * rr * std::sqrt(kk * sigma / ndeg * (1.0 - factor) * factor);
2039 void vrescale_tcoupl(const t_inputrec* ir, int64_t step, gmx_ekindata_t* ekind, real dt, gmx::ArrayRef<double> therm_integral)
2041 const t_grpopts* opts;
2043 real Ek, Ek_ref1, Ek_ref, Ek_new;
2047 for (i = 0; (i < opts->ngtc); i++)
2049 if (ir->eI == IntegrationAlgorithm::VV)
2051 Ek = trace(ekind->tcstat[i].ekinf);
2055 Ek = trace(ekind->tcstat[i].ekinh);
2058 if (opts->tau_t[i] >= 0 && opts->nrdf[i] > 0 && Ek > 0)
2060 Ek_ref1 = 0.5 * opts->ref_t[i] * gmx::c_boltz;
2061 Ek_ref = Ek_ref1 * opts->nrdf[i];
2063 Ek_new = vrescale_resamplekin(Ek, Ek_ref, opts->nrdf[i], opts->tau_t[i] / dt, step, ir->ld_seed);
2065 /* Analytically Ek_new>=0, but we check for rounding errors */
2068 ekind->tcstat[i].lambda = 0.0;
2072 ekind->tcstat[i].lambda = std::sqrt(Ek_new / Ek);
2075 therm_integral[i] -= Ek_new - Ek;
2080 "TC: group %d: Ekr %g, Ek %g, Ek_new %g, Lambda: %g\n",
2085 ekind->tcstat[i].lambda);
2090 ekind->tcstat[i].lambda = 1.0;
2095 void rescale_velocities(const gmx_ekindata_t* ekind,
2096 gmx::ArrayRef<const unsigned short> cTC,
2099 gmx::ArrayRef<gmx::RVec> v)
2101 gmx::ArrayRef<const t_grp_tcstat> tcstat = ekind->tcstat;
2103 for (int n = start; n < end; n++)
2110 const real lg = tcstat[gt].lambda;
2111 for (int d = 0; d < DIM; d++)
2118 //! Check whether we're doing simulated annealing
2119 bool doSimulatedAnnealing(const t_inputrec* ir)
2121 for (int i = 0; i < ir->opts.ngtc; i++)
2123 /* set bSimAnn if any group is being annealed */
2124 if (ir->opts.annealing[i] != SimulatedAnnealing::No)
2132 // TODO If we keep simulated annealing, make a proper module that
2133 // does not rely on changing inputrec.
2134 bool initSimulatedAnnealing(t_inputrec* ir, gmx::Update* upd)
2136 bool doSimAnnealing = doSimulatedAnnealing(ir);
2139 update_annealing_target_temp(ir, ir->init_t, upd);
2141 return doSimAnnealing;
2144 real computeAnnealingTargetTemperature(const t_inputrec& inputrec, int temperatureGroup, real time)
2146 GMX_RELEASE_ASSERT(temperatureGroup >= 0 && temperatureGroup < inputrec.opts.ngtc,
2147 "Invalid temperature group.");
2148 if (inputrec.opts.annealing[temperatureGroup] == SimulatedAnnealing::No)
2150 // No change of temperature, return current reference temperature
2151 return inputrec.opts.ref_t[temperatureGroup];
2154 inputrec.opts.annealing[temperatureGroup] == SimulatedAnnealing::Single
2155 || inputrec.opts.annealing[temperatureGroup] == SimulatedAnnealing::Periodic,
2156 gmx::formatString("Unknown simulated annealing algorithm for temperature group %d", temperatureGroup)
2159 const auto npoints = inputrec.opts.anneal_npoints[temperatureGroup];
2160 if (inputrec.opts.annealing[temperatureGroup] == SimulatedAnnealing::Periodic)
2162 /* calculate time modulo the period */
2163 const auto pert = inputrec.opts.anneal_time[temperatureGroup][npoints - 1];
2164 const auto n = static_cast<int>(time / pert);
2165 thist = time - n * pert; /* modulo time */
2166 /* Make sure rounding didn't get us outside the interval */
2167 if (std::fabs(thist - pert) < GMX_REAL_EPS * 100)
2172 else if (inputrec.opts.annealing[temperatureGroup] == SimulatedAnnealing::Single)
2176 /* We are doing annealing for this group if we got here,
2177 * and we have the (relative) time as thist.
2178 * calculate target temp */
2180 while ((j < npoints - 1) && (thist > (inputrec.opts.anneal_time[temperatureGroup][j + 1])))
2184 if (j < npoints - 1)
2186 /* Found our position between points j and j+1.
2187 * Interpolate: x is the amount from j+1, (1-x) from point j
2188 * First treat possible jumps in temperature as a special case.
2190 if ((inputrec.opts.anneal_time[temperatureGroup][j + 1]
2191 - inputrec.opts.anneal_time[temperatureGroup][j])
2192 < GMX_REAL_EPS * 100)
2194 return inputrec.opts.anneal_temp[temperatureGroup][j + 1];
2198 const real x = ((thist - inputrec.opts.anneal_time[temperatureGroup][j])
2199 / (inputrec.opts.anneal_time[temperatureGroup][j + 1]
2200 - inputrec.opts.anneal_time[temperatureGroup][j]));
2201 return x * inputrec.opts.anneal_temp[temperatureGroup][j + 1]
2202 + (1 - x) * inputrec.opts.anneal_temp[temperatureGroup][j];
2207 return inputrec.opts.anneal_temp[temperatureGroup][npoints - 1];
2211 /* set target temperatures if we are annealing */
2212 void update_annealing_target_temp(t_inputrec* ir, real t, gmx::Update* upd)
2214 for (int temperatureGroup = 0; temperatureGroup < ir->opts.ngtc; temperatureGroup++)
2216 ir->opts.ref_t[temperatureGroup] = computeAnnealingTargetTemperature(*ir, temperatureGroup, t);
2219 upd->update_temperature_constants(*ir);
2222 void pleaseCiteCouplingAlgorithms(FILE* fplog, const t_inputrec& ir)
2224 if (EI_DYNAMICS(ir.eI))
2226 if (ir.etc == TemperatureCoupling::Berendsen)
2228 please_cite(fplog, "Berendsen84a");
2230 if (ir.etc == TemperatureCoupling::VRescale)
2232 please_cite(fplog, "Bussi2007a");
2234 if (ir.epc == PressureCoupling::CRescale)
2236 please_cite(fplog, "Bernetti2020");
2238 // TODO this is actually an integrator, not a coupling algorithm
2239 if (ir.eI == IntegrationAlgorithm::SD1)
2241 please_cite(fplog, "Goga2012");