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,2018, 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! */
42 #include "config.h" /* for GMX_MAX_OPENMP_THREADS */
46 #include "gromacs/math/vec.h"
47 #include "gromacs/math/vectypes.h"
48 #include "gromacs/mdlib/gmx_omp_nthreads.h"
49 #include "gromacs/pbcutil/ishift.h"
50 #include "gromacs/pbcutil/mshift.h"
51 #include "gromacs/pbcutil/pbc.h"
52 #include "gromacs/utility/gmxassert.h"
64 static void upd_vir(rvec vir
, real dvx
, real dvy
, real dvz
)
71 static void calc_x_times_f(int nxf
, const rvec x
[], const rvec f
[],
72 gmx_bool bScrewPBC
, const matrix box
,
77 for (int i
= 0; i
< nxf
; i
++)
79 for (int d
= 0; d
< DIM
; d
++)
81 for (int n
= 0; n
< DIM
; n
++)
83 x_times_f
[d
][n
] += x
[i
][d
]*f
[i
][n
];
90 /* We should correct all odd x-shifts, but the range of isx is -2 to 2 */
91 if (isx
== 1 || isx
== -1)
93 for (int d
= 0; d
< DIM
; d
++)
95 for (int n
= 0; n
< DIM
; n
++)
97 x_times_f
[d
][n
] += box
[d
][d
]*f
[i
][n
];
105 void calc_vir(int nxf
, const rvec x
[], const rvec f
[], tensor vir
,
106 bool bScrewPBC
, const matrix box
)
110 int nthreads
= gmx_omp_nthreads_get_simple_rvec_task(emntDefault
, nxf
*9);
112 GMX_ASSERT(nthreads
>= 1, "Avoids uninitialized x_times_f (warning)");
116 calc_x_times_f(nxf
, x
, f
, bScrewPBC
, box
, x_times_f
);
120 /* Use a buffer on the stack for storing thread-local results.
121 * We use 2 extra elements (=18 reals) per thread to separate thread
122 * local data by at least a cache line. Element 0 is not used.
124 matrix xf_buf
[GMX_OPENMP_MAX_THREADS
*3];
126 #pragma omp parallel for num_threads(nthreads) schedule(static)
127 for (int thread
= 0; thread
< nthreads
; thread
++)
129 int start
= (nxf
*thread
)/nthreads
;
130 int end
= std::min(nxf
*(thread
+ 1)/nthreads
, nxf
);
132 calc_x_times_f(end
- start
, x
+ start
, f
+ start
, bScrewPBC
, box
,
133 thread
== 0 ? x_times_f
: xf_buf
[thread
*3]);
136 for (int thread
= 1; thread
< nthreads
; thread
++)
138 m_add(x_times_f
, xf_buf
[thread
*3], x_times_f
);
142 for (int d
= 0; d
< DIM
; d
++)
144 upd_vir(vir
[d
], x_times_f
[d
][XX
], x_times_f
[d
][YY
], x_times_f
[d
][ZZ
]);
149 static void lo_fcv(int i0
, int i1
,
150 const real x
[], const real f
[], tensor vir
,
151 const int is
[], const real box
[], gmx_bool bTriclinic
)
153 int i
, i3
, tx
, ty
, tz
;
155 real dvxx
= 0, dvxy
= 0, dvxz
= 0, dvyx
= 0, dvyy
= 0, dvyz
= 0, dvzx
= 0, dvzy
= 0, dvzz
= 0;
159 for (i
= i0
; (i
< i1
); i
++)
166 xx
= x
[i3
+XX
]-tx
*box
[XXXX
]-ty
*box
[YYXX
]-tz
*box
[ZZXX
];
171 yy
= x
[i3
+YY
]-ty
*box
[YYYY
]-tz
*box
[ZZYY
];
176 zz
= x
[i3
+ZZ
]-tz
*box
[ZZZZ
];
184 for (i
= i0
; (i
< i1
); i
++)
191 xx
= x
[i3
+XX
]-tx
*box
[XXXX
];
196 yy
= x
[i3
+YY
]-ty
*box
[YYYY
];
201 zz
= x
[i3
+ZZ
]-tz
*box
[ZZZZ
];
208 upd_vir(vir
[XX
], dvxx
, dvxy
, dvxz
);
209 upd_vir(vir
[YY
], dvyx
, dvyy
, dvyz
);
210 upd_vir(vir
[ZZ
], dvzx
, dvzy
, dvzz
);
213 void f_calc_vir(int i0
, int i1
, const rvec x
[], const rvec f
[], tensor vir
,
214 const t_graph
*g
, const matrix box
)
218 if (g
&& (g
->nnodes
> 0))
220 /* Calculate virial for bonded forces only when they belong to
223 start
= std::max(i0
, g
->at_start
);
224 end
= std::min(i1
, g
->at_end
);
225 lo_fcv(start
, end
, x
[0], f
[0], vir
, g
->ishift
[0], box
[0], TRICLINIC(box
));
227 /* If not all atoms are bonded, calculate their virial contribution
228 * anyway, without shifting back their coordinates.
229 * Note the nifty pointer arithmetic...
233 calc_vir(start
-i0
, x
+ i0
, f
+ i0
, vir
, FALSE
, box
);
237 calc_vir(i1
-end
, x
+ end
, f
+ end
, vir
, FALSE
, box
);
242 calc_vir(i1
-i0
, x
+ i0
, f
+ i0
, vir
, FALSE
, box
);