Avoid numerical overflow with overlapping atoms
[gromacs.git] / src / gromacs / mdlib / calcvir.cpp
blob33868b7d99170e67224a236ac0a61c46535cfa10
1 /*
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, 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.
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.
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.
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.
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.
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.
37 /* This file is completely threadsafe - keep it that way! */
38 #include "gmxpre.h"
40 #include <algorithm>
42 #include "gromacs/math/vectypes.h"
43 #include "gromacs/mdlib/force.h"
44 #include "gromacs/mdlib/gmx_omp_nthreads.h"
45 #include "gromacs/pbcutil/ishift.h"
46 #include "gromacs/pbcutil/mshift.h"
47 #include "gromacs/pbcutil/pbc.h"
49 #define XXXX 0
50 #define XXYY 1
51 #define XXZZ 2
52 #define YYXX 3
53 #define YYYY 4
54 #define YYZZ 5
55 #define ZZXX 6
56 #define ZZYY 7
57 #define ZZZZ 8
59 static void upd_vir(rvec vir, real dvx, real dvy, real dvz)
61 vir[XX] -= 0.5*dvx;
62 vir[YY] -= 0.5*dvy;
63 vir[ZZ] -= 0.5*dvz;
66 void calc_vir(int nxf, rvec x[], rvec f[], tensor vir,
67 gmx_bool bScrewPBC, matrix box)
69 int i;
70 double dvxx = 0, dvxy = 0, dvxz = 0, dvyx = 0, dvyy = 0, dvyz = 0, dvzx = 0, dvzy = 0, dvzz = 0;
72 #pragma omp parallel for num_threads(gmx_omp_nthreads_get(emntDefault)) \
73 schedule(static) \
74 reduction(+: dvxx, dvxy, dvxz, dvyx, dvyy, dvyz, dvzx, dvzy, dvzz)
75 for (i = 0; i < nxf; i++)
77 dvxx += x[i][XX]*f[i][XX];
78 dvxy += x[i][XX]*f[i][YY];
79 dvxz += x[i][XX]*f[i][ZZ];
81 dvyx += x[i][YY]*f[i][XX];
82 dvyy += x[i][YY]*f[i][YY];
83 dvyz += x[i][YY]*f[i][ZZ];
85 dvzx += x[i][ZZ]*f[i][XX];
86 dvzy += x[i][ZZ]*f[i][YY];
87 dvzz += x[i][ZZ]*f[i][ZZ];
89 if (bScrewPBC)
91 int isx = IS2X(i);
92 /* We should correct all odd x-shifts, but the range of isx is -2 to 2 */
93 if (isx == 1 || isx == -1)
95 dvyy += box[YY][YY]*f[i][YY];
96 dvyz += box[YY][YY]*f[i][ZZ];
98 dvzy += box[ZZ][ZZ]*f[i][YY];
99 dvzz += box[ZZ][ZZ]*f[i][ZZ];
104 upd_vir(vir[XX], dvxx, dvxy, dvxz);
105 upd_vir(vir[YY], dvyx, dvyy, dvyz);
106 upd_vir(vir[ZZ], dvzx, dvzy, dvzz);
110 static void lo_fcv(int i0, int i1,
111 real x[], real f[], tensor vir,
112 int is[], real box[], gmx_bool bTriclinic)
114 int i, i3, tx, ty, tz;
115 real xx, yy, zz;
116 real dvxx = 0, dvxy = 0, dvxz = 0, dvyx = 0, dvyy = 0, dvyz = 0, dvzx = 0, dvzy = 0, dvzz = 0;
118 if (bTriclinic)
120 for (i = i0; (i < i1); i++)
122 i3 = DIM*i;
123 tx = is[i3+XX];
124 ty = is[i3+YY];
125 tz = is[i3+ZZ];
127 xx = x[i3+XX]-tx*box[XXXX]-ty*box[YYXX]-tz*box[ZZXX];
128 dvxx += xx*f[i3+XX];
129 dvxy += xx*f[i3+YY];
130 dvxz += xx*f[i3+ZZ];
132 yy = x[i3+YY]-ty*box[YYYY]-tz*box[ZZYY];
133 dvyx += yy*f[i3+XX];
134 dvyy += yy*f[i3+YY];
135 dvyz += yy*f[i3+ZZ];
137 zz = x[i3+ZZ]-tz*box[ZZZZ];
138 dvzx += zz*f[i3+XX];
139 dvzy += zz*f[i3+YY];
140 dvzz += zz*f[i3+ZZ];
143 else
145 for (i = i0; (i < i1); i++)
147 i3 = DIM*i;
148 tx = is[i3+XX];
149 ty = is[i3+YY];
150 tz = is[i3+ZZ];
152 xx = x[i3+XX]-tx*box[XXXX];
153 dvxx += xx*f[i3+XX];
154 dvxy += xx*f[i3+YY];
155 dvxz += xx*f[i3+ZZ];
157 yy = x[i3+YY]-ty*box[YYYY];
158 dvyx += yy*f[i3+XX];
159 dvyy += yy*f[i3+YY];
160 dvyz += yy*f[i3+ZZ];
162 zz = x[i3+ZZ]-tz*box[ZZZZ];
163 dvzx += zz*f[i3+XX];
164 dvzy += zz*f[i3+YY];
165 dvzz += zz*f[i3+ZZ];
169 upd_vir(vir[XX], dvxx, dvxy, dvxz);
170 upd_vir(vir[YY], dvyx, dvyy, dvyz);
171 upd_vir(vir[ZZ], dvzx, dvzy, dvzz);
174 void f_calc_vir(int i0, int i1, rvec x[], rvec f[], tensor vir,
175 t_graph *g, matrix box)
177 int start, end;
179 if (g && (g->nnodes > 0))
181 /* Calculate virial for bonded forces only when they belong to
182 * this node.
184 start = std::max(i0, g->at_start);
185 end = std::min(i1, g->at_end);
186 lo_fcv(start, end, x[0], f[0], vir, g->ishift[0], box[0], TRICLINIC(box));
188 /* If not all atoms are bonded, calculate their virial contribution
189 * anyway, without shifting back their coordinates.
190 * Note the nifty pointer arithmetic...
192 if (start > i0)
194 calc_vir(start-i0, x + i0, f + i0, vir, FALSE, box);
196 if (end < i1)
198 calc_vir(i1-end, x + end, f + end, vir, FALSE, box);
201 else
203 calc_vir(i1-i0, x + i0, f + i0, vir, FALSE, box);