22cb5fa1f7927db443a5123a3f2d980a86b387c6
[alexxy/gromacs.git] / src / gromacs / mdlib / tgroup.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team.
6  * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
7  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8  * and including many others, as listed in the AUTHORS file in the
9  * top-level source directory and at http://www.gromacs.org.
10  *
11  * GROMACS is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation; either version 2.1
14  * of the License, or (at your option) any later version.
15  *
16  * GROMACS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with GROMACS; if not, see
23  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25  *
26  * If you want to redistribute modifications to GROMACS, please
27  * consider that scientific software is very special. Version
28  * control is crucial - bugs must be traceable. We will be happy to
29  * consider code for inclusion in the official distribution, but
30  * derived work must not be called official GROMACS. Details are found
31  * in the README & COPYING files - if they are missing, get the
32  * official version at http://www.gromacs.org.
33  *
34  * To help us fund GROMACS development, we humbly ask that you cite
35  * the research papers on the package. Check out http://www.gromacs.org.
36  */
37 /* This file is completely threadsafe - keep it that way! */
38 #include "gmxpre.h"
39
40 #include "tgroup.h"
41
42 #include <cmath>
43
44 #include "gromacs/gmxlib/network.h"
45 #include "gromacs/math/vec.h"
46 #include "gromacs/mdlib/gmx_omp_nthreads.h"
47 #include "gromacs/mdlib/rbin.h"
48 #include "gromacs/mdlib/update.h"
49 #include "gromacs/mdtypes/group.h"
50 #include "gromacs/mdtypes/inputrec.h"
51 #include "gromacs/mdtypes/mdatom.h"
52 #include "gromacs/topology/mtop_util.h"
53 #include "gromacs/topology/topology.h"
54 #include "gromacs/utility/exceptions.h"
55 #include "gromacs/utility/fatalerror.h"
56 #include "gromacs/utility/futil.h"
57 #include "gromacs/utility/smalloc.h"
58
59 static void init_grpstat(const gmx_mtop_t* mtop, int ngacc, t_grp_acc gstat[])
60 {
61     if (ngacc > 0)
62     {
63         const SimulationGroups& groups = mtop->groups;
64         for (const AtomProxy atomP : AtomRange(*mtop))
65         {
66             const t_atom& local = atomP.atom();
67             int           i     = atomP.globalAtomNumber();
68             int           grp   = getGroupType(groups, SimulationAtomGroupType::Acceleration, i);
69             if ((grp < 0) && (grp >= ngacc))
70             {
71                 gmx_incons("Input for acceleration groups wrong");
72             }
73             gstat[grp].nat++;
74             /* This will not work for integrator BD */
75             gstat[grp].mA += local.m;
76             gstat[grp].mB += local.mB;
77         }
78     }
79 }
80
81 void init_ekindata(FILE gmx_unused*  log,
82                    const gmx_mtop_t* mtop,
83                    const t_grpopts*  opts,
84                    gmx_ekindata_t*   ekind,
85                    real              cos_accel)
86 {
87     int i;
88
89     /* bNEMD tells if we should remove remove the COM velocity
90      * from the velocities during velocity scaling in T-coupling.
91      * Turn this on when we have multiple acceleration groups
92      * or one accelerated group.
93      */
94     ekind->bNEMD = (opts->ngacc > 1 || norm2(opts->acc[0]) > 0);
95
96     ekind->ngtc = opts->ngtc;
97     ekind->tcstat.resize(opts->ngtc);
98     /* Set Berendsen tcoupl lambda's to 1,
99      * so runs without Berendsen coupling are not affected.
100      */
101     for (i = 0; i < opts->ngtc; i++)
102     {
103         ekind->tcstat[i].lambda         = 1.0;
104         ekind->tcstat[i].vscale_nhc     = 1.0;
105         ekind->tcstat[i].ekinscaleh_nhc = 1.0;
106         ekind->tcstat[i].ekinscalef_nhc = 1.0;
107     }
108
109     int nthread     = gmx_omp_nthreads_get(emntUpdate);
110     ekind->nthreads = nthread;
111     snew(ekind->ekin_work_alloc, nthread);
112     snew(ekind->ekin_work, nthread);
113     snew(ekind->dekindl_work, nthread);
114 #pragma omp parallel for num_threads(nthread) schedule(static)
115     for (int thread = 0; thread < nthread; thread++)
116     {
117         try
118         {
119 #define EKIN_WORK_BUFFER_SIZE 2
120             /* Allocate 2 extra elements on both sides, so in single
121              * precision we have
122              * EKIN_WORK_BUFFER_SIZE*DIM*DIM*sizeof(real) = 72/144 bytes
123              * buffer on both sides to avoid cache pollution.
124              */
125             snew(ekind->ekin_work_alloc[thread], ekind->ngtc + 2 * EKIN_WORK_BUFFER_SIZE);
126             ekind->ekin_work[thread] = ekind->ekin_work_alloc[thread] + EKIN_WORK_BUFFER_SIZE;
127             /* Nasty hack so we can have the per-thread accumulation
128              * variable for dekindl in the same thread-local cache lines
129              * as the per-thread accumulation tensors for ekin[fh],
130              * because they are accumulated in the same loop. */
131             ekind->dekindl_work[thread] = &(ekind->ekin_work[thread][ekind->ngtc][0][0]);
132 #undef EKIN_WORK_BUFFER_SIZE
133         }
134         GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
135     }
136
137     ekind->ngacc = opts->ngacc;
138     ekind->grpstat.resize(opts->ngacc);
139     init_grpstat(mtop, opts->ngacc, ekind->grpstat.data());
140
141     ekind->cosacc.cos_accel = cos_accel;
142 }
143
144 void accumulate_u(const t_commrec* cr, const t_grpopts* opts, gmx_ekindata_t* ekind)
145 {
146     /* This routine will only be called when it's necessary */
147     t_bin* rb;
148     int    g;
149
150     rb = mk_bin();
151
152     for (g = 0; (g < opts->ngacc); g++)
153     {
154         add_binr(rb, DIM, ekind->grpstat[g].u);
155     }
156     sum_bin(rb, cr);
157
158     for (g = 0; (g < opts->ngacc); g++)
159     {
160         extract_binr(rb, DIM * g, DIM, ekind->grpstat[g].u);
161     }
162     destroy_bin(rb);
163 }
164
165 void update_ekindata(int              start,
166                      int              homenr,
167                      gmx_ekindata_t*  ekind,
168                      const t_grpopts* opts,
169                      const rvec       v[],
170                      const t_mdatoms* md,
171                      real             lambda)
172 {
173     int  d, g, n;
174     real mv;
175
176     /* calculate mean velocities at whole timestep */
177     for (g = 0; (g < opts->ngtc); g++)
178     {
179         ekind->tcstat[g].T = 0;
180     }
181
182     if (ekind->bNEMD)
183     {
184         for (g = 0; (g < opts->ngacc); g++)
185         {
186             clear_rvec(ekind->grpstat[g].u);
187         }
188
189         g = 0;
190         for (n = start; (n < start + homenr); n++)
191         {
192             if (md->cACC)
193             {
194                 g = md->cACC[n];
195             }
196             for (d = 0; (d < DIM); d++)
197             {
198                 mv = md->massT[n] * v[n][d];
199                 ekind->grpstat[g].u[d] += mv;
200             }
201         }
202
203         for (g = 0; (g < opts->ngacc); g++)
204         {
205             for (d = 0; (d < DIM); d++)
206             {
207                 ekind->grpstat[g].u[d] /=
208                         (1 - lambda) * ekind->grpstat[g].mA + lambda * ekind->grpstat[g].mB;
209             }
210         }
211     }
212 }
213
214 real sum_ekin(const t_grpopts* opts, gmx_ekindata_t* ekind, real* dekindlambda, gmx_bool bEkinAveVel, gmx_bool bScaleEkin)
215 {
216     int           i, j, m, ngtc;
217     real          T;
218     t_grp_tcstat* tcstat;
219     real          nrdf, nd, *ndf;
220
221     ngtc = opts->ngtc;
222     ndf  = opts->nrdf;
223
224     T    = 0;
225     nrdf = 0;
226
227     clear_mat(ekind->ekin);
228
229     for (i = 0; (i < ngtc); i++)
230     {
231
232         nd     = ndf[i];
233         tcstat = &ekind->tcstat[i];
234         /* Sometimes a group does not have degrees of freedom, e.g.
235          * when it consists of shells and virtual sites, then we just
236          * set the temperatue to 0 and also neglect the kinetic
237          * energy, which should be  zero anyway.
238          */
239
240         if (nd > 0)
241         {
242             if (bEkinAveVel)
243             {
244                 if (!bScaleEkin)
245                 {
246                     /* in this case, kinetic energy is from the current velocities already */
247                     msmul(tcstat->ekinf, tcstat->ekinscalef_nhc, tcstat->ekinf);
248                 }
249             }
250             else
251             {
252                 /* Calculate the full step Ekin as the average of the half steps */
253                 for (j = 0; (j < DIM); j++)
254                 {
255                     for (m = 0; (m < DIM); m++)
256                     {
257                         tcstat->ekinf[j][m] = 0.5
258                                               * (tcstat->ekinh[j][m] * tcstat->ekinscaleh_nhc
259                                                  + tcstat->ekinh_old[j][m]);
260                     }
261                 }
262             }
263             m_add(tcstat->ekinf, ekind->ekin, ekind->ekin);
264
265             tcstat->Th = calc_temp(trace(tcstat->ekinh), nd);
266             tcstat->T  = calc_temp(trace(tcstat->ekinf), nd);
267
268             /* after the scaling factors have been multiplied in, we can remove them */
269             if (bEkinAveVel)
270             {
271                 tcstat->ekinscalef_nhc = 1.0;
272             }
273             else
274             {
275                 tcstat->ekinscaleh_nhc = 1.0;
276             }
277         }
278         else
279         {
280             tcstat->T  = 0;
281             tcstat->Th = 0;
282         }
283         T += nd * tcstat->T;
284         nrdf += nd;
285     }
286     if (nrdf > 0)
287     {
288         T /= nrdf;
289     }
290     if (dekindlambda)
291     {
292         if (bEkinAveVel)
293         {
294             *dekindlambda = ekind->dekindl;
295         }
296         else
297         {
298             *dekindlambda = 0.5 * (ekind->dekindl + ekind->dekindl_old);
299         }
300     }
301     return T;
302 }