Merge release-4-6 into master
[alexxy/gromacs.git] / src / gromacs / mdlib / calcvir.c
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
9  *                        VERSION 3.2.0
10  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12  * Copyright (c) 2001-2004, The GROMACS development team,
13  * check out http://www.gromacs.org for more information.
14
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * If you want to redistribute modifications, please consider that
21  * scientific software is very special. Version control is crucial -
22  * bugs must be traceable. We will be happy to consider code for
23  * inclusion in the official distribution, but derived work must not
24  * be called official GROMACS. Details are found in the README & COPYING
25  * files - if they are missing, get the official version at www.gromacs.org.
26  *
27  * To help us fund GROMACS development, we humbly ask that you cite
28  * the papers on the package - you can find them in the top README file.
29  *
30  * For more info, check our website at http://www.gromacs.org
31  *
32  * And Hey:
33  * GROwing Monsters And Cloning Shrimps
34  */
35 /* This file is completely threadsafe - keep it that way! */
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include "sysstuff.h"
41 #include "force.h"
42 #include "vec.h"
43 #include "mshift.h"
44 #include "macros.h"
45
46 static void upd_vir(rvec vir, real dvx, real dvy, real dvz)
47 {
48     vir[XX] -= 0.5*dvx;
49     vir[YY] -= 0.5*dvy;
50     vir[ZZ] -= 0.5*dvz;
51 }
52
53 void calc_vir(FILE *log, int nxf, rvec x[], rvec f[], tensor vir,
54               gmx_bool bScrewPBC, matrix box)
55 {
56     int      i, isx;
57     double   dvxx = 0, dvxy = 0, dvxz = 0, dvyx = 0, dvyy = 0, dvyz = 0, dvzx = 0, dvzy = 0, dvzz = 0;
58
59     for (i = 0; (i < nxf); i++)
60     {
61         dvxx += x[i][XX]*f[i][XX];
62         dvxy += x[i][XX]*f[i][YY];
63         dvxz += x[i][XX]*f[i][ZZ];
64
65         dvyx += x[i][YY]*f[i][XX];
66         dvyy += x[i][YY]*f[i][YY];
67         dvyz += x[i][YY]*f[i][ZZ];
68
69         dvzx += x[i][ZZ]*f[i][XX];
70         dvzy += x[i][ZZ]*f[i][YY];
71         dvzz += x[i][ZZ]*f[i][ZZ];
72
73         if (bScrewPBC)
74         {
75             isx = IS2X(i);
76             /* We should correct all odd x-shifts, but the range of isx is -2 to 2 */
77             if (isx == 1 || isx == -1)
78             {
79                 dvyy += box[YY][YY]*f[i][YY];
80                 dvyz += box[YY][YY]*f[i][ZZ];
81
82                 dvzy += box[ZZ][ZZ]*f[i][YY];
83                 dvzz += box[ZZ][ZZ]*f[i][ZZ];
84             }
85         }
86     }
87
88     upd_vir(vir[XX], dvxx, dvxy, dvxz);
89     upd_vir(vir[YY], dvyx, dvyy, dvyz);
90     upd_vir(vir[ZZ], dvzx, dvzy, dvzz);
91 }
92
93
94 static void lo_fcv(int i0, int i1,
95                    real x[], real f[], tensor vir,
96                    int is[], real box[], gmx_bool bTriclinic)
97 {
98     int      i, i3, tx, ty, tz;
99     real     xx, yy, zz;
100     real     dvxx = 0, dvxy = 0, dvxz = 0, dvyx = 0, dvyy = 0, dvyz = 0, dvzx = 0, dvzy = 0, dvzz = 0;
101
102     if (bTriclinic)
103     {
104         for (i = i0; (i < i1); i++)
105         {
106             i3 = DIM*i;
107             tx = is[i3+XX];
108             ty = is[i3+YY];
109             tz = is[i3+ZZ];
110
111             xx    = x[i3+XX]-tx*box[XXXX]-ty*box[YYXX]-tz*box[ZZXX];
112             dvxx += xx*f[i3+XX];
113             dvxy += xx*f[i3+YY];
114             dvxz += xx*f[i3+ZZ];
115
116             yy    = x[i3+YY]-ty*box[YYYY]-tz*box[ZZYY];
117             dvyx += yy*f[i3+XX];
118             dvyy += yy*f[i3+YY];
119             dvyz += yy*f[i3+ZZ];
120
121             zz    = x[i3+ZZ]-tz*box[ZZZZ];
122             dvzx += zz*f[i3+XX];
123             dvzy += zz*f[i3+YY];
124             dvzz += zz*f[i3+ZZ];
125         }
126     }
127     else
128     {
129         for (i = i0; (i < i1); i++)
130         {
131             i3 = DIM*i;
132             tx = is[i3+XX];
133             ty = is[i3+YY];
134             tz = is[i3+ZZ];
135
136             xx    = x[i3+XX]-tx*box[XXXX];
137             dvxx += xx*f[i3+XX];
138             dvxy += xx*f[i3+YY];
139             dvxz += xx*f[i3+ZZ];
140
141             yy    = x[i3+YY]-ty*box[YYYY];
142             dvyx += yy*f[i3+XX];
143             dvyy += yy*f[i3+YY];
144             dvyz += yy*f[i3+ZZ];
145
146             zz    = x[i3+ZZ]-tz*box[ZZZZ];
147             dvzx += zz*f[i3+XX];
148             dvzy += zz*f[i3+YY];
149             dvzz += zz*f[i3+ZZ];
150         }
151     }
152
153     upd_vir(vir[XX], dvxx, dvxy, dvxz);
154     upd_vir(vir[YY], dvyx, dvyy, dvyz);
155     upd_vir(vir[ZZ], dvzx, dvzy, dvzz);
156 }
157
158 static void lo_fcv2(int i0, int i1,
159                     rvec x[], rvec f[], tensor vir,
160                     ivec is[], matrix box, gmx_bool bTriclinic)
161 {
162     int      i, gg, tx, ty, tz;
163     real     xx, yy, zz;
164     real     dvxx = 0, dvxy = 0, dvxz = 0, dvyx = 0, dvyy = 0, dvyz = 0, dvzx = 0, dvzy = 0, dvzz = 0;
165
166     if (bTriclinic)
167     {
168         for (i = i0, gg = 0; (i < i1); i++, gg++)
169         {
170             tx = is[gg][XX];
171             ty = is[gg][YY];
172             tz = is[gg][ZZ];
173
174             xx    = x[i][XX]-tx*box[XX][XX]-ty*box[YY][XX]-tz*box[ZZ][XX];
175             dvxx += xx*f[i][XX];
176             dvxy += xx*f[i][YY];
177             dvxz += xx*f[i][ZZ];
178
179             yy    = x[i][YY]-ty*box[YY][YY]-tz*box[ZZ][YY];
180             dvyx += yy*f[i][XX];
181             dvyy += yy*f[i][YY];
182             dvyz += yy*f[i][ZZ];
183
184             zz    = x[i][ZZ]-tz*box[ZZ][ZZ];
185             dvzx += zz*f[i][XX];
186             dvzy += zz*f[i][YY];
187             dvzz += zz*f[i][ZZ];
188         }
189     }
190     else
191     {
192         for (i = i0, gg = 0; (i < i1); i++, gg++)
193         {
194             tx = is[gg][XX];
195             ty = is[gg][YY];
196             tz = is[gg][ZZ];
197
198             xx    = x[i][XX]-tx*box[XX][XX];
199             dvxx += xx*f[i][XX];
200             dvxy += xx*f[i][YY];
201             dvxz += xx*f[i][ZZ];
202
203             yy    = x[i][YY]-ty*box[YY][YY];
204             dvyx += yy*f[i][XX];
205             dvyy += yy*f[i][YY];
206             dvyz += yy*f[i][ZZ];
207
208             zz    = x[i][ZZ]-tz*box[ZZ][ZZ];
209             dvzx += zz*f[i][XX];
210             dvzy += zz*f[i][YY];
211             dvzz += zz*f[i][ZZ];
212         }
213     }
214
215     upd_vir(vir[XX], dvxx, dvxy, dvxz);
216     upd_vir(vir[YY], dvyx, dvyy, dvyz);
217     upd_vir(vir[ZZ], dvzx, dvzy, dvzz);
218 }
219
220 void f_calc_vir(FILE *log, int i0, int i1, rvec x[], rvec f[], tensor vir,
221                 t_graph *g, matrix box)
222 {
223     int start, end;
224
225     if (g && (g->nnodes > 0))
226     {
227         /* Calculate virial for bonded forces only when they belong to
228          * this node.
229          */
230         start = max(i0, g->at_start);
231         end   = min(i1, g->at_end);
232 #ifdef SAFE
233         lo_fcv2(start, end, x, f, vir, g->ishift, box, TRICLINIC(box));
234 #else
235         lo_fcv(start, end, x[0], f[0], vir, g->ishift[0], box[0], TRICLINIC(box));
236 #endif
237
238         /* If not all atoms are bonded, calculate their virial contribution
239          * anyway, without shifting back their coordinates.
240          * Note the nifty pointer arithmetic...
241          */
242         if (start > i0)
243         {
244             calc_vir(log, start-i0, x + i0, f + i0, vir, FALSE, box);
245         }
246         if (end < i1)
247         {
248             calc_vir(log, i1-end, x + end, f + end, vir, FALSE, box);
249         }
250     }
251     else
252     {
253         calc_vir(log, i1-i0, x + i0, f + i0, vir, FALSE, box);
254     }
255 }