Enable missing declarations warning
[alexxy/gromacs.git] / src / gromacs / listed-forces / bonded.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, 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 /*! \internal \file
38  *
39  * \brief This file defines low-level functions necessary for
40  * computing energies and forces for listed interactions.
41  *
42  * \author Mark Abraham <mark.j.abraham@gmail.com>
43  *
44  * \ingroup module_listed-forces
45  */
46 #include "gmxpre.h"
47
48 #include "bonded.h"
49
50 #include "config.h"
51
52 #include <cassert>
53 #include <cmath>
54
55 #include <algorithm>
56
57 #include "gromacs/listed-forces/pairs.h"
58 #include "gromacs/math/functions.h"
59 #include "gromacs/math/units.h"
60 #include "gromacs/math/utilities.h"
61 #include "gromacs/math/vec.h"
62 #include "gromacs/pbcutil/ishift.h"
63 #include "gromacs/pbcutil/mshift.h"
64 #include "gromacs/pbcutil/pbc.h"
65 #include "gromacs/pbcutil/pbc-simd.h"
66 #include "gromacs/simd/simd.h"
67 #include "gromacs/simd/simd_math.h"
68 #include "gromacs/simd/vector_operations.h"
69 #include "gromacs/utility/basedefinitions.h"
70 #include "gromacs/utility/fatalerror.h"
71 #include "gromacs/utility/real.h"
72 #include "gromacs/utility/smalloc.h"
73
74 #include "listed-internal.h"
75 #include "restcbt.h"
76
77 using namespace gmx; // TODO: Remove when this file is moved into gmx namespace
78
79 /*! \brief Mysterious CMAP coefficient matrix */
80 const int cmap_coeff_matrix[] = {
81     1, 0, -3,  2, 0, 0,  0,  0, -3,  0,  9, -6,  2,  0, -6,  4,
82     0, 0,  0,  0, 0, 0,  0,  0,  3,  0, -9,  6, -2,  0,  6, -4,
83     0, 0,  0,  0, 0, 0,  0,  0,  0,  0,  9, -6,  0,  0, -6,  4,
84     0, 0,  3, -2, 0, 0,  0,  0,  0,  0, -9,  6,  0,  0,  6, -4,
85     0, 0,  0,  0, 1, 0, -3,  2, -2,  0,  6, -4,  1,  0, -3,  2,
86     0, 0,  0,  0, 0, 0,  0,  0, -1,  0,  3, -2,  1,  0, -3,  2,
87     0, 0,  0,  0, 0, 0,  0,  0,  0,  0, -3,  2,  0,  0,  3, -2,
88     0, 0,  0,  0, 0, 0,  3, -2,  0,  0, -6,  4,  0,  0,  3, -2,
89     0, 1, -2,  1, 0, 0,  0,  0,  0, -3,  6, -3,  0,  2, -4,  2,
90     0, 0,  0,  0, 0, 0,  0,  0,  0,  3, -6,  3,  0, -2,  4, -2,
91     0, 0,  0,  0, 0, 0,  0,  0,  0,  0, -3,  3,  0,  0,  2, -2,
92     0, 0, -1,  1, 0, 0,  0,  0,  0,  0,  3, -3,  0,  0, -2,  2,
93     0, 0,  0,  0, 0, 1, -2,  1,  0, -2,  4, -2,  0,  1, -2,  1,
94     0, 0,  0,  0, 0, 0,  0,  0,  0, -1,  2, -1,  0,  1, -2,  1,
95     0, 0,  0,  0, 0, 0,  0,  0,  0,  0,  1, -1,  0,  0, -1,  1,
96     0, 0,  0,  0, 0, 0, -1,  1,  0,  0,  2, -2,  0,  0, -1,  1
97 };
98
99
100 /*! \brief Compute dx = xi - xj, modulo PBC if non-NULL
101  *
102  * \todo This kind of code appears in many places. Consolidate it */
103 static int pbc_rvec_sub(const t_pbc *pbc, const rvec xi, const rvec xj, rvec dx)
104 {
105     if (pbc)
106     {
107         return pbc_dx_aiuc(pbc, xi, xj, dx);
108     }
109     else
110     {
111         rvec_sub(xi, xj, dx);
112         return CENTRAL;
113     }
114 }
115
116 /*! \brief Morse potential bond
117  *
118  * By Frank Everdij. Three parameters needed:
119  *
120  * b0 = equilibrium distance in nm
121  * be = beta in nm^-1 (actually, it's nu_e*Sqrt(2*pi*pi*mu/D_e))
122  * cb = well depth in kJ/mol
123  *
124  * Note: the potential is referenced to be +cb at infinite separation
125  *       and zero at the equilibrium distance!
126  */
127 real morse_bonds(int nbonds,
128                  const t_iatom forceatoms[], const t_iparams forceparams[],
129                  const rvec x[], rvec4 f[], rvec fshift[],
130                  const t_pbc *pbc, const t_graph *g,
131                  real lambda, real *dvdlambda,
132                  const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
133                  int gmx_unused *global_atom_index)
134 {
135     const real one = 1.0;
136     const real two = 2.0;
137     real       dr, dr2, temp, omtemp, cbomtemp, fbond, vbond, fij, vtot;
138     real       b0, be, cb, b0A, beA, cbA, b0B, beB, cbB, L1;
139     rvec       dx;
140     int        i, m, ki, type, ai, aj;
141     ivec       dt;
142
143     vtot = 0.0;
144     for (i = 0; (i < nbonds); )
145     {
146         type = forceatoms[i++];
147         ai   = forceatoms[i++];
148         aj   = forceatoms[i++];
149
150         b0A   = forceparams[type].morse.b0A;
151         beA   = forceparams[type].morse.betaA;
152         cbA   = forceparams[type].morse.cbA;
153
154         b0B   = forceparams[type].morse.b0B;
155         beB   = forceparams[type].morse.betaB;
156         cbB   = forceparams[type].morse.cbB;
157
158         L1 = one-lambda;                            /* 1 */
159         b0 = L1*b0A + lambda*b0B;                   /* 3 */
160         be = L1*beA + lambda*beB;                   /* 3 */
161         cb = L1*cbA + lambda*cbB;                   /* 3 */
162
163         ki   = pbc_rvec_sub(pbc, x[ai], x[aj], dx); /*   3          */
164         dr2  = iprod(dx, dx);                       /*   5          */
165         dr   = dr2*gmx::invsqrt(dr2);               /*  10          */
166         temp = std::exp(-be*(dr-b0));               /*  12          */
167
168         if (temp == one)
169         {
170             /* bonds are constrainted. This may _not_ include bond constraints if they are lambda dependent */
171             *dvdlambda += cbB-cbA;
172             continue;
173         }
174
175         omtemp    = one-temp;                                                                                        /*   1          */
176         cbomtemp  = cb*omtemp;                                                                                       /*   1          */
177         vbond     = cbomtemp*omtemp;                                                                                 /*   1          */
178         fbond     = -two*be*temp*cbomtemp*gmx::invsqrt(dr2);                                                         /*   9          */
179         vtot     += vbond;                                                                                           /*   1          */
180
181         *dvdlambda += (cbB - cbA) * omtemp * omtemp - (2-2*omtemp)*omtemp * cb * ((b0B-b0A)*be - (beB-beA)*(dr-b0)); /* 15 */
182
183         if (g)
184         {
185             ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
186             ki = IVEC2IS(dt);
187         }
188
189         for (m = 0; (m < DIM); m++)                    /*  15          */
190         {
191             fij                 = fbond*dx[m];
192             f[ai][m]           += fij;
193             f[aj][m]           -= fij;
194             fshift[ki][m]      += fij;
195             fshift[CENTRAL][m] -= fij;
196         }
197     }                                         /*  83 TOTAL    */
198     return vtot;
199 }
200
201 //! \cond
202 real cubic_bonds(int nbonds,
203                  const t_iatom forceatoms[], const t_iparams forceparams[],
204                  const rvec x[], rvec4 f[], rvec fshift[],
205                  const t_pbc *pbc, const t_graph *g,
206                  real gmx_unused lambda, real gmx_unused *dvdlambda,
207                  const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
208                  int gmx_unused *global_atom_index)
209 {
210     const real three = 3.0;
211     const real two   = 2.0;
212     real       kb, b0, kcub;
213     real       dr, dr2, dist, kdist, kdist2, fbond, vbond, fij, vtot;
214     rvec       dx;
215     int        i, m, ki, type, ai, aj;
216     ivec       dt;
217
218     vtot = 0.0;
219     for (i = 0; (i < nbonds); )
220     {
221         type = forceatoms[i++];
222         ai   = forceatoms[i++];
223         aj   = forceatoms[i++];
224
225         b0   = forceparams[type].cubic.b0;
226         kb   = forceparams[type].cubic.kb;
227         kcub = forceparams[type].cubic.kcub;
228
229         ki   = pbc_rvec_sub(pbc, x[ai], x[aj], dx);     /*   3          */
230         dr2  = iprod(dx, dx);                           /*   5          */
231
232         if (dr2 == 0.0)
233         {
234             continue;
235         }
236
237         dr         = dr2*gmx::invsqrt(dr2);                  /*  10          */
238         dist       = dr-b0;
239         kdist      = kb*dist;
240         kdist2     = kdist*dist;
241
242         vbond      = kdist2 + kcub*kdist2*dist;
243         fbond      = -(two*kdist + three*kdist2*kcub)/dr;
244
245         vtot      += vbond;   /* 21 */
246
247         if (g)
248         {
249             ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
250             ki = IVEC2IS(dt);
251         }
252         for (m = 0; (m < DIM); m++)                    /*  15          */
253         {
254             fij                 = fbond*dx[m];
255             f[ai][m]           += fij;
256             f[aj][m]           -= fij;
257             fshift[ki][m]      += fij;
258             fshift[CENTRAL][m] -= fij;
259         }
260     }                                         /*  54 TOTAL    */
261     return vtot;
262 }
263
264 real FENE_bonds(int nbonds,
265                 const t_iatom forceatoms[], const t_iparams forceparams[],
266                 const rvec x[], rvec4 f[], rvec fshift[],
267                 const t_pbc *pbc, const t_graph *g,
268                 real gmx_unused lambda, real gmx_unused *dvdlambda,
269                 const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
270                 int *global_atom_index)
271 {
272     const real half = 0.5;
273     const real one  = 1.0;
274     real       bm, kb;
275     real       dr2, bm2, omdr2obm2, fbond, vbond, fij, vtot;
276     rvec       dx;
277     int        i, m, ki, type, ai, aj;
278     ivec       dt;
279
280     vtot = 0.0;
281     for (i = 0; (i < nbonds); )
282     {
283         type = forceatoms[i++];
284         ai   = forceatoms[i++];
285         aj   = forceatoms[i++];
286
287         bm   = forceparams[type].fene.bm;
288         kb   = forceparams[type].fene.kb;
289
290         ki   = pbc_rvec_sub(pbc, x[ai], x[aj], dx);     /*   3          */
291         dr2  = iprod(dx, dx);                           /*   5          */
292
293         if (dr2 == 0.0)
294         {
295             continue;
296         }
297
298         bm2 = bm*bm;
299
300         if (dr2 >= bm2)
301         {
302             gmx_fatal(FARGS,
303                       "r^2 (%f) >= bm^2 (%f) in FENE bond between atoms %d and %d",
304                       dr2, bm2,
305                       glatnr(global_atom_index, ai),
306                       glatnr(global_atom_index, aj));
307         }
308
309         omdr2obm2  = one - dr2/bm2;
310
311         vbond      = -half*kb*bm2*std::log(omdr2obm2);
312         fbond      = -kb/omdr2obm2;
313
314         vtot      += vbond;   /* 35 */
315
316         if (g)
317         {
318             ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
319             ki = IVEC2IS(dt);
320         }
321         for (m = 0; (m < DIM); m++)                    /*  15          */
322         {
323             fij                 = fbond*dx[m];
324             f[ai][m]           += fij;
325             f[aj][m]           -= fij;
326             fshift[ki][m]      += fij;
327             fshift[CENTRAL][m] -= fij;
328         }
329     }                                         /*  58 TOTAL    */
330     return vtot;
331 }
332
333 static real harmonic(real kA, real kB, real xA, real xB, real x, real lambda,
334                      real *V, real *F)
335 {
336     const real half = 0.5;
337     real       L1, kk, x0, dx, dx2;
338     real       v, f, dvdlambda;
339
340     L1    = 1.0-lambda;
341     kk    = L1*kA+lambda*kB;
342     x0    = L1*xA+lambda*xB;
343
344     dx    = x-x0;
345     dx2   = dx*dx;
346
347     f          = -kk*dx;
348     v          = half*kk*dx2;
349     dvdlambda  = half*(kB-kA)*dx2 + (xA-xB)*kk*dx;
350
351     *F    = f;
352     *V    = v;
353
354     return dvdlambda;
355
356     /* That was 19 flops */
357 }
358
359
360 real bonds(int nbonds,
361            const t_iatom forceatoms[], const t_iparams forceparams[],
362            const rvec x[], rvec4 f[], rvec fshift[],
363            const t_pbc *pbc, const t_graph *g,
364            real lambda, real *dvdlambda,
365            const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
366            int gmx_unused *global_atom_index)
367 {
368     int  i, m, ki, ai, aj, type;
369     real dr, dr2, fbond, vbond, fij, vtot;
370     rvec dx;
371     ivec dt;
372
373     vtot = 0.0;
374     for (i = 0; (i < nbonds); )
375     {
376         type = forceatoms[i++];
377         ai   = forceatoms[i++];
378         aj   = forceatoms[i++];
379
380         ki   = pbc_rvec_sub(pbc, x[ai], x[aj], dx); /*   3      */
381         dr2  = iprod(dx, dx);                       /*   5              */
382         dr   = dr2*gmx::invsqrt(dr2);               /*  10              */
383
384         *dvdlambda += harmonic(forceparams[type].harmonic.krA,
385                                forceparams[type].harmonic.krB,
386                                forceparams[type].harmonic.rA,
387                                forceparams[type].harmonic.rB,
388                                dr, lambda, &vbond, &fbond); /*  19  */
389
390         if (dr2 == 0.0)
391         {
392             continue;
393         }
394
395
396         vtot  += vbond;             /* 1*/
397         fbond *= gmx::invsqrt(dr2); /*   6              */
398 #ifdef DEBUG
399         if (debug)
400         {
401             fprintf(debug, "BONDS: dr = %10g  vbond = %10g  fbond = %10g\n",
402                     dr, vbond, fbond);
403         }
404 #endif
405         if (g)
406         {
407             ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
408             ki = IVEC2IS(dt);
409         }
410         for (m = 0; (m < DIM); m++)     /*  15          */
411         {
412             fij                 = fbond*dx[m];
413             f[ai][m]           += fij;
414             f[aj][m]           -= fij;
415             fshift[ki][m]      += fij;
416             fshift[CENTRAL][m] -= fij;
417         }
418     }               /* 59 TOTAL */
419     return vtot;
420 }
421
422 real restraint_bonds(int nbonds,
423                      const t_iatom forceatoms[], const t_iparams forceparams[],
424                      const rvec x[], rvec4 f[], rvec fshift[],
425                      const t_pbc *pbc, const t_graph *g,
426                      real lambda, real *dvdlambda,
427                      const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
428                      int gmx_unused *global_atom_index)
429 {
430     int  i, m, ki, ai, aj, type;
431     real dr, dr2, fbond, vbond, fij, vtot;
432     real L1;
433     real low, dlow, up1, dup1, up2, dup2, k, dk;
434     real drh, drh2;
435     rvec dx;
436     ivec dt;
437
438     L1   = 1.0 - lambda;
439
440     vtot = 0.0;
441     for (i = 0; (i < nbonds); )
442     {
443         type = forceatoms[i++];
444         ai   = forceatoms[i++];
445         aj   = forceatoms[i++];
446
447         ki   = pbc_rvec_sub(pbc, x[ai], x[aj], dx); /*   3      */
448         dr2  = iprod(dx, dx);                       /*   5              */
449         dr   = dr2*gmx::invsqrt(dr2);               /*  10              */
450
451         low  = L1*forceparams[type].restraint.lowA + lambda*forceparams[type].restraint.lowB;
452         dlow =   -forceparams[type].restraint.lowA +        forceparams[type].restraint.lowB;
453         up1  = L1*forceparams[type].restraint.up1A + lambda*forceparams[type].restraint.up1B;
454         dup1 =   -forceparams[type].restraint.up1A +        forceparams[type].restraint.up1B;
455         up2  = L1*forceparams[type].restraint.up2A + lambda*forceparams[type].restraint.up2B;
456         dup2 =   -forceparams[type].restraint.up2A +        forceparams[type].restraint.up2B;
457         k    = L1*forceparams[type].restraint.kA   + lambda*forceparams[type].restraint.kB;
458         dk   =   -forceparams[type].restraint.kA   +        forceparams[type].restraint.kB;
459         /* 24 */
460
461         if (dr < low)
462         {
463             drh         = dr - low;
464             drh2        = drh*drh;
465             vbond       = 0.5*k*drh2;
466             fbond       = -k*drh;
467             *dvdlambda += 0.5*dk*drh2 - k*dlow*drh;
468         } /* 11 */
469         else if (dr <= up1)
470         {
471             vbond = 0;
472             fbond = 0;
473         }
474         else if (dr <= up2)
475         {
476             drh         = dr - up1;
477             drh2        = drh*drh;
478             vbond       = 0.5*k*drh2;
479             fbond       = -k*drh;
480             *dvdlambda += 0.5*dk*drh2 - k*dup1*drh;
481         } /* 11 */
482         else
483         {
484             drh         = dr - up2;
485             vbond       = k*(up2 - up1)*(0.5*(up2 - up1) + drh);
486             fbond       = -k*(up2 - up1);
487             *dvdlambda += dk*(up2 - up1)*(0.5*(up2 - up1) + drh)
488                 + k*(dup2 - dup1)*(up2 - up1 + drh)
489                 - k*(up2 - up1)*dup2;
490         }
491
492         if (dr2 == 0.0)
493         {
494             continue;
495         }
496
497         vtot  += vbond;             /* 1*/
498         fbond *= gmx::invsqrt(dr2); /*   6              */
499 #ifdef DEBUG
500         if (debug)
501         {
502             fprintf(debug, "BONDS: dr = %10g  vbond = %10g  fbond = %10g\n",
503                     dr, vbond, fbond);
504         }
505 #endif
506         if (g)
507         {
508             ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
509             ki = IVEC2IS(dt);
510         }
511         for (m = 0; (m < DIM); m++)             /*  15          */
512         {
513             fij                 = fbond*dx[m];
514             f[ai][m]           += fij;
515             f[aj][m]           -= fij;
516             fshift[ki][m]      += fij;
517             fshift[CENTRAL][m] -= fij;
518         }
519     }                   /* 59 TOTAL     */
520
521     return vtot;
522 }
523
524 real polarize(int nbonds,
525               const t_iatom forceatoms[], const t_iparams forceparams[],
526               const rvec x[], rvec4 f[], rvec fshift[],
527               const t_pbc *pbc, const t_graph *g,
528               real lambda, real *dvdlambda,
529               const t_mdatoms *md, t_fcdata gmx_unused *fcd,
530               int gmx_unused *global_atom_index)
531 {
532     int  i, m, ki, ai, aj, type;
533     real dr, dr2, fbond, vbond, fij, vtot, ksh;
534     rvec dx;
535     ivec dt;
536
537     vtot = 0.0;
538     for (i = 0; (i < nbonds); )
539     {
540         type = forceatoms[i++];
541         ai   = forceatoms[i++];
542         aj   = forceatoms[i++];
543         ksh  = gmx::square(md->chargeA[aj])*ONE_4PI_EPS0/forceparams[type].polarize.alpha;
544         if (debug)
545         {
546             fprintf(debug, "POL: local ai = %d aj = %d ksh = %.3f\n", ai, aj, ksh);
547         }
548
549         ki   = pbc_rvec_sub(pbc, x[ai], x[aj], dx);                         /*   3      */
550         dr2  = iprod(dx, dx);                                               /*   5              */
551         dr   = std::sqrt(dr2);                                              /*  10              */
552
553         *dvdlambda += harmonic(ksh, ksh, 0, 0, dr, lambda, &vbond, &fbond); /*  19  */
554
555         if (dr2 == 0.0)
556         {
557             continue;
558         }
559
560         vtot  += vbond;             /* 1*/
561         fbond *= gmx::invsqrt(dr2); /*   6              */
562
563         if (g)
564         {
565             ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
566             ki = IVEC2IS(dt);
567         }
568         for (m = 0; (m < DIM); m++)     /*  15          */
569         {
570             fij                 = fbond*dx[m];
571             f[ai][m]           += fij;
572             f[aj][m]           -= fij;
573             fshift[ki][m]      += fij;
574             fshift[CENTRAL][m] -= fij;
575         }
576     }               /* 59 TOTAL */
577     return vtot;
578 }
579
580 real anharm_polarize(int nbonds,
581                      const t_iatom forceatoms[], const t_iparams forceparams[],
582                      const rvec x[], rvec4 f[], rvec fshift[],
583                      const t_pbc *pbc, const t_graph *g,
584                      real lambda, real *dvdlambda,
585                      const t_mdatoms *md, t_fcdata gmx_unused *fcd,
586                      int gmx_unused *global_atom_index)
587 {
588     int  i, m, ki, ai, aj, type;
589     real dr, dr2, fbond, vbond, fij, vtot, ksh, khyp, drcut, ddr, ddr3;
590     rvec dx;
591     ivec dt;
592
593     vtot = 0.0;
594     for (i = 0; (i < nbonds); )
595     {
596         type  = forceatoms[i++];
597         ai    = forceatoms[i++];
598         aj    = forceatoms[i++];
599         ksh   = gmx::square(md->chargeA[aj])*ONE_4PI_EPS0/forceparams[type].anharm_polarize.alpha; /* 7*/
600         khyp  = forceparams[type].anharm_polarize.khyp;
601         drcut = forceparams[type].anharm_polarize.drcut;
602         if (debug)
603         {
604             fprintf(debug, "POL: local ai = %d aj = %d ksh = %.3f\n", ai, aj, ksh);
605         }
606
607         ki   = pbc_rvec_sub(pbc, x[ai], x[aj], dx);                         /*   3      */
608         dr2  = iprod(dx, dx);                                               /*   5              */
609         dr   = dr2*gmx::invsqrt(dr2);                                       /*  10              */
610
611         *dvdlambda += harmonic(ksh, ksh, 0, 0, dr, lambda, &vbond, &fbond); /*  19  */
612
613         if (dr2 == 0.0)
614         {
615             continue;
616         }
617
618         if (dr > drcut)
619         {
620             ddr    = dr-drcut;
621             ddr3   = ddr*ddr*ddr;
622             vbond += khyp*ddr*ddr3;
623             fbond -= 4*khyp*ddr3;
624         }
625         fbond *= gmx::invsqrt(dr2); /*   6              */
626         vtot  += vbond;             /* 1*/
627
628         if (g)
629         {
630             ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
631             ki = IVEC2IS(dt);
632         }
633         for (m = 0; (m < DIM); m++)     /*  15          */
634         {
635             fij                 = fbond*dx[m];
636             f[ai][m]           += fij;
637             f[aj][m]           -= fij;
638             fshift[ki][m]      += fij;
639             fshift[CENTRAL][m] -= fij;
640         }
641     }               /* 72 TOTAL */
642     return vtot;
643 }
644
645 real water_pol(int nbonds,
646                const t_iatom forceatoms[], const t_iparams forceparams[],
647                const rvec x[], rvec4 f[], rvec gmx_unused fshift[],
648                const t_pbc gmx_unused *pbc, const t_graph gmx_unused *g,
649                real gmx_unused lambda, real gmx_unused *dvdlambda,
650                const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
651                int gmx_unused *global_atom_index)
652 {
653     /* This routine implements anisotropic polarizibility for water, through
654      * a shell connected to a dummy with spring constant that differ in the
655      * three spatial dimensions in the molecular frame.
656      */
657     int  i, m, aO, aH1, aH2, aD, aS, type, type0, ki;
658     ivec dt;
659     rvec dOH1, dOH2, dHH, dOD, dDS, nW, kk, dx, kdx, proj;
660 #ifdef DEBUG
661     rvec df;
662 #endif
663     real vtot, fij, r_HH, r_OD, r_nW, tx, ty, tz, qS;
664
665     vtot = 0.0;
666     if (nbonds > 0)
667     {
668         type0  = forceatoms[0];
669         aS     = forceatoms[5];
670         qS     = md->chargeA[aS];
671         kk[XX] = gmx::square(qS)*ONE_4PI_EPS0/forceparams[type0].wpol.al_x;
672         kk[YY] = gmx::square(qS)*ONE_4PI_EPS0/forceparams[type0].wpol.al_y;
673         kk[ZZ] = gmx::square(qS)*ONE_4PI_EPS0/forceparams[type0].wpol.al_z;
674         r_HH   = 1.0/forceparams[type0].wpol.rHH;
675         if (debug)
676         {
677             fprintf(debug, "WPOL: qS  = %10.5f aS = %5d\n", qS, aS);
678             fprintf(debug, "WPOL: kk  = %10.3f        %10.3f        %10.3f\n",
679                     kk[XX], kk[YY], kk[ZZ]);
680             fprintf(debug, "WPOL: rOH = %10.3f  rHH = %10.3f  rOD = %10.3f\n",
681                     forceparams[type0].wpol.rOH,
682                     forceparams[type0].wpol.rHH,
683                     forceparams[type0].wpol.rOD);
684         }
685         for (i = 0; (i < nbonds); i += 6)
686         {
687             type = forceatoms[i];
688             if (type != type0)
689             {
690                 gmx_fatal(FARGS, "Sorry, type = %d, type0 = %d, file = %s, line = %d",
691                           type, type0, __FILE__, __LINE__);
692             }
693             aO   = forceatoms[i+1];
694             aH1  = forceatoms[i+2];
695             aH2  = forceatoms[i+3];
696             aD   = forceatoms[i+4];
697             aS   = forceatoms[i+5];
698
699             /* Compute vectors describing the water frame */
700             pbc_rvec_sub(pbc, x[aH1], x[aO], dOH1);
701             pbc_rvec_sub(pbc, x[aH2], x[aO], dOH2);
702             pbc_rvec_sub(pbc, x[aH2], x[aH1], dHH);
703             pbc_rvec_sub(pbc, x[aD], x[aO], dOD);
704             ki = pbc_rvec_sub(pbc, x[aS], x[aD], dDS);
705             cprod(dOH1, dOH2, nW);
706
707             /* Compute inverse length of normal vector
708              * (this one could be precomputed, but I'm too lazy now)
709              */
710             r_nW = gmx::invsqrt(iprod(nW, nW));
711             /* This is for precision, but does not make a big difference,
712              * it can go later.
713              */
714             r_OD = gmx::invsqrt(iprod(dOD, dOD));
715
716             /* Normalize the vectors in the water frame */
717             svmul(r_nW, nW, nW);
718             svmul(r_HH, dHH, dHH);
719             svmul(r_OD, dOD, dOD);
720
721             /* Compute displacement of shell along components of the vector */
722             dx[ZZ] = iprod(dDS, dOD);
723             /* Compute projection on the XY plane: dDS - dx[ZZ]*dOD */
724             for (m = 0; (m < DIM); m++)
725             {
726                 proj[m] = dDS[m]-dx[ZZ]*dOD[m];
727             }
728
729             /*dx[XX] = iprod(dDS,nW);
730                dx[YY] = iprod(dDS,dHH);*/
731             dx[XX] = iprod(proj, nW);
732             for (m = 0; (m < DIM); m++)
733             {
734                 proj[m] -= dx[XX]*nW[m];
735             }
736             dx[YY] = iprod(proj, dHH);
737             /*#define DEBUG*/
738 #ifdef DEBUG
739             if (debug)
740             {
741                 fprintf(debug, "WPOL: dx2=%10g  dy2=%10g  dz2=%10g  sum=%10g  dDS^2=%10g\n",
742                         gmx::square(dx[XX]), gmx::square(dx[YY]), gmx::square(dx[ZZ]), iprod(dx, dx), iprod(dDS, dDS));
743                 fprintf(debug, "WPOL: dHH=(%10g,%10g,%10g)\n", dHH[XX], dHH[YY], dHH[ZZ]);
744                 fprintf(debug, "WPOL: dOD=(%10g,%10g,%10g), 1/r_OD = %10g\n",
745                         dOD[XX], dOD[YY], dOD[ZZ], 1/r_OD);
746                 fprintf(debug, "WPOL: nW =(%10g,%10g,%10g), 1/r_nW = %10g\n",
747                         nW[XX], nW[YY], nW[ZZ], 1/r_nW);
748                 fprintf(debug, "WPOL: dx  =%10g, dy  =%10g, dz  =%10g\n",
749                         dx[XX], dx[YY], dx[ZZ]);
750                 fprintf(debug, "WPOL: dDSx=%10g, dDSy=%10g, dDSz=%10g\n",
751                         dDS[XX], dDS[YY], dDS[ZZ]);
752             }
753 #endif
754             /* Now compute the forces and energy */
755             kdx[XX] = kk[XX]*dx[XX];
756             kdx[YY] = kk[YY]*dx[YY];
757             kdx[ZZ] = kk[ZZ]*dx[ZZ];
758             vtot   += iprod(dx, kdx);
759
760             if (g)
761             {
762                 ivec_sub(SHIFT_IVEC(g, aS), SHIFT_IVEC(g, aD), dt);
763                 ki = IVEC2IS(dt);
764             }
765
766             for (m = 0; (m < DIM); m++)
767             {
768                 /* This is a tensor operation but written out for speed */
769                 tx        =  nW[m]*kdx[XX];
770                 ty        = dHH[m]*kdx[YY];
771                 tz        = dOD[m]*kdx[ZZ];
772                 fij       = -tx-ty-tz;
773 #ifdef DEBUG
774                 df[m] = fij;
775 #endif
776                 f[aS][m]           += fij;
777                 f[aD][m]           -= fij;
778                 fshift[ki][m]      += fij;
779                 fshift[CENTRAL][m] -= fij;
780             }
781 #ifdef DEBUG
782             if (debug)
783             {
784                 fprintf(debug, "WPOL: vwpol=%g\n", 0.5*iprod(dx, kdx));
785                 fprintf(debug, "WPOL: df = (%10g, %10g, %10g)\n", df[XX], df[YY], df[ZZ]);
786             }
787 #endif
788         }
789     }
790     return 0.5*vtot;
791 }
792
793 static real do_1_thole(const rvec xi, const rvec xj, rvec fi, rvec fj,
794                        const t_pbc *pbc, real qq,
795                        rvec fshift[], real afac)
796 {
797     rvec r12;
798     real r12sq, r12_1, r12bar, v0, v1, fscal, ebar, fff;
799     int  m, t;
800
801     t      = pbc_rvec_sub(pbc, xi, xj, r12);                      /*  3 */
802
803     r12sq  = iprod(r12, r12);                                     /*  5 */
804     r12_1  = gmx::invsqrt(r12sq);                                 /*  5 */
805     r12bar = afac/r12_1;                                          /*  5 */
806     v0     = qq*ONE_4PI_EPS0*r12_1;                               /*  2 */
807     ebar   = std::exp(-r12bar);                                   /*  5 */
808     v1     = (1-(1+0.5*r12bar)*ebar);                             /*  4 */
809     fscal  = ((v0*r12_1)*v1 - v0*0.5*afac*ebar*(r12bar+1))*r12_1; /* 9 */
810     if (debug)
811     {
812         fprintf(debug, "THOLE: v0 = %.3f v1 = %.3f r12= % .3f r12bar = %.3f fscal = %.3f  ebar = %.3f\n", v0, v1, 1/r12_1, r12bar, fscal, ebar);
813     }
814
815     for (m = 0; (m < DIM); m++)
816     {
817         fff                 = fscal*r12[m];
818         fi[m]              += fff;
819         fj[m]              -= fff;
820         fshift[t][m]       += fff;
821         fshift[CENTRAL][m] -= fff;
822     }             /* 15 */
823
824     return v0*v1; /* 1 */
825     /* 54 */
826 }
827
828 real thole_pol(int nbonds,
829                const t_iatom forceatoms[], const t_iparams forceparams[],
830                const rvec x[], rvec4 f[], rvec fshift[],
831                const t_pbc *pbc, const t_graph gmx_unused *g,
832                real gmx_unused lambda, real gmx_unused *dvdlambda,
833                const t_mdatoms *md, t_fcdata gmx_unused *fcd,
834                int gmx_unused *global_atom_index)
835 {
836     /* Interaction between two pairs of particles with opposite charge */
837     int        i, type, a1, da1, a2, da2;
838     real       q1, q2, qq, a, al1, al2, afac;
839     real       V             = 0;
840
841     for (i = 0; (i < nbonds); )
842     {
843         type  = forceatoms[i++];
844         a1    = forceatoms[i++];
845         da1   = forceatoms[i++];
846         a2    = forceatoms[i++];
847         da2   = forceatoms[i++];
848         q1    = md->chargeA[da1];
849         q2    = md->chargeA[da2];
850         a     = forceparams[type].thole.a;
851         al1   = forceparams[type].thole.alpha1;
852         al2   = forceparams[type].thole.alpha2;
853         qq    = q1*q2;
854         afac  = a*gmx::invsixthroot(al1*al2);
855         V    += do_1_thole(x[a1], x[a2], f[a1], f[a2], pbc, qq, fshift, afac);
856         V    += do_1_thole(x[da1], x[a2], f[da1], f[a2], pbc, -qq, fshift, afac);
857         V    += do_1_thole(x[a1], x[da2], f[a1], f[da2], pbc, -qq, fshift, afac);
858         V    += do_1_thole(x[da1], x[da2], f[da1], f[da2], pbc, qq, fshift, afac);
859     }
860     /* 290 flops */
861     return V;
862 }
863
864 real bond_angle(const rvec xi, const rvec xj, const rvec xk, const t_pbc *pbc,
865                 rvec r_ij, rvec r_kj, real *costh,
866                 int *t1, int *t2)
867 /* Return value is the angle between the bonds i-j and j-k */
868 {
869     /* 41 FLOPS */
870     real th;
871
872     *t1 = pbc_rvec_sub(pbc, xi, xj, r_ij); /*  3                */
873     *t2 = pbc_rvec_sub(pbc, xk, xj, r_kj); /*  3                */
874
875     *costh = cos_angle(r_ij, r_kj);        /* 25                */
876     th     = std::acos(*costh);            /* 10                */
877     /* 41 TOTAL */
878     return th;
879 }
880
881 real angles(int nbonds,
882             const t_iatom forceatoms[], const t_iparams forceparams[],
883             const rvec x[], rvec4 f[], rvec fshift[],
884             const t_pbc *pbc, const t_graph *g,
885             real lambda, real *dvdlambda,
886             const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
887             int gmx_unused *global_atom_index)
888 {
889     int  i, ai, aj, ak, t1, t2, type;
890     rvec r_ij, r_kj;
891     real cos_theta, cos_theta2, theta, dVdt, va, vtot;
892     ivec jt, dt_ij, dt_kj;
893
894     vtot = 0.0;
895     for (i = 0; i < nbonds; )
896     {
897         type = forceatoms[i++];
898         ai   = forceatoms[i++];
899         aj   = forceatoms[i++];
900         ak   = forceatoms[i++];
901
902         theta  = bond_angle(x[ai], x[aj], x[ak], pbc,
903                             r_ij, r_kj, &cos_theta, &t1, &t2);  /*  41          */
904
905         *dvdlambda += harmonic(forceparams[type].harmonic.krA,
906                                forceparams[type].harmonic.krB,
907                                forceparams[type].harmonic.rA*DEG2RAD,
908                                forceparams[type].harmonic.rB*DEG2RAD,
909                                theta, lambda, &va, &dVdt);  /*  21  */
910         vtot += va;
911
912         cos_theta2 = gmx::square(cos_theta);
913         if (cos_theta2 < 1)
914         {
915             int  m;
916             real st, sth;
917             real cik, cii, ckk;
918             real nrkj2, nrij2;
919             real nrkj_1, nrij_1;
920             rvec f_i, f_j, f_k;
921
922             st  = dVdt*gmx::invsqrt(1 - cos_theta2); /*  12             */
923             sth = st*cos_theta;                      /*   1             */
924 #ifdef DEBUG
925             if (debug)
926             {
927                 fprintf(debug, "ANGLES: theta = %10g  vth = %10g  dV/dtheta = %10g\n",
928                         theta*RAD2DEG, va, dVdt);
929             }
930 #endif
931             nrij2 = iprod(r_ij, r_ij);      /*   5              */
932             nrkj2 = iprod(r_kj, r_kj);      /*   5              */
933
934             nrij_1 = gmx::invsqrt(nrij2);   /*  10              */
935             nrkj_1 = gmx::invsqrt(nrkj2);   /*  10              */
936
937             cik = st*nrij_1*nrkj_1;         /*   2              */
938             cii = sth*nrij_1*nrij_1;        /*   2              */
939             ckk = sth*nrkj_1*nrkj_1;        /*   2              */
940
941             for (m = 0; m < DIM; m++)
942             {           /*  39          */
943                 f_i[m]    = -(cik*r_kj[m] - cii*r_ij[m]);
944                 f_k[m]    = -(cik*r_ij[m] - ckk*r_kj[m]);
945                 f_j[m]    = -f_i[m] - f_k[m];
946                 f[ai][m] += f_i[m];
947                 f[aj][m] += f_j[m];
948                 f[ak][m] += f_k[m];
949             }
950             if (g != nullptr)
951             {
952                 copy_ivec(SHIFT_IVEC(g, aj), jt);
953
954                 ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
955                 ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
956                 t1 = IVEC2IS(dt_ij);
957                 t2 = IVEC2IS(dt_kj);
958             }
959             rvec_inc(fshift[t1], f_i);
960             rvec_inc(fshift[CENTRAL], f_j);
961             rvec_inc(fshift[t2], f_k);
962         }                                           /* 161 TOTAL        */
963     }
964
965     return vtot;
966 }
967
968 #if GMX_SIMD_HAVE_REAL
969
970 /* As angles, but using SIMD to calculate many angles at once.
971  * This routines does not calculate energies and shift forces.
972  */
973 void
974 angles_noener_simd(int nbonds,
975                    const t_iatom forceatoms[], const t_iparams forceparams[],
976                    const rvec x[], rvec4 f[],
977                    const t_pbc *pbc, const t_graph gmx_unused *g,
978                    real gmx_unused lambda,
979                    const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
980                    int gmx_unused *global_atom_index)
981 {
982     const int            nfa1 = 4;
983     int                  i, iu, s;
984     int                  type;
985     GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH)    ai[GMX_SIMD_REAL_WIDTH];
986     GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH)    aj[GMX_SIMD_REAL_WIDTH];
987     GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH)    ak[GMX_SIMD_REAL_WIDTH];
988     GMX_ALIGNED(real, GMX_SIMD_REAL_WIDTH)   coeff[2*GMX_SIMD_REAL_WIDTH];
989     SimdReal             deg2rad_S(DEG2RAD);
990     SimdReal             xi_S, yi_S, zi_S;
991     SimdReal             xj_S, yj_S, zj_S;
992     SimdReal             xk_S, yk_S, zk_S;
993     SimdReal             k_S, theta0_S;
994     SimdReal             rijx_S, rijy_S, rijz_S;
995     SimdReal             rkjx_S, rkjy_S, rkjz_S;
996     SimdReal             one_S(1.0);
997     SimdReal             min_one_plus_eps_S(-1.0 + 2.0*GMX_REAL_EPS); // Smallest number > -1
998
999     SimdReal             rij_rkj_S;
1000     SimdReal             nrij2_S, nrij_1_S;
1001     SimdReal             nrkj2_S, nrkj_1_S;
1002     SimdReal             cos_S, invsin_S;
1003     SimdReal             theta_S;
1004     SimdReal             st_S, sth_S;
1005     SimdReal             cik_S, cii_S, ckk_S;
1006     SimdReal             f_ix_S, f_iy_S, f_iz_S;
1007     SimdReal             f_kx_S, f_ky_S, f_kz_S;
1008     GMX_ALIGNED(real, GMX_SIMD_REAL_WIDTH)    pbc_simd[9*GMX_SIMD_REAL_WIDTH];
1009
1010     set_pbc_simd(pbc, pbc_simd);
1011
1012     /* nbonds is the number of angles times nfa1, here we step GMX_SIMD_REAL_WIDTH angles */
1013     for (i = 0; (i < nbonds); i += GMX_SIMD_REAL_WIDTH*nfa1)
1014     {
1015         /* Collect atoms for GMX_SIMD_REAL_WIDTH angles.
1016          * iu indexes into forceatoms, we should not let iu go beyond nbonds.
1017          */
1018         iu = i;
1019         for (s = 0; s < GMX_SIMD_REAL_WIDTH; s++)
1020         {
1021             type  = forceatoms[iu];
1022             ai[s] = forceatoms[iu+1];
1023             aj[s] = forceatoms[iu+2];
1024             ak[s] = forceatoms[iu+3];
1025
1026             /* At the end fill the arrays with the last atoms and 0 params */
1027             if (i + s*nfa1 < nbonds)
1028             {
1029                 coeff[s]                     = forceparams[type].harmonic.krA;
1030                 coeff[GMX_SIMD_REAL_WIDTH+s] = forceparams[type].harmonic.rA;
1031
1032                 if (iu + nfa1 < nbonds)
1033                 {
1034                     iu += nfa1;
1035                 }
1036             }
1037             else
1038             {
1039                 coeff[s]                     = 0;
1040                 coeff[GMX_SIMD_REAL_WIDTH+s] = 0;
1041             }
1042         }
1043
1044         /* Store the non PBC corrected distances packed and aligned */
1045         gatherLoadUTranspose<3>(reinterpret_cast<const real *>(x), ai, &xi_S, &yi_S, &zi_S);
1046         gatherLoadUTranspose<3>(reinterpret_cast<const real *>(x), aj, &xj_S, &yj_S, &zj_S);
1047         gatherLoadUTranspose<3>(reinterpret_cast<const real *>(x), ak, &xk_S, &yk_S, &zk_S);
1048         rijx_S = xi_S - xj_S;
1049         rijy_S = yi_S - yj_S;
1050         rijz_S = zi_S - zj_S;
1051         rkjx_S = xk_S - xj_S;
1052         rkjy_S = yk_S - yj_S;
1053         rkjz_S = zk_S - zj_S;
1054
1055         k_S       = load(coeff);
1056         theta0_S  = load(coeff+GMX_SIMD_REAL_WIDTH) * deg2rad_S;
1057
1058         pbc_correct_dx_simd(&rijx_S, &rijy_S, &rijz_S, pbc_simd);
1059         pbc_correct_dx_simd(&rkjx_S, &rkjy_S, &rkjz_S, pbc_simd);
1060
1061         rij_rkj_S = iprod(rijx_S, rijy_S, rijz_S,
1062                           rkjx_S, rkjy_S, rkjz_S);
1063
1064         nrij2_S   = norm2(rijx_S, rijy_S, rijz_S);
1065         nrkj2_S   = norm2(rkjx_S, rkjy_S, rkjz_S);
1066
1067         nrij_1_S  = invsqrt(nrij2_S);
1068         nrkj_1_S  = invsqrt(nrkj2_S);
1069
1070         cos_S     = rij_rkj_S * nrij_1_S * nrkj_1_S;
1071
1072         /* To allow for 180 degrees, we take the max of cos and -1 + 1bit,
1073          * so we can safely get the 1/sin from 1/sqrt(1 - cos^2).
1074          * This also ensures that rounding errors would cause the argument
1075          * of simdAcos to be < -1.
1076          * Note that we do not take precautions for cos(0)=1, so the outer
1077          * atoms in an angle should not be on top of each other.
1078          */
1079         cos_S     = max(cos_S, min_one_plus_eps_S);
1080
1081         theta_S   = acos(cos_S);
1082
1083         invsin_S  = invsqrt( one_S - cos_S * cos_S );
1084
1085         st_S      = k_S * (theta0_S - theta_S) * invsin_S;
1086         sth_S     = st_S * cos_S;
1087
1088         cik_S     = st_S  * nrij_1_S * nrkj_1_S;
1089         cii_S     = sth_S * nrij_1_S * nrij_1_S;
1090         ckk_S     = sth_S * nrkj_1_S * nrkj_1_S;
1091
1092         f_ix_S    = cii_S * rijx_S;
1093         f_ix_S    = fnma(cik_S, rkjx_S, f_ix_S);
1094         f_iy_S    = cii_S * rijy_S;
1095         f_iy_S    = fnma(cik_S, rkjy_S, f_iy_S);
1096         f_iz_S    = cii_S * rijz_S;
1097         f_iz_S    = fnma(cik_S, rkjz_S, f_iz_S);
1098         f_kx_S    = ckk_S * rkjx_S;
1099         f_kx_S    = fnma(cik_S, rijx_S, f_kx_S);
1100         f_ky_S    = ckk_S * rkjy_S;
1101         f_ky_S    = fnma(cik_S, rijy_S, f_ky_S);
1102         f_kz_S    = ckk_S * rkjz_S;
1103         f_kz_S    = fnma(cik_S, rijz_S, f_kz_S);
1104
1105         transposeScatterIncrU<4>(reinterpret_cast<real *>(f), ai, f_ix_S, f_iy_S, f_iz_S);
1106         transposeScatterDecrU<4>(reinterpret_cast<real *>(f), aj, f_ix_S + f_kx_S, f_iy_S + f_ky_S, f_iz_S + f_kz_S);
1107         transposeScatterIncrU<4>(reinterpret_cast<real *>(f), ak, f_kx_S, f_ky_S, f_kz_S);
1108     }
1109 }
1110
1111 #endif // GMX_SIMD_HAVE_REAL
1112
1113 real linear_angles(int nbonds,
1114                    const t_iatom forceatoms[], const t_iparams forceparams[],
1115                    const rvec x[], rvec4 f[], rvec fshift[],
1116                    const t_pbc *pbc, const t_graph *g,
1117                    real lambda, real *dvdlambda,
1118                    const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
1119                    int gmx_unused *global_atom_index)
1120 {
1121     int  i, m, ai, aj, ak, t1, t2, type;
1122     rvec f_i, f_j, f_k;
1123     real L1, kA, kB, aA, aB, dr, dr2, va, vtot, a, b, klin;
1124     ivec jt, dt_ij, dt_kj;
1125     rvec r_ij, r_kj, r_ik, dx;
1126
1127     L1   = 1-lambda;
1128     vtot = 0.0;
1129     for (i = 0; (i < nbonds); )
1130     {
1131         type = forceatoms[i++];
1132         ai   = forceatoms[i++];
1133         aj   = forceatoms[i++];
1134         ak   = forceatoms[i++];
1135
1136         kA   = forceparams[type].linangle.klinA;
1137         kB   = forceparams[type].linangle.klinB;
1138         klin = L1*kA + lambda*kB;
1139
1140         aA   = forceparams[type].linangle.aA;
1141         aB   = forceparams[type].linangle.aB;
1142         a    = L1*aA+lambda*aB;
1143         b    = 1-a;
1144
1145         t1 = pbc_rvec_sub(pbc, x[ai], x[aj], r_ij);
1146         t2 = pbc_rvec_sub(pbc, x[ak], x[aj], r_kj);
1147         rvec_sub(r_ij, r_kj, r_ik);
1148
1149         dr2 = 0;
1150         for (m = 0; (m < DIM); m++)
1151         {
1152             dr        = -a * r_ij[m] - b * r_kj[m];
1153             dr2      += dr*dr;
1154             dx[m]     = dr;
1155             f_i[m]    = a*klin*dr;
1156             f_k[m]    = b*klin*dr;
1157             f_j[m]    = -(f_i[m]+f_k[m]);
1158             f[ai][m] += f_i[m];
1159             f[aj][m] += f_j[m];
1160             f[ak][m] += f_k[m];
1161         }
1162         va          = 0.5*klin*dr2;
1163         *dvdlambda += 0.5*(kB-kA)*dr2 + klin*(aB-aA)*iprod(dx, r_ik);
1164
1165         vtot += va;
1166
1167         if (g)
1168         {
1169             copy_ivec(SHIFT_IVEC(g, aj), jt);
1170
1171             ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
1172             ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
1173             t1 = IVEC2IS(dt_ij);
1174             t2 = IVEC2IS(dt_kj);
1175         }
1176         rvec_inc(fshift[t1], f_i);
1177         rvec_inc(fshift[CENTRAL], f_j);
1178         rvec_inc(fshift[t2], f_k);
1179     }                                         /* 57 TOTAL       */
1180     return vtot;
1181 }
1182
1183 real urey_bradley(int nbonds,
1184                   const t_iatom forceatoms[], const t_iparams forceparams[],
1185                   const rvec x[], rvec4 f[], rvec fshift[],
1186                   const t_pbc *pbc, const t_graph *g,
1187                   real lambda, real *dvdlambda,
1188                   const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
1189                   int gmx_unused *global_atom_index)
1190 {
1191     int  i, m, ai, aj, ak, t1, t2, type, ki;
1192     rvec r_ij, r_kj, r_ik;
1193     real cos_theta, cos_theta2, theta;
1194     real dVdt, va, vtot, dr, dr2, vbond, fbond, fik;
1195     real kthA, th0A, kUBA, r13A, kthB, th0B, kUBB, r13B;
1196     ivec jt, dt_ij, dt_kj, dt_ik;
1197
1198     vtot = 0.0;
1199     for (i = 0; (i < nbonds); )
1200     {
1201         type  = forceatoms[i++];
1202         ai    = forceatoms[i++];
1203         aj    = forceatoms[i++];
1204         ak    = forceatoms[i++];
1205         th0A  = forceparams[type].u_b.thetaA*DEG2RAD;
1206         kthA  = forceparams[type].u_b.kthetaA;
1207         r13A  = forceparams[type].u_b.r13A;
1208         kUBA  = forceparams[type].u_b.kUBA;
1209         th0B  = forceparams[type].u_b.thetaB*DEG2RAD;
1210         kthB  = forceparams[type].u_b.kthetaB;
1211         r13B  = forceparams[type].u_b.r13B;
1212         kUBB  = forceparams[type].u_b.kUBB;
1213
1214         theta  = bond_angle(x[ai], x[aj], x[ak], pbc,
1215                             r_ij, r_kj, &cos_theta, &t1, &t2);                     /*  41               */
1216
1217         *dvdlambda += harmonic(kthA, kthB, th0A, th0B, theta, lambda, &va, &dVdt); /*  21  */
1218         vtot       += va;
1219
1220         ki   = pbc_rvec_sub(pbc, x[ai], x[ak], r_ik);                               /*   3      */
1221         dr2  = iprod(r_ik, r_ik);                                                   /*   5              */
1222         dr   = dr2*gmx::invsqrt(dr2);                                               /*  10              */
1223
1224         *dvdlambda += harmonic(kUBA, kUBB, r13A, r13B, dr, lambda, &vbond, &fbond); /*  19  */
1225
1226         cos_theta2 = gmx::square(cos_theta);                                        /*   1              */
1227         if (cos_theta2 < 1)
1228         {
1229             real st, sth;
1230             real cik, cii, ckk;
1231             real nrkj2, nrij2;
1232             rvec f_i, f_j, f_k;
1233
1234             st  = dVdt*gmx::invsqrt(1 - cos_theta2); /*  12             */
1235             sth = st*cos_theta;                      /*   1             */
1236 #ifdef DEBUG
1237             if (debug)
1238             {
1239                 fprintf(debug, "ANGLES: theta = %10g  vth = %10g  dV/dtheta = %10g\n",
1240                         theta*RAD2DEG, va, dVdt);
1241             }
1242 #endif
1243             nrkj2 = iprod(r_kj, r_kj);  /*   5          */
1244             nrij2 = iprod(r_ij, r_ij);
1245
1246             cik = st*gmx::invsqrt(nrkj2*nrij2); /*  12          */
1247             cii = sth/nrij2;                    /*  10          */
1248             ckk = sth/nrkj2;                    /*  10          */
1249
1250             for (m = 0; (m < DIM); m++)         /*  39          */
1251             {
1252                 f_i[m]    = -(cik*r_kj[m]-cii*r_ij[m]);
1253                 f_k[m]    = -(cik*r_ij[m]-ckk*r_kj[m]);
1254                 f_j[m]    = -f_i[m]-f_k[m];
1255                 f[ai][m] += f_i[m];
1256                 f[aj][m] += f_j[m];
1257                 f[ak][m] += f_k[m];
1258             }
1259             if (g)
1260             {
1261                 copy_ivec(SHIFT_IVEC(g, aj), jt);
1262
1263                 ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
1264                 ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
1265                 t1 = IVEC2IS(dt_ij);
1266                 t2 = IVEC2IS(dt_kj);
1267             }
1268             rvec_inc(fshift[t1], f_i);
1269             rvec_inc(fshift[CENTRAL], f_j);
1270             rvec_inc(fshift[t2], f_k);
1271         }                                       /* 161 TOTAL    */
1272         /* Time for the bond calculations */
1273         if (dr2 == 0.0)
1274         {
1275             continue;
1276         }
1277
1278         vtot  += vbond;             /* 1*/
1279         fbond *= gmx::invsqrt(dr2); /*   6              */
1280
1281         if (g)
1282         {
1283             ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, ak), dt_ik);
1284             ki = IVEC2IS(dt_ik);
1285         }
1286         for (m = 0; (m < DIM); m++)     /*  15          */
1287         {
1288             fik                 = fbond*r_ik[m];
1289             f[ai][m]           += fik;
1290             f[ak][m]           -= fik;
1291             fshift[ki][m]      += fik;
1292             fshift[CENTRAL][m] -= fik;
1293         }
1294     }
1295     return vtot;
1296 }
1297
1298 real quartic_angles(int nbonds,
1299                     const t_iatom forceatoms[], const t_iparams forceparams[],
1300                     const rvec x[], rvec4 f[], rvec fshift[],
1301                     const t_pbc *pbc, const t_graph *g,
1302                     real gmx_unused lambda, real gmx_unused *dvdlambda,
1303                     const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
1304                     int gmx_unused *global_atom_index)
1305 {
1306     int  i, j, ai, aj, ak, t1, t2, type;
1307     rvec r_ij, r_kj;
1308     real cos_theta, cos_theta2, theta, dt, dVdt, va, dtp, c, vtot;
1309     ivec jt, dt_ij, dt_kj;
1310
1311     vtot = 0.0;
1312     for (i = 0; (i < nbonds); )
1313     {
1314         type = forceatoms[i++];
1315         ai   = forceatoms[i++];
1316         aj   = forceatoms[i++];
1317         ak   = forceatoms[i++];
1318
1319         theta  = bond_angle(x[ai], x[aj], x[ak], pbc,
1320                             r_ij, r_kj, &cos_theta, &t1, &t2); /*  41           */
1321
1322         dt = theta - forceparams[type].qangle.theta*DEG2RAD;   /* 2          */
1323
1324         dVdt = 0;
1325         va   = forceparams[type].qangle.c[0];
1326         dtp  = 1.0;
1327         for (j = 1; j <= 4; j++)
1328         {
1329             c     = forceparams[type].qangle.c[j];
1330             dVdt -= j*c*dtp;
1331             dtp  *= dt;
1332             va   += c*dtp;
1333         }
1334         /* 20 */
1335
1336         vtot += va;
1337
1338         cos_theta2 = gmx::square(cos_theta);            /*   1          */
1339         if (cos_theta2 < 1)
1340         {
1341             int  m;
1342             real st, sth;
1343             real cik, cii, ckk;
1344             real nrkj2, nrij2;
1345             rvec f_i, f_j, f_k;
1346
1347             st  = dVdt*gmx::invsqrt(1 - cos_theta2); /*  12             */
1348             sth = st*cos_theta;                      /*   1             */
1349 #ifdef DEBUG
1350             if (debug)
1351             {
1352                 fprintf(debug, "ANGLES: theta = %10g  vth = %10g  dV/dtheta = %10g\n",
1353                         theta*RAD2DEG, va, dVdt);
1354             }
1355 #endif
1356             nrkj2 = iprod(r_kj, r_kj);  /*   5          */
1357             nrij2 = iprod(r_ij, r_ij);
1358
1359             cik = st*gmx::invsqrt(nrkj2*nrij2); /*  12          */
1360             cii = sth/nrij2;                    /*  10          */
1361             ckk = sth/nrkj2;                    /*  10          */
1362
1363             for (m = 0; (m < DIM); m++)         /*  39          */
1364             {
1365                 f_i[m]    = -(cik*r_kj[m]-cii*r_ij[m]);
1366                 f_k[m]    = -(cik*r_ij[m]-ckk*r_kj[m]);
1367                 f_j[m]    = -f_i[m]-f_k[m];
1368                 f[ai][m] += f_i[m];
1369                 f[aj][m] += f_j[m];
1370                 f[ak][m] += f_k[m];
1371             }
1372             if (g)
1373             {
1374                 copy_ivec(SHIFT_IVEC(g, aj), jt);
1375
1376                 ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
1377                 ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
1378                 t1 = IVEC2IS(dt_ij);
1379                 t2 = IVEC2IS(dt_kj);
1380             }
1381             rvec_inc(fshift[t1], f_i);
1382             rvec_inc(fshift[CENTRAL], f_j);
1383             rvec_inc(fshift[t2], f_k);
1384         }                                       /* 153 TOTAL    */
1385     }
1386     return vtot;
1387 }
1388
1389 real dih_angle(const rvec xi, const rvec xj, const rvec xk, const rvec xl,
1390                const t_pbc *pbc,
1391                rvec r_ij, rvec r_kj, rvec r_kl, rvec m, rvec n,
1392                real *sign, int *t1, int *t2, int *t3)
1393 {
1394     real ipr, phi;
1395
1396     *t1 = pbc_rvec_sub(pbc, xi, xj, r_ij); /*  3        */
1397     *t2 = pbc_rvec_sub(pbc, xk, xj, r_kj); /*  3                */
1398     *t3 = pbc_rvec_sub(pbc, xk, xl, r_kl); /*  3                */
1399
1400     cprod(r_ij, r_kj, m);                  /*  9        */
1401     cprod(r_kj, r_kl, n);                  /*  9                */
1402     phi     = gmx_angle(m, n);             /* 49 (assuming 25 for atan2) */
1403     ipr     = iprod(r_ij, n);              /*  5        */
1404     (*sign) = (ipr < 0.0) ? -1.0 : 1.0;
1405     phi     = (*sign)*phi;                 /*  1                */
1406     /* 82 TOTAL */
1407     return phi;
1408 }
1409
1410
1411 #if GMX_SIMD_HAVE_REAL
1412
1413 /* As dih_angle above, but calculates 4 dihedral angles at once using SIMD,
1414  * also calculates the pre-factor required for the dihedral force update.
1415  * Note that bv and buf should be register aligned.
1416  */
1417 static gmx_inline void
1418 dih_angle_simd(const rvec *x,
1419                const int *ai, const int *aj, const int *ak, const int *al,
1420                const real *pbc_simd,
1421                SimdReal *phi_S,
1422                SimdReal *mx_S, SimdReal *my_S, SimdReal *mz_S,
1423                SimdReal *nx_S, SimdReal *ny_S, SimdReal *nz_S,
1424                SimdReal *nrkj_m2_S,
1425                SimdReal *nrkj_n2_S,
1426                SimdReal *p_S,
1427                SimdReal *q_S)
1428 {
1429     SimdReal xi_S, yi_S, zi_S;
1430     SimdReal xj_S, yj_S, zj_S;
1431     SimdReal xk_S, yk_S, zk_S;
1432     SimdReal xl_S, yl_S, zl_S;
1433     SimdReal rijx_S, rijy_S, rijz_S;
1434     SimdReal rkjx_S, rkjy_S, rkjz_S;
1435     SimdReal rklx_S, rkly_S, rklz_S;
1436     SimdReal cx_S, cy_S, cz_S;
1437     SimdReal cn_S;
1438     SimdReal s_S;
1439     SimdReal ipr_S;
1440     SimdReal iprm_S, iprn_S;
1441     SimdReal nrkj2_S, nrkj_1_S, nrkj_2_S, nrkj_S;
1442     SimdReal toler_S;
1443     SimdReal nrkj2_min_S;
1444     SimdReal real_eps_S;
1445
1446     /* Used to avoid division by zero.
1447      * We take into acount that we multiply the result by real_eps_S.
1448      */
1449     nrkj2_min_S = SimdReal(GMX_REAL_MIN/(2*GMX_REAL_EPS));
1450
1451     /* The value of the last significant bit (GMX_REAL_EPS is half of that) */
1452     real_eps_S  = SimdReal(2*GMX_REAL_EPS);
1453
1454     /* Store the non PBC corrected distances packed and aligned */
1455     gatherLoadUTranspose<3>(reinterpret_cast<const real *>(x), ai, &xi_S, &yi_S, &zi_S);
1456     gatherLoadUTranspose<3>(reinterpret_cast<const real *>(x), aj, &xj_S, &yj_S, &zj_S);
1457     gatherLoadUTranspose<3>(reinterpret_cast<const real *>(x), ak, &xk_S, &yk_S, &zk_S);
1458     gatherLoadUTranspose<3>(reinterpret_cast<const real *>(x), al, &xl_S, &yl_S, &zl_S);
1459     rijx_S = xi_S - xj_S;
1460     rijy_S = yi_S - yj_S;
1461     rijz_S = zi_S - zj_S;
1462     rkjx_S = xk_S - xj_S;
1463     rkjy_S = yk_S - yj_S;
1464     rkjz_S = zk_S - zj_S;
1465     rklx_S = xk_S - xl_S;
1466     rkly_S = yk_S - yl_S;
1467     rklz_S = zk_S - zl_S;
1468
1469     pbc_correct_dx_simd(&rijx_S, &rijy_S, &rijz_S, pbc_simd);
1470     pbc_correct_dx_simd(&rkjx_S, &rkjy_S, &rkjz_S, pbc_simd);
1471     pbc_correct_dx_simd(&rklx_S, &rkly_S, &rklz_S, pbc_simd);
1472
1473     cprod(rijx_S, rijy_S, rijz_S,
1474           rkjx_S, rkjy_S, rkjz_S,
1475           mx_S, my_S, mz_S);
1476
1477     cprod(rkjx_S, rkjy_S, rkjz_S,
1478           rklx_S, rkly_S, rklz_S,
1479           nx_S, ny_S, nz_S);
1480
1481     cprod(*mx_S, *my_S, *mz_S,
1482           *nx_S, *ny_S, *nz_S,
1483           &cx_S, &cy_S, &cz_S);
1484
1485     cn_S       = sqrt(norm2(cx_S, cy_S, cz_S));
1486
1487     s_S        = iprod(*mx_S, *my_S, *mz_S, *nx_S, *ny_S, *nz_S);
1488
1489     /* Determine the dihedral angle, the sign might need correction */
1490     *phi_S     = atan2(cn_S, s_S);
1491
1492     ipr_S      = iprod(rijx_S, rijy_S, rijz_S,
1493                        *nx_S, *ny_S, *nz_S);
1494
1495     iprm_S     = norm2(*mx_S, *my_S, *mz_S);
1496     iprn_S     = norm2(*nx_S, *ny_S, *nz_S);
1497
1498     nrkj2_S    = norm2(rkjx_S, rkjy_S, rkjz_S);
1499
1500     /* Avoid division by zero. When zero, the result is multiplied by 0
1501      * anyhow, so the 3 max below do not affect the final result.
1502      */
1503     nrkj2_S    = max(nrkj2_S, nrkj2_min_S);
1504     nrkj_1_S   = invsqrt(nrkj2_S);
1505     nrkj_2_S   = nrkj_1_S * nrkj_1_S;
1506     nrkj_S     = nrkj2_S * nrkj_1_S;
1507
1508     toler_S    = nrkj2_S * real_eps_S;
1509
1510     /* Here the plain-C code uses a conditional, but we can't do that in SIMD.
1511      * So we take a max with the tolerance instead. Since we multiply with
1512      * m or n later, the max does not affect the results.
1513      */
1514     iprm_S     = max(iprm_S, toler_S);
1515     iprn_S     = max(iprn_S, toler_S);
1516     *nrkj_m2_S = nrkj_S * inv(iprm_S);
1517     *nrkj_n2_S = nrkj_S * inv(iprn_S);
1518
1519     /* Set sign of phi_S with the sign of ipr_S; phi_S is currently positive */
1520     *phi_S     = copysign(*phi_S, ipr_S);
1521     *p_S       = iprod(rijx_S, rijy_S, rijz_S, rkjx_S, rkjy_S, rkjz_S);
1522     *p_S       = *p_S * nrkj_2_S;
1523
1524     *q_S       = iprod(rklx_S, rkly_S, rklz_S, rkjx_S, rkjy_S, rkjz_S);
1525     *q_S       = *q_S * nrkj_2_S;
1526 }
1527
1528 #endif // GMX_SIMD_HAVE_REAL
1529
1530 void do_dih_fup(int i, int j, int k, int l, real ddphi,
1531                 rvec r_ij, rvec r_kj, rvec r_kl,
1532                 rvec m, rvec n, rvec4 f[], rvec fshift[],
1533                 const t_pbc *pbc, const t_graph *g,
1534                 const rvec x[], int t1, int t2, int t3)
1535 {
1536     /* 143 FLOPS */
1537     rvec f_i, f_j, f_k, f_l;
1538     rvec uvec, vvec, svec, dx_jl;
1539     real iprm, iprn, nrkj, nrkj2, nrkj_1, nrkj_2;
1540     real a, b, p, q, toler;
1541     ivec jt, dt_ij, dt_kj, dt_lj;
1542
1543     iprm  = iprod(m, m);       /*  5    */
1544     iprn  = iprod(n, n);       /*  5    */
1545     nrkj2 = iprod(r_kj, r_kj); /*  5    */
1546     toler = nrkj2*GMX_REAL_EPS;
1547     if ((iprm > toler) && (iprn > toler))
1548     {
1549         nrkj_1 = gmx::invsqrt(nrkj2); /* 10     */
1550         nrkj_2 = nrkj_1*nrkj_1;       /*  1     */
1551         nrkj   = nrkj2*nrkj_1;        /*  1     */
1552         a      = -ddphi*nrkj/iprm;    /* 11     */
1553         svmul(a, m, f_i);             /*  3     */
1554         b     = ddphi*nrkj/iprn;      /* 11     */
1555         svmul(b, n, f_l);             /*  3  */
1556         p     = iprod(r_ij, r_kj);    /*  5     */
1557         p    *= nrkj_2;               /*  1     */
1558         q     = iprod(r_kl, r_kj);    /*  5     */
1559         q    *= nrkj_2;               /*  1     */
1560         svmul(p, f_i, uvec);          /*  3     */
1561         svmul(q, f_l, vvec);          /*  3     */
1562         rvec_sub(uvec, vvec, svec);   /*  3     */
1563         rvec_sub(f_i, svec, f_j);     /*  3     */
1564         rvec_add(f_l, svec, f_k);     /*  3     */
1565         rvec_inc(f[i], f_i);          /*  3     */
1566         rvec_dec(f[j], f_j);          /*  3     */
1567         rvec_dec(f[k], f_k);          /*  3     */
1568         rvec_inc(f[l], f_l);          /*  3     */
1569
1570         if (g)
1571         {
1572             copy_ivec(SHIFT_IVEC(g, j), jt);
1573             ivec_sub(SHIFT_IVEC(g, i), jt, dt_ij);
1574             ivec_sub(SHIFT_IVEC(g, k), jt, dt_kj);
1575             ivec_sub(SHIFT_IVEC(g, l), jt, dt_lj);
1576             t1 = IVEC2IS(dt_ij);
1577             t2 = IVEC2IS(dt_kj);
1578             t3 = IVEC2IS(dt_lj);
1579         }
1580         else if (pbc)
1581         {
1582             t3 = pbc_rvec_sub(pbc, x[l], x[j], dx_jl);
1583         }
1584         else
1585         {
1586             t3 = CENTRAL;
1587         }
1588
1589         rvec_inc(fshift[t1], f_i);
1590         rvec_dec(fshift[CENTRAL], f_j);
1591         rvec_dec(fshift[t2], f_k);
1592         rvec_inc(fshift[t3], f_l);
1593     }
1594     /* 112 TOTAL    */
1595 }
1596
1597 /* As do_dih_fup above, but without shift forces */
1598 static void
1599 do_dih_fup_noshiftf(int i, int j, int k, int l, real ddphi,
1600                     rvec r_ij, rvec r_kj, rvec r_kl,
1601                     rvec m, rvec n, rvec4 f[])
1602 {
1603     rvec f_i, f_j, f_k, f_l;
1604     rvec uvec, vvec, svec;
1605     real iprm, iprn, nrkj, nrkj2, nrkj_1, nrkj_2;
1606     real a, b, p, q, toler;
1607
1608     iprm  = iprod(m, m);       /*  5    */
1609     iprn  = iprod(n, n);       /*  5    */
1610     nrkj2 = iprod(r_kj, r_kj); /*  5    */
1611     toler = nrkj2*GMX_REAL_EPS;
1612     if ((iprm > toler) && (iprn > toler))
1613     {
1614         nrkj_1 = gmx::invsqrt(nrkj2); /* 10     */
1615         nrkj_2 = nrkj_1*nrkj_1;       /*  1     */
1616         nrkj   = nrkj2*nrkj_1;        /*  1     */
1617         a      = -ddphi*nrkj/iprm;    /* 11     */
1618         svmul(a, m, f_i);             /*  3     */
1619         b     = ddphi*nrkj/iprn;      /* 11     */
1620         svmul(b, n, f_l);             /*  3  */
1621         p     = iprod(r_ij, r_kj);    /*  5     */
1622         p    *= nrkj_2;               /*  1     */
1623         q     = iprod(r_kl, r_kj);    /*  5     */
1624         q    *= nrkj_2;               /*  1     */
1625         svmul(p, f_i, uvec);          /*  3     */
1626         svmul(q, f_l, vvec);          /*  3     */
1627         rvec_sub(uvec, vvec, svec);   /*  3     */
1628         rvec_sub(f_i, svec, f_j);     /*  3     */
1629         rvec_add(f_l, svec, f_k);     /*  3     */
1630         rvec_inc(f[i], f_i);          /*  3     */
1631         rvec_dec(f[j], f_j);          /*  3     */
1632         rvec_dec(f[k], f_k);          /*  3     */
1633         rvec_inc(f[l], f_l);          /*  3     */
1634     }
1635 }
1636
1637 #if GMX_SIMD_HAVE_REAL
1638 /* As do_dih_fup_noshiftf above, but with SIMD and pre-calculated pre-factors */
1639 static gmx_inline void gmx_simdcall
1640 do_dih_fup_noshiftf_simd(const int *ai, const int *aj, const int *ak, const int *al,
1641                          SimdReal p, SimdReal q,
1642                          SimdReal f_i_x,  SimdReal f_i_y,  SimdReal f_i_z,
1643                          SimdReal mf_l_x, SimdReal mf_l_y, SimdReal mf_l_z,
1644                          rvec4 f[])
1645 {
1646     SimdReal sx    = p * f_i_x + q * mf_l_x;
1647     SimdReal sy    = p * f_i_y + q * mf_l_y;
1648     SimdReal sz    = p * f_i_z + q * mf_l_z;
1649     SimdReal f_j_x = f_i_x - sx;
1650     SimdReal f_j_y = f_i_y - sy;
1651     SimdReal f_j_z = f_i_z - sz;
1652     SimdReal f_k_x = mf_l_x - sx;
1653     SimdReal f_k_y = mf_l_y - sy;
1654     SimdReal f_k_z = mf_l_z - sz;
1655     transposeScatterIncrU<4>(reinterpret_cast<real *>(f), ai, f_i_x, f_i_y, f_i_z);
1656     transposeScatterDecrU<4>(reinterpret_cast<real *>(f), aj, f_j_x, f_j_y, f_j_z);
1657     transposeScatterIncrU<4>(reinterpret_cast<real *>(f), ak, f_k_x, f_k_y, f_k_z);
1658     transposeScatterDecrU<4>(reinterpret_cast<real *>(f), al, mf_l_x, mf_l_y, mf_l_z);
1659 }
1660 #endif // GMX_SIMD_HAVE_REAL
1661
1662 static real dopdihs(real cpA, real cpB, real phiA, real phiB, int mult,
1663                     real phi, real lambda, real *V, real *F)
1664 {
1665     real v, dvdlambda, mdphi, v1, sdphi, ddphi;
1666     real L1   = 1.0 - lambda;
1667     real ph0  = (L1*phiA + lambda*phiB)*DEG2RAD;
1668     real dph0 = (phiB - phiA)*DEG2RAD;
1669     real cp   = L1*cpA + lambda*cpB;
1670
1671     mdphi =  mult*phi - ph0;
1672     sdphi = std::sin(mdphi);
1673     ddphi = -cp*mult*sdphi;
1674     v1    = 1.0 + std::cos(mdphi);
1675     v     = cp*v1;
1676
1677     dvdlambda  = (cpB - cpA)*v1 + cp*dph0*sdphi;
1678
1679     *V = v;
1680     *F = ddphi;
1681
1682     return dvdlambda;
1683
1684     /* That was 40 flops */
1685 }
1686
1687 static void
1688 dopdihs_noener(real cpA, real cpB, real phiA, real phiB, int mult,
1689                real phi, real lambda, real *F)
1690 {
1691     real mdphi, sdphi, ddphi;
1692     real L1   = 1.0 - lambda;
1693     real ph0  = (L1*phiA + lambda*phiB)*DEG2RAD;
1694     real cp   = L1*cpA + lambda*cpB;
1695
1696     mdphi = mult*phi - ph0;
1697     sdphi = std::sin(mdphi);
1698     ddphi = -cp*mult*sdphi;
1699
1700     *F = ddphi;
1701
1702     /* That was 20 flops */
1703 }
1704
1705 static real dopdihs_min(real cpA, real cpB, real phiA, real phiB, int mult,
1706                         real phi, real lambda, real *V, real *F)
1707 /* similar to dopdihs, except for a minus sign  *
1708  * and a different treatment of mult/phi0       */
1709 {
1710     real v, dvdlambda, mdphi, v1, sdphi, ddphi;
1711     real L1   = 1.0 - lambda;
1712     real ph0  = (L1*phiA + lambda*phiB)*DEG2RAD;
1713     real dph0 = (phiB - phiA)*DEG2RAD;
1714     real cp   = L1*cpA + lambda*cpB;
1715
1716     mdphi = mult*(phi-ph0);
1717     sdphi = std::sin(mdphi);
1718     ddphi = cp*mult*sdphi;
1719     v1    = 1.0-std::cos(mdphi);
1720     v     = cp*v1;
1721
1722     dvdlambda  = (cpB-cpA)*v1 + cp*dph0*sdphi;
1723
1724     *V = v;
1725     *F = ddphi;
1726
1727     return dvdlambda;
1728
1729     /* That was 40 flops */
1730 }
1731
1732 real pdihs(int nbonds,
1733            const t_iatom forceatoms[], const t_iparams forceparams[],
1734            const rvec x[], rvec4 f[], rvec fshift[],
1735            const t_pbc *pbc, const t_graph *g,
1736            real lambda, real *dvdlambda,
1737            const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
1738            int gmx_unused *global_atom_index)
1739 {
1740     int  i, type, ai, aj, ak, al;
1741     int  t1, t2, t3;
1742     rvec r_ij, r_kj, r_kl, m, n;
1743     real phi, sign, ddphi, vpd, vtot;
1744
1745     vtot = 0.0;
1746
1747     for (i = 0; (i < nbonds); )
1748     {
1749         type = forceatoms[i++];
1750         ai   = forceatoms[i++];
1751         aj   = forceatoms[i++];
1752         ak   = forceatoms[i++];
1753         al   = forceatoms[i++];
1754
1755         phi = dih_angle(x[ai], x[aj], x[ak], x[al], pbc, r_ij, r_kj, r_kl, m, n,
1756                         &sign, &t1, &t2, &t3);  /*  84      */
1757         *dvdlambda += dopdihs(forceparams[type].pdihs.cpA,
1758                               forceparams[type].pdihs.cpB,
1759                               forceparams[type].pdihs.phiA,
1760                               forceparams[type].pdihs.phiB,
1761                               forceparams[type].pdihs.mult,
1762                               phi, lambda, &vpd, &ddphi);
1763
1764         vtot += vpd;
1765         do_dih_fup(ai, aj, ak, al, ddphi, r_ij, r_kj, r_kl, m, n,
1766                    f, fshift, pbc, g, x, t1, t2, t3); /* 112            */
1767
1768 #ifdef DEBUG
1769         fprintf(debug, "pdih: (%d,%d,%d,%d) phi=%g\n",
1770                 ai, aj, ak, al, phi);
1771 #endif
1772     } /* 223 TOTAL  */
1773
1774     return vtot;
1775 }
1776
1777 void make_dp_periodic(real *dp)  /* 1 flop? */
1778 {
1779     /* dp cannot be outside (-pi,pi) */
1780     if (*dp >= M_PI)
1781     {
1782         *dp -= 2*M_PI;
1783     }
1784     else if (*dp < -M_PI)
1785     {
1786         *dp += 2*M_PI;
1787     }
1788     return;
1789 }
1790
1791 /* As pdihs above, but without calculating energies and shift forces */
1792 void
1793 pdihs_noener(int nbonds,
1794              const t_iatom forceatoms[], const t_iparams forceparams[],
1795              const rvec x[], rvec4 f[],
1796              const t_pbc gmx_unused *pbc, const t_graph gmx_unused *g,
1797              real lambda,
1798              const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
1799              int gmx_unused *global_atom_index)
1800 {
1801     int  i, type, ai, aj, ak, al;
1802     int  t1, t2, t3;
1803     rvec r_ij, r_kj, r_kl, m, n;
1804     real phi, sign, ddphi_tot, ddphi;
1805
1806     for (i = 0; (i < nbonds); )
1807     {
1808         ai   = forceatoms[i+1];
1809         aj   = forceatoms[i+2];
1810         ak   = forceatoms[i+3];
1811         al   = forceatoms[i+4];
1812
1813         phi = dih_angle(x[ai], x[aj], x[ak], x[al], pbc, r_ij, r_kj, r_kl, m, n,
1814                         &sign, &t1, &t2, &t3);
1815
1816         ddphi_tot = 0;
1817
1818         /* Loop over dihedrals working on the same atoms,
1819          * so we avoid recalculating angles and force distributions.
1820          */
1821         do
1822         {
1823             type = forceatoms[i];
1824             dopdihs_noener(forceparams[type].pdihs.cpA,
1825                            forceparams[type].pdihs.cpB,
1826                            forceparams[type].pdihs.phiA,
1827                            forceparams[type].pdihs.phiB,
1828                            forceparams[type].pdihs.mult,
1829                            phi, lambda, &ddphi);
1830             ddphi_tot += ddphi;
1831
1832             i += 5;
1833         }
1834         while (i < nbonds &&
1835                forceatoms[i+1] == ai &&
1836                forceatoms[i+2] == aj &&
1837                forceatoms[i+3] == ak &&
1838                forceatoms[i+4] == al);
1839
1840         do_dih_fup_noshiftf(ai, aj, ak, al, ddphi_tot, r_ij, r_kj, r_kl, m, n, f);
1841     }
1842 }
1843
1844
1845 #if GMX_SIMD_HAVE_REAL
1846
1847 /* As pdihs_noner above, but using SIMD to calculate many dihedrals at once */
1848 void
1849 pdihs_noener_simd(int nbonds,
1850                   const t_iatom forceatoms[], const t_iparams forceparams[],
1851                   const rvec x[], rvec4 f[],
1852                   const t_pbc *pbc, const t_graph gmx_unused *g,
1853                   real gmx_unused lambda,
1854                   const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
1855                   int gmx_unused *global_atom_index)
1856 {
1857     const int             nfa1 = 5;
1858     int                   i, iu, s;
1859     int                   type;
1860     GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH)    ai[GMX_SIMD_REAL_WIDTH];
1861     GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH)    aj[GMX_SIMD_REAL_WIDTH];
1862     GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH)    ak[GMX_SIMD_REAL_WIDTH];
1863     GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH)    al[GMX_SIMD_REAL_WIDTH];
1864     GMX_ALIGNED(real, GMX_SIMD_REAL_WIDTH)  buf[3*GMX_SIMD_REAL_WIDTH];
1865     real                 *cp, *phi0, *mult;
1866     SimdReal              deg2rad_S(DEG2RAD);
1867     SimdReal              p_S, q_S;
1868     SimdReal              phi0_S, phi_S;
1869     SimdReal              mx_S, my_S, mz_S;
1870     SimdReal              nx_S, ny_S, nz_S;
1871     SimdReal              nrkj_m2_S, nrkj_n2_S;
1872     SimdReal              cp_S, mdphi_S, mult_S;
1873     SimdReal              sin_S, cos_S;
1874     SimdReal              mddphi_S;
1875     SimdReal              sf_i_S, msf_l_S;
1876     GMX_ALIGNED(real, GMX_SIMD_REAL_WIDTH)    pbc_simd[9*GMX_SIMD_REAL_WIDTH];
1877
1878     /* Extract aligned pointer for parameters and variables */
1879     cp    = buf + 0*GMX_SIMD_REAL_WIDTH;
1880     phi0  = buf + 1*GMX_SIMD_REAL_WIDTH;
1881     mult  = buf + 2*GMX_SIMD_REAL_WIDTH;
1882
1883     set_pbc_simd(pbc, pbc_simd);
1884
1885     /* nbonds is the number of dihedrals times nfa1, here we step GMX_SIMD_REAL_WIDTH dihs */
1886     for (i = 0; (i < nbonds); i += GMX_SIMD_REAL_WIDTH*nfa1)
1887     {
1888         /* Collect atoms quadruplets for GMX_SIMD_REAL_WIDTH dihedrals.
1889          * iu indexes into forceatoms, we should not let iu go beyond nbonds.
1890          */
1891         iu = i;
1892         for (s = 0; s < GMX_SIMD_REAL_WIDTH; s++)
1893         {
1894             type  = forceatoms[iu];
1895             ai[s] = forceatoms[iu+1];
1896             aj[s] = forceatoms[iu+2];
1897             ak[s] = forceatoms[iu+3];
1898             al[s] = forceatoms[iu+4];
1899
1900             /* At the end fill the arrays with the last atoms and 0 params */
1901             if (i + s*nfa1 < nbonds)
1902             {
1903                 cp[s]   = forceparams[type].pdihs.cpA;
1904                 phi0[s] = forceparams[type].pdihs.phiA;
1905                 mult[s] = forceparams[type].pdihs.mult;
1906
1907                 if (iu + nfa1 < nbonds)
1908                 {
1909                     iu += nfa1;
1910                 }
1911             }
1912             else
1913             {
1914                 cp[s]   = 0;
1915                 phi0[s] = 0;
1916                 mult[s] = 0;
1917             }
1918         }
1919
1920         /* Caclulate GMX_SIMD_REAL_WIDTH dihedral angles at once */
1921         dih_angle_simd(x, ai, aj, ak, al, pbc_simd,
1922                        &phi_S,
1923                        &mx_S, &my_S, &mz_S,
1924                        &nx_S, &ny_S, &nz_S,
1925                        &nrkj_m2_S,
1926                        &nrkj_n2_S,
1927                        &p_S, &q_S);
1928
1929         cp_S     = load(cp);
1930         phi0_S   = load(phi0) * deg2rad_S;
1931         mult_S   = load(mult);
1932
1933         mdphi_S  = fms(mult_S, phi_S, phi0_S);
1934
1935         /* Calculate GMX_SIMD_REAL_WIDTH sines at once */
1936         sincos(mdphi_S, &sin_S, &cos_S);
1937         mddphi_S = cp_S * mult_S * sin_S;
1938         sf_i_S   = mddphi_S * nrkj_m2_S;
1939         msf_l_S  = mddphi_S * nrkj_n2_S;
1940
1941         /* After this m?_S will contain f[i] */
1942         mx_S     = sf_i_S * mx_S;
1943         my_S     = sf_i_S * my_S;
1944         mz_S     = sf_i_S * mz_S;
1945
1946         /* After this m?_S will contain -f[l] */
1947         nx_S     = msf_l_S * nx_S;
1948         ny_S     = msf_l_S * ny_S;
1949         nz_S     = msf_l_S * nz_S;
1950
1951         do_dih_fup_noshiftf_simd(ai, aj, ak, al,
1952                                  p_S, q_S,
1953                                  mx_S, my_S, mz_S,
1954                                  nx_S, ny_S, nz_S,
1955                                  f);
1956     }
1957 }
1958
1959 /* This is mostly a copy of pdihs_noener_simd above, but with using
1960  * the RB potential instead of a harmonic potential.
1961  * This function can replace rbdihs() when no energy and virial are needed.
1962  */
1963 void
1964 rbdihs_noener_simd(int nbonds,
1965                    const t_iatom forceatoms[], const t_iparams forceparams[],
1966                    const rvec x[], rvec4 f[],
1967                    const t_pbc *pbc, const t_graph gmx_unused *g,
1968                    real gmx_unused lambda,
1969                    const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
1970                    int gmx_unused *global_atom_index)
1971 {
1972     const int             nfa1 = 5;
1973     int                   i, iu, s, j;
1974     int                   type;
1975     GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH)    ai[GMX_SIMD_REAL_WIDTH];
1976     GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH)    aj[GMX_SIMD_REAL_WIDTH];
1977     GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH)    ak[GMX_SIMD_REAL_WIDTH];
1978     GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH)    al[GMX_SIMD_REAL_WIDTH];
1979     GMX_ALIGNED(real, GMX_SIMD_REAL_WIDTH) parm[NR_RBDIHS*GMX_SIMD_REAL_WIDTH];
1980
1981     SimdReal              p_S, q_S;
1982     SimdReal              phi_S;
1983     SimdReal              ddphi_S, cosfac_S;
1984     SimdReal              mx_S, my_S, mz_S;
1985     SimdReal              nx_S, ny_S, nz_S;
1986     SimdReal              nrkj_m2_S, nrkj_n2_S;
1987     SimdReal              parm_S, c_S;
1988     SimdReal              sin_S, cos_S;
1989     SimdReal              sf_i_S, msf_l_S;
1990     GMX_ALIGNED(real, GMX_SIMD_REAL_WIDTH)    pbc_simd[9*GMX_SIMD_REAL_WIDTH];
1991
1992     SimdReal              pi_S(M_PI);
1993     SimdReal              one_S(1.0);
1994
1995     set_pbc_simd(pbc, pbc_simd);
1996
1997     /* nbonds is the number of dihedrals times nfa1, here we step GMX_SIMD_REAL_WIDTH dihs */
1998     for (i = 0; (i < nbonds); i += GMX_SIMD_REAL_WIDTH*nfa1)
1999     {
2000         /* Collect atoms quadruplets for GMX_SIMD_REAL_WIDTH dihedrals.
2001          * iu indexes into forceatoms, we should not let iu go beyond nbonds.
2002          */
2003         iu = i;
2004         for (s = 0; s < GMX_SIMD_REAL_WIDTH; s++)
2005         {
2006             type  = forceatoms[iu];
2007             ai[s] = forceatoms[iu+1];
2008             aj[s] = forceatoms[iu+2];
2009             ak[s] = forceatoms[iu+3];
2010             al[s] = forceatoms[iu+4];
2011
2012             /* At the end fill the arrays with the last atoms and 0 params */
2013             if (i + s*nfa1 < nbonds)
2014             {
2015                 /* We don't need the first parameter, since that's a constant
2016                  * which only affects the energies, not the forces.
2017                  */
2018                 for (j = 1; j < NR_RBDIHS; j++)
2019                 {
2020                     parm[j*GMX_SIMD_REAL_WIDTH + s] =
2021                         forceparams[type].rbdihs.rbcA[j];
2022                 }
2023
2024                 if (iu + nfa1 < nbonds)
2025                 {
2026                     iu += nfa1;
2027                 }
2028             }
2029             else
2030             {
2031                 for (j = 1; j < NR_RBDIHS; j++)
2032                 {
2033                     parm[j*GMX_SIMD_REAL_WIDTH + s] = 0;
2034                 }
2035             }
2036         }
2037
2038         /* Caclulate GMX_SIMD_REAL_WIDTH dihedral angles at once */
2039         dih_angle_simd(x, ai, aj, ak, al, pbc_simd,
2040                        &phi_S,
2041                        &mx_S, &my_S, &mz_S,
2042                        &nx_S, &ny_S, &nz_S,
2043                        &nrkj_m2_S,
2044                        &nrkj_n2_S,
2045                        &p_S, &q_S);
2046
2047         /* Change to polymer convention */
2048         phi_S = phi_S - pi_S;
2049
2050         sincos(phi_S, &sin_S, &cos_S);
2051
2052         ddphi_S   = setZero();
2053         c_S       = one_S;
2054         cosfac_S  = one_S;
2055         for (j = 1; j < NR_RBDIHS; j++)
2056         {
2057             parm_S   = load(parm + j*GMX_SIMD_REAL_WIDTH);
2058             ddphi_S  = fma(c_S * parm_S, cosfac_S, ddphi_S);
2059             cosfac_S = cosfac_S * cos_S;
2060             c_S      = c_S + one_S;
2061         }
2062
2063         /* Note that here we do not use the minus sign which is present
2064          * in the normal RB code. This is corrected for through (m)sf below.
2065          */
2066         ddphi_S  = ddphi_S * sin_S;
2067
2068         sf_i_S   = ddphi_S * nrkj_m2_S;
2069         msf_l_S  = ddphi_S * nrkj_n2_S;
2070
2071         /* After this m?_S will contain f[i] */
2072         mx_S     = sf_i_S * mx_S;
2073         my_S     = sf_i_S * my_S;
2074         mz_S     = sf_i_S * mz_S;
2075
2076         /* After this m?_S will contain -f[l] */
2077         nx_S     = msf_l_S * nx_S;
2078         ny_S     = msf_l_S * ny_S;
2079         nz_S     = msf_l_S * nz_S;
2080
2081         do_dih_fup_noshiftf_simd(ai, aj, ak, al,
2082                                  p_S, q_S,
2083                                  mx_S, my_S, mz_S,
2084                                  nx_S, ny_S, nz_S,
2085                                  f);
2086     }
2087 }
2088
2089 #endif // GMX_SIMD_HAVE_REAL
2090
2091
2092 real idihs(int nbonds,
2093            const t_iatom forceatoms[], const t_iparams forceparams[],
2094            const rvec x[], rvec4 f[], rvec fshift[],
2095            const t_pbc *pbc, const t_graph *g,
2096            real lambda, real *dvdlambda,
2097            const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
2098            int gmx_unused *global_atom_index)
2099 {
2100     int  i, type, ai, aj, ak, al;
2101     int  t1, t2, t3;
2102     real phi, phi0, dphi0, ddphi, sign, vtot;
2103     rvec r_ij, r_kj, r_kl, m, n;
2104     real L1, kk, dp, dp2, kA, kB, pA, pB, dvdl_term;
2105
2106     L1        = 1.0-lambda;
2107     dvdl_term = 0;
2108     vtot      = 0.0;
2109     for (i = 0; (i < nbonds); )
2110     {
2111         type = forceatoms[i++];
2112         ai   = forceatoms[i++];
2113         aj   = forceatoms[i++];
2114         ak   = forceatoms[i++];
2115         al   = forceatoms[i++];
2116
2117         phi = dih_angle(x[ai], x[aj], x[ak], x[al], pbc, r_ij, r_kj, r_kl, m, n,
2118                         &sign, &t1, &t2, &t3);  /*  84          */
2119
2120         /* phi can jump if phi0 is close to Pi/-Pi, which will cause huge
2121          * force changes if we just apply a normal harmonic.
2122          * Instead, we first calculate phi-phi0 and take it modulo (-Pi,Pi).
2123          * This means we will never have the periodicity problem, unless
2124          * the dihedral is Pi away from phiO, which is very unlikely due to
2125          * the potential.
2126          */
2127         kA = forceparams[type].harmonic.krA;
2128         kB = forceparams[type].harmonic.krB;
2129         pA = forceparams[type].harmonic.rA;
2130         pB = forceparams[type].harmonic.rB;
2131
2132         kk    = L1*kA + lambda*kB;
2133         phi0  = (L1*pA + lambda*pB)*DEG2RAD;
2134         dphi0 = (pB - pA)*DEG2RAD;
2135
2136         dp = phi-phi0;
2137
2138         make_dp_periodic(&dp);
2139
2140         dp2 = dp*dp;
2141
2142         vtot += 0.5*kk*dp2;
2143         ddphi = -kk*dp;
2144
2145         dvdl_term += 0.5*(kB - kA)*dp2 - kk*dphi0*dp;
2146
2147         do_dih_fup(ai, aj, ak, al, -ddphi, r_ij, r_kj, r_kl, m, n,
2148                    f, fshift, pbc, g, x, t1, t2, t3); /* 112            */
2149         /* 218 TOTAL    */
2150 #ifdef DEBUG
2151         if (debug)
2152         {
2153             fprintf(debug, "idih: (%d,%d,%d,%d) phi=%g\n",
2154                     ai, aj, ak, al, phi);
2155         }
2156 #endif
2157     }
2158
2159     *dvdlambda += dvdl_term;
2160     return vtot;
2161 }
2162
2163 static real low_angres(int nbonds,
2164                        const t_iatom forceatoms[], const t_iparams forceparams[],
2165                        const rvec x[], rvec4 f[], rvec fshift[],
2166                        const t_pbc *pbc, const t_graph *g,
2167                        real lambda, real *dvdlambda,
2168                        gmx_bool bZAxis)
2169 {
2170     int  i, m, type, ai, aj, ak, al;
2171     int  t1, t2;
2172     real phi, cos_phi, cos_phi2, vid, vtot, dVdphi;
2173     rvec r_ij, r_kl, f_i, f_k = {0, 0, 0};
2174     real st, sth, nrij2, nrkl2, c, cij, ckl;
2175
2176     ivec dt;
2177     t2 = 0; /* avoid warning with gcc-3.3. It is never used uninitialized */
2178
2179     vtot = 0.0;
2180     ak   = al = 0; /* to avoid warnings */
2181     for (i = 0; i < nbonds; )
2182     {
2183         type = forceatoms[i++];
2184         ai   = forceatoms[i++];
2185         aj   = forceatoms[i++];
2186         t1   = pbc_rvec_sub(pbc, x[aj], x[ai], r_ij);       /*  3               */
2187         if (!bZAxis)
2188         {
2189             ak   = forceatoms[i++];
2190             al   = forceatoms[i++];
2191             t2   = pbc_rvec_sub(pbc, x[al], x[ak], r_kl);  /*  3                */
2192         }
2193         else
2194         {
2195             r_kl[XX] = 0;
2196             r_kl[YY] = 0;
2197             r_kl[ZZ] = 1;
2198         }
2199
2200         cos_phi = cos_angle(r_ij, r_kl); /* 25          */
2201         phi     = std::acos(cos_phi);    /* 10           */
2202
2203         *dvdlambda += dopdihs_min(forceparams[type].pdihs.cpA,
2204                                   forceparams[type].pdihs.cpB,
2205                                   forceparams[type].pdihs.phiA,
2206                                   forceparams[type].pdihs.phiB,
2207                                   forceparams[type].pdihs.mult,
2208                                   phi, lambda, &vid, &dVdphi); /*  40  */
2209
2210         vtot += vid;
2211
2212         cos_phi2 = gmx::square(cos_phi);                /*   1          */
2213         if (cos_phi2 < 1)
2214         {
2215             st    = -dVdphi*gmx::invsqrt(1 - cos_phi2); /*  12          */
2216             sth   = st*cos_phi;                         /*   1          */
2217             nrij2 = iprod(r_ij, r_ij);                  /*   5          */
2218             nrkl2 = iprod(r_kl, r_kl);                  /*   5          */
2219
2220             c   = st*gmx::invsqrt(nrij2*nrkl2);         /*  11          */
2221             cij = sth/nrij2;                            /*  10          */
2222             ckl = sth/nrkl2;                            /*  10          */
2223
2224             for (m = 0; m < DIM; m++)                   /*  18+18       */
2225             {
2226                 f_i[m]    = (c*r_kl[m]-cij*r_ij[m]);
2227                 f[ai][m] += f_i[m];
2228                 f[aj][m] -= f_i[m];
2229                 if (!bZAxis)
2230                 {
2231                     f_k[m]    = (c*r_ij[m]-ckl*r_kl[m]);
2232                     f[ak][m] += f_k[m];
2233                     f[al][m] -= f_k[m];
2234                 }
2235             }
2236
2237             if (g)
2238             {
2239                 ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
2240                 t1 = IVEC2IS(dt);
2241             }
2242             rvec_inc(fshift[t1], f_i);
2243             rvec_dec(fshift[CENTRAL], f_i);
2244             if (!bZAxis)
2245             {
2246                 if (g)
2247                 {
2248                     ivec_sub(SHIFT_IVEC(g, ak), SHIFT_IVEC(g, al), dt);
2249                     t2 = IVEC2IS(dt);
2250                 }
2251                 rvec_inc(fshift[t2], f_k);
2252                 rvec_dec(fshift[CENTRAL], f_k);
2253             }
2254         }
2255     }
2256
2257     return vtot; /*  184 / 157 (bZAxis)  total  */
2258 }
2259
2260 real angres(int nbonds,
2261             const t_iatom forceatoms[], const t_iparams forceparams[],
2262             const rvec x[], rvec4 f[], rvec fshift[],
2263             const t_pbc *pbc, const t_graph *g,
2264             real lambda, real *dvdlambda,
2265             const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
2266             int gmx_unused *global_atom_index)
2267 {
2268     return low_angres(nbonds, forceatoms, forceparams, x, f, fshift, pbc, g,
2269                       lambda, dvdlambda, FALSE);
2270 }
2271
2272 real angresz(int nbonds,
2273              const t_iatom forceatoms[], const t_iparams forceparams[],
2274              const rvec x[], rvec4 f[], rvec fshift[],
2275              const t_pbc *pbc, const t_graph *g,
2276              real lambda, real *dvdlambda,
2277              const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
2278              int gmx_unused *global_atom_index)
2279 {
2280     return low_angres(nbonds, forceatoms, forceparams, x, f, fshift, pbc, g,
2281                       lambda, dvdlambda, TRUE);
2282 }
2283
2284 real dihres(int nbonds,
2285             const t_iatom forceatoms[], const t_iparams forceparams[],
2286             const rvec x[], rvec4 f[], rvec fshift[],
2287             const t_pbc *pbc, const t_graph *g,
2288             real lambda, real *dvdlambda,
2289             const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
2290             int gmx_unused  *global_atom_index)
2291 {
2292     real vtot = 0;
2293     int  ai, aj, ak, al, i, k, type, t1, t2, t3;
2294     real phi0A, phi0B, dphiA, dphiB, kfacA, kfacB, phi0, dphi, kfac;
2295     real phi, ddphi, ddp, ddp2, dp, sign, d2r, L1;
2296     rvec r_ij, r_kj, r_kl, m, n;
2297
2298     L1 = 1.0-lambda;
2299
2300     d2r = DEG2RAD;
2301     k   = 0;
2302
2303     for (i = 0; (i < nbonds); )
2304     {
2305         type = forceatoms[i++];
2306         ai   = forceatoms[i++];
2307         aj   = forceatoms[i++];
2308         ak   = forceatoms[i++];
2309         al   = forceatoms[i++];
2310
2311         phi0A  = forceparams[type].dihres.phiA*d2r;
2312         dphiA  = forceparams[type].dihres.dphiA*d2r;
2313         kfacA  = forceparams[type].dihres.kfacA;
2314
2315         phi0B  = forceparams[type].dihres.phiB*d2r;
2316         dphiB  = forceparams[type].dihres.dphiB*d2r;
2317         kfacB  = forceparams[type].dihres.kfacB;
2318
2319         phi0  = L1*phi0A + lambda*phi0B;
2320         dphi  = L1*dphiA + lambda*dphiB;
2321         kfac  = L1*kfacA + lambda*kfacB;
2322
2323         phi = dih_angle(x[ai], x[aj], x[ak], x[al], pbc, r_ij, r_kj, r_kl, m, n,
2324                         &sign, &t1, &t2, &t3);
2325         /* 84 flops */
2326
2327         if (debug)
2328         {
2329             fprintf(debug, "dihres[%d]: %d %d %d %d : phi=%f, dphi=%f, kfac=%f\n",
2330                     k++, ai, aj, ak, al, phi0, dphi, kfac);
2331         }
2332         /* phi can jump if phi0 is close to Pi/-Pi, which will cause huge
2333          * force changes if we just apply a normal harmonic.
2334          * Instead, we first calculate phi-phi0 and take it modulo (-Pi,Pi).
2335          * This means we will never have the periodicity problem, unless
2336          * the dihedral is Pi away from phiO, which is very unlikely due to
2337          * the potential.
2338          */
2339         dp = phi-phi0;
2340         make_dp_periodic(&dp);
2341
2342         if (dp > dphi)
2343         {
2344             ddp = dp-dphi;
2345         }
2346         else if (dp < -dphi)
2347         {
2348             ddp = dp+dphi;
2349         }
2350         else
2351         {
2352             ddp = 0;
2353         }
2354
2355         if (ddp != 0.0)
2356         {
2357             ddp2  = ddp*ddp;
2358             vtot += 0.5*kfac*ddp2;
2359             ddphi = kfac*ddp;
2360
2361             *dvdlambda += 0.5*(kfacB - kfacA)*ddp2;
2362             /* lambda dependence from changing restraint distances */
2363             if (ddp > 0)
2364             {
2365                 *dvdlambda -= kfac*ddp*((dphiB - dphiA)+(phi0B - phi0A));
2366             }
2367             else if (ddp < 0)
2368             {
2369                 *dvdlambda += kfac*ddp*((dphiB - dphiA)-(phi0B - phi0A));
2370             }
2371             do_dih_fup(ai, aj, ak, al, ddphi, r_ij, r_kj, r_kl, m, n,
2372                        f, fshift, pbc, g, x, t1, t2, t3);      /* 112           */
2373         }
2374     }
2375     return vtot;
2376 }
2377
2378
2379 real unimplemented(int gmx_unused nbonds,
2380                    const t_iatom gmx_unused forceatoms[], const t_iparams gmx_unused forceparams[],
2381                    const rvec gmx_unused x[], rvec4 gmx_unused f[], rvec gmx_unused fshift[],
2382                    const t_pbc gmx_unused *pbc, const t_graph  gmx_unused *g,
2383                    real gmx_unused lambda, real gmx_unused *dvdlambda,
2384                    const t_mdatoms  gmx_unused *md, t_fcdata gmx_unused *fcd,
2385                    int gmx_unused *global_atom_index)
2386 {
2387     gmx_impl("*** you are using a not implemented function");
2388
2389     return 0.0; /* To make the compiler happy */
2390 }
2391
2392 real restrangles(int nbonds,
2393                  const t_iatom forceatoms[], const t_iparams forceparams[],
2394                  const rvec x[], rvec4 f[], rvec fshift[],
2395                  const t_pbc *pbc, const t_graph *g,
2396                  real gmx_unused lambda, real gmx_unused *dvdlambda,
2397                  const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
2398                  int gmx_unused *global_atom_index)
2399 {
2400     int  i, d, ai, aj, ak, type, m;
2401     int  t1, t2;
2402     real v, vtot;
2403     ivec jt, dt_ij, dt_kj;
2404     rvec f_i, f_j, f_k;
2405     real prefactor, ratio_ante, ratio_post;
2406     rvec delta_ante, delta_post, vec_temp;
2407
2408     vtot = 0.0;
2409     for (i = 0; (i < nbonds); )
2410     {
2411         type = forceatoms[i++];
2412         ai   = forceatoms[i++];
2413         aj   = forceatoms[i++];
2414         ak   = forceatoms[i++];
2415
2416         t1 = pbc_rvec_sub(pbc, x[ai], x[aj], vec_temp);
2417         pbc_rvec_sub(pbc, x[aj], x[ai], delta_ante);
2418         t2 = pbc_rvec_sub(pbc, x[ak], x[aj], delta_post);
2419
2420
2421         /* This function computes factors needed for restricted angle potential.
2422          * The restricted angle potential is used in coarse-grained simulations to avoid singularities
2423          * when three particles align and the dihedral angle and dihedral potential
2424          * cannot be calculated. This potential is calculated using the formula:
2425            real restrangles(int nbonds,
2426             const t_iatom forceatoms[],const t_iparams forceparams[],
2427             const rvec x[],rvec4 f[],rvec fshift[],
2428             const t_pbc *pbc,const t_graph *g,
2429             real gmx_unused lambda,real gmx_unused *dvdlambda,
2430             const t_mdatoms gmx_unused *md,t_fcdata gmx_unused *fcd,
2431             int gmx_unused *global_atom_index)
2432            {
2433            int  i, d, ai, aj, ak, type, m;
2434            int t1, t2;
2435            rvec r_ij,r_kj;
2436            real v, vtot;
2437            ivec jt,dt_ij,dt_kj;
2438            rvec f_i, f_j, f_k;
2439            real prefactor, ratio_ante, ratio_post;
2440            rvec delta_ante, delta_post, vec_temp;
2441
2442            vtot = 0.0;
2443            for(i=0; (i<nbonds); )
2444            {
2445            type = forceatoms[i++];
2446            ai   = forceatoms[i++];
2447            aj   = forceatoms[i++];
2448            ak   = forceatoms[i++];
2449
2450          * \f[V_{\rm ReB}(\theta_i) = \frac{1}{2} k_{\theta} \frac{(\cos\theta_i - \cos\theta_0)^2}
2451          * {\sin^2\theta_i}\f] ({eq:ReB} and ref \cite{MonicaGoga2013} from the manual).
2452          * For more explanations see comments file "restcbt.h". */
2453
2454         compute_factors_restangles(type, forceparams,  delta_ante, delta_post,
2455                                    &prefactor, &ratio_ante, &ratio_post, &v);
2456
2457         /*   Forces are computed per component */
2458         for (d = 0; d < DIM; d++)
2459         {
2460             f_i[d] = prefactor * (ratio_ante * delta_ante[d] - delta_post[d]);
2461             f_j[d] = prefactor * ((ratio_post + 1.0) * delta_post[d] - (ratio_ante + 1.0) * delta_ante[d]);
2462             f_k[d] = prefactor * (delta_ante[d] - ratio_post * delta_post[d]);
2463         }
2464
2465         /*   Computation of potential energy   */
2466
2467         vtot += v;
2468
2469         /*   Update forces */
2470
2471         for (m = 0; (m < DIM); m++)
2472         {
2473             f[ai][m] += f_i[m];
2474             f[aj][m] += f_j[m];
2475             f[ak][m] += f_k[m];
2476         }
2477
2478         if (g)
2479         {
2480             copy_ivec(SHIFT_IVEC(g, aj), jt);
2481             ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
2482             ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
2483             t1 = IVEC2IS(dt_ij);
2484             t2 = IVEC2IS(dt_kj);
2485         }
2486
2487         rvec_inc(fshift[t1], f_i);
2488         rvec_inc(fshift[CENTRAL], f_j);
2489         rvec_inc(fshift[t2], f_k);
2490     }
2491     return vtot;
2492 }
2493
2494
2495 real restrdihs(int nbonds,
2496                const t_iatom forceatoms[], const t_iparams forceparams[],
2497                const rvec x[], rvec4 f[], rvec fshift[],
2498                const t_pbc *pbc, const t_graph *g,
2499                real gmx_unused lambda, real gmx_unused *dvlambda,
2500                const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
2501                int gmx_unused *global_atom_index)
2502 {
2503     int  i, d, type, ai, aj, ak, al;
2504     rvec f_i, f_j, f_k, f_l;
2505     rvec dx_jl;
2506     ivec jt, dt_ij, dt_kj, dt_lj;
2507     int  t1, t2, t3;
2508     real v, vtot;
2509     rvec delta_ante,  delta_crnt, delta_post, vec_temp;
2510     real factor_phi_ai_ante, factor_phi_ai_crnt, factor_phi_ai_post;
2511     real factor_phi_aj_ante, factor_phi_aj_crnt, factor_phi_aj_post;
2512     real factor_phi_ak_ante, factor_phi_ak_crnt, factor_phi_ak_post;
2513     real factor_phi_al_ante, factor_phi_al_crnt, factor_phi_al_post;
2514     real prefactor_phi;
2515
2516
2517     vtot = 0.0;
2518     for (i = 0; (i < nbonds); )
2519     {
2520         type = forceatoms[i++];
2521         ai   = forceatoms[i++];
2522         aj   = forceatoms[i++];
2523         ak   = forceatoms[i++];
2524         al   = forceatoms[i++];
2525
2526         t1 = pbc_rvec_sub(pbc, x[ai], x[aj], vec_temp);
2527         pbc_rvec_sub(pbc, x[aj], x[ai], delta_ante);
2528         t2 = pbc_rvec_sub(pbc, x[ak], x[aj], delta_crnt);
2529         pbc_rvec_sub(pbc, x[ak], x[al], vec_temp);
2530         pbc_rvec_sub(pbc, x[al], x[ak], delta_post);
2531
2532         /* This function computes factors needed for restricted angle potential.
2533          * The restricted angle potential is used in coarse-grained simulations to avoid singularities
2534          * when three particles align and the dihedral angle and dihedral potential cannot be calculated.
2535          * This potential is calculated using the formula:
2536          * \f[V_{\rm ReB}(\theta_i) = \frac{1}{2} k_{\theta}
2537          * \frac{(\cos\theta_i - \cos\theta_0)^2}{\sin^2\theta_i}\f]
2538          * ({eq:ReB} and ref \cite{MonicaGoga2013} from the manual).
2539          * For more explanations see comments file "restcbt.h" */
2540
2541         compute_factors_restrdihs(type, forceparams,
2542                                   delta_ante, delta_crnt, delta_post,
2543                                   &factor_phi_ai_ante, &factor_phi_ai_crnt, &factor_phi_ai_post,
2544                                   &factor_phi_aj_ante, &factor_phi_aj_crnt, &factor_phi_aj_post,
2545                                   &factor_phi_ak_ante, &factor_phi_ak_crnt, &factor_phi_ak_post,
2546                                   &factor_phi_al_ante, &factor_phi_al_crnt, &factor_phi_al_post,
2547                                   &prefactor_phi, &v);
2548
2549
2550         /*      Computation of forces per component */
2551         for (d = 0; d < DIM; d++)
2552         {
2553             f_i[d] = prefactor_phi * (factor_phi_ai_ante * delta_ante[d] + factor_phi_ai_crnt * delta_crnt[d] + factor_phi_ai_post * delta_post[d]);
2554             f_j[d] = prefactor_phi * (factor_phi_aj_ante * delta_ante[d] + factor_phi_aj_crnt * delta_crnt[d] + factor_phi_aj_post * delta_post[d]);
2555             f_k[d] = prefactor_phi * (factor_phi_ak_ante * delta_ante[d] + factor_phi_ak_crnt * delta_crnt[d] + factor_phi_ak_post * delta_post[d]);
2556             f_l[d] = prefactor_phi * (factor_phi_al_ante * delta_ante[d] + factor_phi_al_crnt * delta_crnt[d] + factor_phi_al_post * delta_post[d]);
2557         }
2558         /*      Computation of the energy */
2559
2560         vtot += v;
2561
2562
2563
2564         /*    Updating the forces */
2565
2566         rvec_inc(f[ai], f_i);
2567         rvec_inc(f[aj], f_j);
2568         rvec_inc(f[ak], f_k);
2569         rvec_inc(f[al], f_l);
2570
2571
2572         /* Updating the fshift forces for the pressure coupling */
2573         if (g)
2574         {
2575             copy_ivec(SHIFT_IVEC(g, aj), jt);
2576             ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
2577             ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
2578             ivec_sub(SHIFT_IVEC(g, al), jt, dt_lj);
2579             t1 = IVEC2IS(dt_ij);
2580             t2 = IVEC2IS(dt_kj);
2581             t3 = IVEC2IS(dt_lj);
2582         }
2583         else if (pbc)
2584         {
2585             t3 = pbc_rvec_sub(pbc, x[al], x[aj], dx_jl);
2586         }
2587         else
2588         {
2589             t3 = CENTRAL;
2590         }
2591
2592         rvec_inc(fshift[t1], f_i);
2593         rvec_inc(fshift[CENTRAL], f_j);
2594         rvec_inc(fshift[t2], f_k);
2595         rvec_inc(fshift[t3], f_l);
2596
2597     }
2598
2599     return vtot;
2600 }
2601
2602
2603 real cbtdihs(int nbonds,
2604              const t_iatom forceatoms[], const t_iparams forceparams[],
2605              const rvec x[], rvec4 f[], rvec fshift[],
2606              const t_pbc *pbc, const t_graph *g,
2607              real gmx_unused lambda, real gmx_unused *dvdlambda,
2608              const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
2609              int gmx_unused *global_atom_index)
2610 {
2611     int  type, ai, aj, ak, al, i, d;
2612     int  t1, t2, t3;
2613     real v, vtot;
2614     rvec vec_temp;
2615     rvec f_i, f_j, f_k, f_l;
2616     ivec jt, dt_ij, dt_kj, dt_lj;
2617     rvec dx_jl;
2618     rvec delta_ante, delta_crnt, delta_post;
2619     rvec f_phi_ai, f_phi_aj, f_phi_ak, f_phi_al;
2620     rvec f_theta_ante_ai, f_theta_ante_aj, f_theta_ante_ak;
2621     rvec f_theta_post_aj, f_theta_post_ak, f_theta_post_al;
2622
2623
2624
2625
2626     vtot = 0.0;
2627     for (i = 0; (i < nbonds); )
2628     {
2629         type = forceatoms[i++];
2630         ai   = forceatoms[i++];
2631         aj   = forceatoms[i++];
2632         ak   = forceatoms[i++];
2633         al   = forceatoms[i++];
2634
2635
2636         t1 = pbc_rvec_sub(pbc, x[ai], x[aj], vec_temp);
2637         pbc_rvec_sub(pbc, x[aj], x[ai], delta_ante);
2638         t2 = pbc_rvec_sub(pbc, x[ak], x[aj], vec_temp);
2639         pbc_rvec_sub(pbc, x[ak], x[aj], delta_crnt);
2640         pbc_rvec_sub(pbc, x[ak], x[al], vec_temp);
2641         pbc_rvec_sub(pbc, x[al], x[ak], delta_post);
2642
2643         /* \brief Compute factors for CBT potential
2644          * The combined bending-torsion potential goes to zero in a very smooth manner, eliminating the numerical
2645          * instabilities, when three coarse-grained particles align and the dihedral angle and standard
2646          * dihedral potentials cannot be calculated. The CBT potential is calculated using the formula:
2647          * \f[V_{\rm CBT}(\theta_{i-1}, \theta_i, \phi_i) = k_{\phi} \sin^3\theta_{i-1} \sin^3\theta_{i}
2648          * \sum_{n=0}^4 { a_n \cos^n\phi_i}\f] ({eq:CBT} and ref \cite{MonicaGoga2013} from the manual).
2649          * It contains in its expression not only the dihedral angle \f$\phi\f$
2650          * but also \f[\theta_{i-1}\f] (theta_ante bellow) and \f[\theta_{i}\f] (theta_post bellow)
2651          * --- the adjacent bending angles.
2652          * For more explanations see comments file "restcbt.h". */
2653
2654         compute_factors_cbtdihs(type, forceparams, delta_ante, delta_crnt, delta_post,
2655                                 f_phi_ai, f_phi_aj, f_phi_ak, f_phi_al,
2656                                 f_theta_ante_ai, f_theta_ante_aj, f_theta_ante_ak,
2657                                 f_theta_post_aj, f_theta_post_ak, f_theta_post_al,
2658                                 &v);
2659
2660
2661         /*      Acumulate the resuts per beads */
2662         for (d = 0; d < DIM; d++)
2663         {
2664             f_i[d] = f_phi_ai[d] + f_theta_ante_ai[d];
2665             f_j[d] = f_phi_aj[d] + f_theta_ante_aj[d] + f_theta_post_aj[d];
2666             f_k[d] = f_phi_ak[d] + f_theta_ante_ak[d] + f_theta_post_ak[d];
2667             f_l[d] = f_phi_al[d] + f_theta_post_al[d];
2668         }
2669
2670         /*      Compute the potential energy */
2671
2672         vtot += v;
2673
2674
2675         /*  Updating the forces */
2676         rvec_inc(f[ai], f_i);
2677         rvec_inc(f[aj], f_j);
2678         rvec_inc(f[ak], f_k);
2679         rvec_inc(f[al], f_l);
2680
2681
2682         /* Updating the fshift forces for the pressure coupling */
2683         if (g)
2684         {
2685             copy_ivec(SHIFT_IVEC(g, aj), jt);
2686             ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
2687             ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
2688             ivec_sub(SHIFT_IVEC(g, al), jt, dt_lj);
2689             t1 = IVEC2IS(dt_ij);
2690             t2 = IVEC2IS(dt_kj);
2691             t3 = IVEC2IS(dt_lj);
2692         }
2693         else if (pbc)
2694         {
2695             t3 = pbc_rvec_sub(pbc, x[al], x[aj], dx_jl);
2696         }
2697         else
2698         {
2699             t3 = CENTRAL;
2700         }
2701
2702         rvec_inc(fshift[t1], f_i);
2703         rvec_inc(fshift[CENTRAL], f_j);
2704         rvec_inc(fshift[t2], f_k);
2705         rvec_inc(fshift[t3], f_l);
2706     }
2707
2708     return vtot;
2709 }
2710
2711 real rbdihs(int nbonds,
2712             const t_iatom forceatoms[], const t_iparams forceparams[],
2713             const rvec x[], rvec4 f[], rvec fshift[],
2714             const t_pbc *pbc, const t_graph *g,
2715             real lambda, real *dvdlambda,
2716             const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
2717             int gmx_unused *global_atom_index)
2718 {
2719     const real c0 = 0.0, c1 = 1.0, c2 = 2.0, c3 = 3.0, c4 = 4.0, c5 = 5.0;
2720     int        type, ai, aj, ak, al, i, j;
2721     int        t1, t2, t3;
2722     rvec       r_ij, r_kj, r_kl, m, n;
2723     real       parmA[NR_RBDIHS];
2724     real       parmB[NR_RBDIHS];
2725     real       parm[NR_RBDIHS];
2726     real       cos_phi, phi, rbp, rbpBA;
2727     real       v, sign, ddphi, sin_phi;
2728     real       cosfac, vtot;
2729     real       L1        = 1.0-lambda;
2730     real       dvdl_term = 0;
2731
2732     vtot = 0.0;
2733     for (i = 0; (i < nbonds); )
2734     {
2735         type = forceatoms[i++];
2736         ai   = forceatoms[i++];
2737         aj   = forceatoms[i++];
2738         ak   = forceatoms[i++];
2739         al   = forceatoms[i++];
2740
2741         phi = dih_angle(x[ai], x[aj], x[ak], x[al], pbc, r_ij, r_kj, r_kl, m, n,
2742                         &sign, &t1, &t2, &t3);  /*  84          */
2743
2744         /* Change to polymer convention */
2745         if (phi < c0)
2746         {
2747             phi += M_PI;
2748         }
2749         else
2750         {
2751             phi -= M_PI;    /*   1              */
2752
2753         }
2754         cos_phi = std::cos(phi);
2755         /* Beware of accuracy loss, cannot use 1-sqrt(cos^2) ! */
2756         sin_phi = std::sin(phi);
2757
2758         for (j = 0; (j < NR_RBDIHS); j++)
2759         {
2760             parmA[j] = forceparams[type].rbdihs.rbcA[j];
2761             parmB[j] = forceparams[type].rbdihs.rbcB[j];
2762             parm[j]  = L1*parmA[j]+lambda*parmB[j];
2763         }
2764         /* Calculate cosine powers */
2765         /* Calculate the energy */
2766         /* Calculate the derivative */
2767
2768         v            = parm[0];
2769         dvdl_term   += (parmB[0]-parmA[0]);
2770         ddphi        = c0;
2771         cosfac       = c1;
2772
2773         rbp          = parm[1];
2774         rbpBA        = parmB[1]-parmA[1];
2775         ddphi       += rbp*cosfac;
2776         cosfac      *= cos_phi;
2777         v           += cosfac*rbp;
2778         dvdl_term   += cosfac*rbpBA;
2779         rbp          = parm[2];
2780         rbpBA        = parmB[2]-parmA[2];
2781         ddphi       += c2*rbp*cosfac;
2782         cosfac      *= cos_phi;
2783         v           += cosfac*rbp;
2784         dvdl_term   += cosfac*rbpBA;
2785         rbp          = parm[3];
2786         rbpBA        = parmB[3]-parmA[3];
2787         ddphi       += c3*rbp*cosfac;
2788         cosfac      *= cos_phi;
2789         v           += cosfac*rbp;
2790         dvdl_term   += cosfac*rbpBA;
2791         rbp          = parm[4];
2792         rbpBA        = parmB[4]-parmA[4];
2793         ddphi       += c4*rbp*cosfac;
2794         cosfac      *= cos_phi;
2795         v           += cosfac*rbp;
2796         dvdl_term   += cosfac*rbpBA;
2797         rbp          = parm[5];
2798         rbpBA        = parmB[5]-parmA[5];
2799         ddphi       += c5*rbp*cosfac;
2800         cosfac      *= cos_phi;
2801         v           += cosfac*rbp;
2802         dvdl_term   += cosfac*rbpBA;
2803
2804         ddphi = -ddphi*sin_phi;         /*  11          */
2805
2806         do_dih_fup(ai, aj, ak, al, ddphi, r_ij, r_kj, r_kl, m, n,
2807                    f, fshift, pbc, g, x, t1, t2, t3); /* 112            */
2808         vtot += v;
2809     }
2810     *dvdlambda += dvdl_term;
2811
2812     return vtot;
2813 }
2814
2815 //! \endcond
2816
2817 /*! \brief Mysterious undocumented function */
2818 static int
2819 cmap_setup_grid_index(int ip, int grid_spacing, int *ipm1, int *ipp1, int *ipp2)
2820 {
2821     int im1, ip1, ip2;
2822
2823     if (ip < 0)
2824     {
2825         ip = ip + grid_spacing - 1;
2826     }
2827     else if (ip > grid_spacing)
2828     {
2829         ip = ip - grid_spacing - 1;
2830     }
2831
2832     im1 = ip - 1;
2833     ip1 = ip + 1;
2834     ip2 = ip + 2;
2835
2836     if (ip == 0)
2837     {
2838         im1 = grid_spacing - 1;
2839     }
2840     else if (ip == grid_spacing-2)
2841     {
2842         ip2 = 0;
2843     }
2844     else if (ip == grid_spacing-1)
2845     {
2846         ip1 = 0;
2847         ip2 = 1;
2848     }
2849
2850     *ipm1 = im1;
2851     *ipp1 = ip1;
2852     *ipp2 = ip2;
2853
2854     return ip;
2855
2856 }
2857
2858 real
2859 cmap_dihs(int nbonds,
2860           const t_iatom forceatoms[], const t_iparams forceparams[],
2861           const gmx_cmap_t *cmap_grid,
2862           const rvec x[], rvec4 f[], rvec fshift[],
2863           const struct t_pbc *pbc, const struct t_graph *g,
2864           real gmx_unused lambda, real gmx_unused *dvdlambda,
2865           const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
2866           int  gmx_unused *global_atom_index)
2867 {
2868     int         i, j, k, n, idx;
2869     int         ai, aj, ak, al, am;
2870     int         a1i, a1j, a1k, a1l, a2i, a2j, a2k, a2l;
2871     int         type, cmapA;
2872     int         t11, t21, t31, t12, t22, t32;
2873     int         iphi1, ip1m1, ip1p1, ip1p2;
2874     int         iphi2, ip2m1, ip2p1, ip2p2;
2875     int         l1, l2, l3;
2876     int         pos1, pos2, pos3, pos4;
2877
2878     real        ty[4], ty1[4], ty2[4], ty12[4], tc[16], tx[16];
2879     real        phi1, cos_phi1, sin_phi1, sign1, xphi1;
2880     real        phi2, cos_phi2, sin_phi2, sign2, xphi2;
2881     real        dx, xx, tt, tu, e, df1, df2, vtot;
2882     real        ra21, rb21, rg21, rg1, rgr1, ra2r1, rb2r1, rabr1;
2883     real        ra22, rb22, rg22, rg2, rgr2, ra2r2, rb2r2, rabr2;
2884     real        fg1, hg1, fga1, hgb1, gaa1, gbb1;
2885     real        fg2, hg2, fga2, hgb2, gaa2, gbb2;
2886     real        fac;
2887
2888     rvec        r1_ij, r1_kj, r1_kl, m1, n1;
2889     rvec        r2_ij, r2_kj, r2_kl, m2, n2;
2890     rvec        f1_i, f1_j, f1_k, f1_l;
2891     rvec        f2_i, f2_j, f2_k, f2_l;
2892     rvec        a1, b1, a2, b2;
2893     rvec        f1, g1, h1, f2, g2, h2;
2894     rvec        dtf1, dtg1, dth1, dtf2, dtg2, dth2;
2895     ivec        jt1, dt1_ij, dt1_kj, dt1_lj;
2896     ivec        jt2, dt2_ij, dt2_kj, dt2_lj;
2897
2898     const real *cmapd;
2899
2900     int         loop_index[4][4] = {
2901         {0, 4, 8, 12},
2902         {1, 5, 9, 13},
2903         {2, 6, 10, 14},
2904         {3, 7, 11, 15}
2905     };
2906
2907     /* Total CMAP energy */
2908     vtot = 0;
2909
2910     for (n = 0; n < nbonds; )
2911     {
2912         /* Five atoms are involved in the two torsions */
2913         type   = forceatoms[n++];
2914         ai     = forceatoms[n++];
2915         aj     = forceatoms[n++];
2916         ak     = forceatoms[n++];
2917         al     = forceatoms[n++];
2918         am     = forceatoms[n++];
2919
2920         /* Which CMAP type is this */
2921         cmapA = forceparams[type].cmap.cmapA;
2922         cmapd = cmap_grid->cmapdata[cmapA].cmap;
2923
2924         /* First torsion */
2925         a1i   = ai;
2926         a1j   = aj;
2927         a1k   = ak;
2928         a1l   = al;
2929
2930         phi1  = dih_angle(x[a1i], x[a1j], x[a1k], x[a1l], pbc, r1_ij, r1_kj, r1_kl, m1, n1,
2931                           &sign1, &t11, &t21, &t31);  /* 84 */
2932
2933         cos_phi1 = std::cos(phi1);
2934
2935         a1[0] = r1_ij[1]*r1_kj[2]-r1_ij[2]*r1_kj[1];
2936         a1[1] = r1_ij[2]*r1_kj[0]-r1_ij[0]*r1_kj[2];
2937         a1[2] = r1_ij[0]*r1_kj[1]-r1_ij[1]*r1_kj[0]; /* 9 */
2938
2939         b1[0] = r1_kl[1]*r1_kj[2]-r1_kl[2]*r1_kj[1];
2940         b1[1] = r1_kl[2]*r1_kj[0]-r1_kl[0]*r1_kj[2];
2941         b1[2] = r1_kl[0]*r1_kj[1]-r1_kl[1]*r1_kj[0]; /* 9 */
2942
2943         pbc_rvec_sub(pbc, x[a1l], x[a1k], h1);
2944
2945         ra21  = iprod(a1, a1);       /* 5 */
2946         rb21  = iprod(b1, b1);       /* 5 */
2947         rg21  = iprod(r1_kj, r1_kj); /* 5 */
2948         rg1   = sqrt(rg21);
2949
2950         rgr1  = 1.0/rg1;
2951         ra2r1 = 1.0/ra21;
2952         rb2r1 = 1.0/rb21;
2953         rabr1 = sqrt(ra2r1*rb2r1);
2954
2955         sin_phi1 = rg1 * rabr1 * iprod(a1, h1) * (-1);
2956
2957         if (cos_phi1 < -0.5 || cos_phi1 > 0.5)
2958         {
2959             phi1 = std::asin(sin_phi1);
2960
2961             if (cos_phi1 < 0)
2962             {
2963                 if (phi1 > 0)
2964                 {
2965                     phi1 = M_PI - phi1;
2966                 }
2967                 else
2968                 {
2969                     phi1 = -M_PI - phi1;
2970                 }
2971             }
2972         }
2973         else
2974         {
2975             phi1 = std::acos(cos_phi1);
2976
2977             if (sin_phi1 < 0)
2978             {
2979                 phi1 = -phi1;
2980             }
2981         }
2982
2983         xphi1 = phi1 + M_PI; /* 1 */
2984
2985         /* Second torsion */
2986         a2i   = aj;
2987         a2j   = ak;
2988         a2k   = al;
2989         a2l   = am;
2990
2991         phi2  = dih_angle(x[a2i], x[a2j], x[a2k], x[a2l], pbc, r2_ij, r2_kj, r2_kl, m2, n2,
2992                           &sign2, &t12, &t22, &t32); /* 84 */
2993
2994         cos_phi2 = std::cos(phi2);
2995
2996         a2[0] = r2_ij[1]*r2_kj[2]-r2_ij[2]*r2_kj[1];
2997         a2[1] = r2_ij[2]*r2_kj[0]-r2_ij[0]*r2_kj[2];
2998         a2[2] = r2_ij[0]*r2_kj[1]-r2_ij[1]*r2_kj[0]; /* 9 */
2999
3000         b2[0] = r2_kl[1]*r2_kj[2]-r2_kl[2]*r2_kj[1];
3001         b2[1] = r2_kl[2]*r2_kj[0]-r2_kl[0]*r2_kj[2];
3002         b2[2] = r2_kl[0]*r2_kj[1]-r2_kl[1]*r2_kj[0]; /* 9 */
3003
3004         pbc_rvec_sub(pbc, x[a2l], x[a2k], h2);
3005
3006         ra22  = iprod(a2, a2);         /* 5 */
3007         rb22  = iprod(b2, b2);         /* 5 */
3008         rg22  = iprod(r2_kj, r2_kj);   /* 5 */
3009         rg2   = sqrt(rg22);
3010
3011         rgr2  = 1.0/rg2;
3012         ra2r2 = 1.0/ra22;
3013         rb2r2 = 1.0/rb22;
3014         rabr2 = sqrt(ra2r2*rb2r2);
3015
3016         sin_phi2 = rg2 * rabr2 * iprod(a2, h2) * (-1);
3017
3018         if (cos_phi2 < -0.5 || cos_phi2 > 0.5)
3019         {
3020             phi2 = std::asin(sin_phi2);
3021
3022             if (cos_phi2 < 0)
3023             {
3024                 if (phi2 > 0)
3025                 {
3026                     phi2 = M_PI - phi2;
3027                 }
3028                 else
3029                 {
3030                     phi2 = -M_PI - phi2;
3031                 }
3032             }
3033         }
3034         else
3035         {
3036             phi2 = std::acos(cos_phi2);
3037
3038             if (sin_phi2 < 0)
3039             {
3040                 phi2 = -phi2;
3041             }
3042         }
3043
3044         xphi2 = phi2 + M_PI; /* 1 */
3045
3046         /* Range mangling */
3047         if (xphi1 < 0)
3048         {
3049             xphi1 = xphi1 + 2*M_PI;
3050         }
3051         else if (xphi1 >= 2*M_PI)
3052         {
3053             xphi1 = xphi1 - 2*M_PI;
3054         }
3055
3056         if (xphi2 < 0)
3057         {
3058             xphi2 = xphi2 + 2*M_PI;
3059         }
3060         else if (xphi2 >= 2*M_PI)
3061         {
3062             xphi2 = xphi2 - 2*M_PI;
3063         }
3064
3065         /* Number of grid points */
3066         dx = 2*M_PI / cmap_grid->grid_spacing;
3067
3068         /* Where on the grid are we */
3069         iphi1 = static_cast<int>(xphi1/dx);
3070         iphi2 = static_cast<int>(xphi2/dx);
3071
3072         iphi1 = cmap_setup_grid_index(iphi1, cmap_grid->grid_spacing, &ip1m1, &ip1p1, &ip1p2);
3073         iphi2 = cmap_setup_grid_index(iphi2, cmap_grid->grid_spacing, &ip2m1, &ip2p1, &ip2p2);
3074
3075         pos1    = iphi1*cmap_grid->grid_spacing+iphi2;
3076         pos2    = ip1p1*cmap_grid->grid_spacing+iphi2;
3077         pos3    = ip1p1*cmap_grid->grid_spacing+ip2p1;
3078         pos4    = iphi1*cmap_grid->grid_spacing+ip2p1;
3079
3080         ty[0]   = cmapd[pos1*4];
3081         ty[1]   = cmapd[pos2*4];
3082         ty[2]   = cmapd[pos3*4];
3083         ty[3]   = cmapd[pos4*4];
3084
3085         ty1[0]   = cmapd[pos1*4+1];
3086         ty1[1]   = cmapd[pos2*4+1];
3087         ty1[2]   = cmapd[pos3*4+1];
3088         ty1[3]   = cmapd[pos4*4+1];
3089
3090         ty2[0]   = cmapd[pos1*4+2];
3091         ty2[1]   = cmapd[pos2*4+2];
3092         ty2[2]   = cmapd[pos3*4+2];
3093         ty2[3]   = cmapd[pos4*4+2];
3094
3095         ty12[0]   = cmapd[pos1*4+3];
3096         ty12[1]   = cmapd[pos2*4+3];
3097         ty12[2]   = cmapd[pos3*4+3];
3098         ty12[3]   = cmapd[pos4*4+3];
3099
3100         /* Switch to degrees */
3101         dx    = 360.0 / cmap_grid->grid_spacing;
3102         xphi1 = xphi1 * RAD2DEG;
3103         xphi2 = xphi2 * RAD2DEG;
3104
3105         for (i = 0; i < 4; i++) /* 16 */
3106         {
3107             tx[i]    = ty[i];
3108             tx[i+4]  = ty1[i]*dx;
3109             tx[i+8]  = ty2[i]*dx;
3110             tx[i+12] = ty12[i]*dx*dx;
3111         }
3112
3113         idx = 0;
3114         for (i = 0; i < 4; i++) /* 1056 */
3115         {
3116             for (j = 0; j < 4; j++)
3117             {
3118                 xx = 0;
3119                 for (k = 0; k < 16; k++)
3120                 {
3121                     xx = xx + cmap_coeff_matrix[k*16+idx]*tx[k];
3122                 }
3123
3124                 idx++;
3125                 tc[i*4+j] = xx;
3126             }
3127         }
3128
3129         tt    = (xphi1-iphi1*dx)/dx;
3130         tu    = (xphi2-iphi2*dx)/dx;
3131
3132         e     = 0;
3133         df1   = 0;
3134         df2   = 0;
3135
3136         for (i = 3; i >= 0; i--)
3137         {
3138             l1 = loop_index[i][3];
3139             l2 = loop_index[i][2];
3140             l3 = loop_index[i][1];
3141
3142             e     = tt * e    + ((tc[i*4+3]*tu+tc[i*4+2])*tu + tc[i*4+1])*tu+tc[i*4];
3143             df1   = tu * df1  + (3.0*tc[l1]*tt+2.0*tc[l2])*tt+tc[l3];
3144             df2   = tt * df2  + (3.0*tc[i*4+3]*tu+2.0*tc[i*4+2])*tu+tc[i*4+1];
3145         }
3146
3147         fac     = RAD2DEG/dx;
3148         df1     = df1   * fac;
3149         df2     = df2   * fac;
3150
3151         /* CMAP energy */
3152         vtot += e;
3153
3154         /* Do forces - first torsion */
3155         fg1       = iprod(r1_ij, r1_kj);
3156         hg1       = iprod(r1_kl, r1_kj);
3157         fga1      = fg1*ra2r1*rgr1;
3158         hgb1      = hg1*rb2r1*rgr1;
3159         gaa1      = -ra2r1*rg1;
3160         gbb1      = rb2r1*rg1;
3161
3162         for (i = 0; i < DIM; i++)
3163         {
3164             dtf1[i]   = gaa1 * a1[i];
3165             dtg1[i]   = fga1 * a1[i] - hgb1 * b1[i];
3166             dth1[i]   = gbb1 * b1[i];
3167
3168             f1[i]     = df1  * dtf1[i];
3169             g1[i]     = df1  * dtg1[i];
3170             h1[i]     = df1  * dth1[i];
3171
3172             f1_i[i]   =  f1[i];
3173             f1_j[i]   = -f1[i] - g1[i];
3174             f1_k[i]   =  h1[i] + g1[i];
3175             f1_l[i]   = -h1[i];
3176
3177             f[a1i][i] = f[a1i][i] + f1_i[i];
3178             f[a1j][i] = f[a1j][i] + f1_j[i]; /* - f1[i] - g1[i] */
3179             f[a1k][i] = f[a1k][i] + f1_k[i]; /* h1[i] + g1[i] */
3180             f[a1l][i] = f[a1l][i] + f1_l[i]; /* h1[i] */
3181         }
3182
3183         /* Do forces - second torsion */
3184         fg2       = iprod(r2_ij, r2_kj);
3185         hg2       = iprod(r2_kl, r2_kj);
3186         fga2      = fg2*ra2r2*rgr2;
3187         hgb2      = hg2*rb2r2*rgr2;
3188         gaa2      = -ra2r2*rg2;
3189         gbb2      = rb2r2*rg2;
3190
3191         for (i = 0; i < DIM; i++)
3192         {
3193             dtf2[i]   = gaa2 * a2[i];
3194             dtg2[i]   = fga2 * a2[i] - hgb2 * b2[i];
3195             dth2[i]   = gbb2 * b2[i];
3196
3197             f2[i]     = df2  * dtf2[i];
3198             g2[i]     = df2  * dtg2[i];
3199             h2[i]     = df2  * dth2[i];
3200
3201             f2_i[i]   =  f2[i];
3202             f2_j[i]   = -f2[i] - g2[i];
3203             f2_k[i]   =  h2[i] + g2[i];
3204             f2_l[i]   = -h2[i];
3205
3206             f[a2i][i] = f[a2i][i] + f2_i[i]; /* f2[i] */
3207             f[a2j][i] = f[a2j][i] + f2_j[i]; /* - f2[i] - g2[i] */
3208             f[a2k][i] = f[a2k][i] + f2_k[i]; /* h2[i] + g2[i] */
3209             f[a2l][i] = f[a2l][i] + f2_l[i]; /* - h2[i] */
3210         }
3211
3212         /* Shift forces */
3213         if (g)
3214         {
3215             copy_ivec(SHIFT_IVEC(g, a1j), jt1);
3216             ivec_sub(SHIFT_IVEC(g, a1i),  jt1, dt1_ij);
3217             ivec_sub(SHIFT_IVEC(g, a1k),  jt1, dt1_kj);
3218             ivec_sub(SHIFT_IVEC(g, a1l),  jt1, dt1_lj);
3219             t11 = IVEC2IS(dt1_ij);
3220             t21 = IVEC2IS(dt1_kj);
3221             t31 = IVEC2IS(dt1_lj);
3222
3223             copy_ivec(SHIFT_IVEC(g, a2j), jt2);
3224             ivec_sub(SHIFT_IVEC(g, a2i),  jt2, dt2_ij);
3225             ivec_sub(SHIFT_IVEC(g, a2k),  jt2, dt2_kj);
3226             ivec_sub(SHIFT_IVEC(g, a2l),  jt2, dt2_lj);
3227             t12 = IVEC2IS(dt2_ij);
3228             t22 = IVEC2IS(dt2_kj);
3229             t32 = IVEC2IS(dt2_lj);
3230         }
3231         else if (pbc)
3232         {
3233             t31 = pbc_rvec_sub(pbc, x[a1l], x[a1j], h1);
3234             t32 = pbc_rvec_sub(pbc, x[a2l], x[a2j], h2);
3235         }
3236         else
3237         {
3238             t31 = CENTRAL;
3239             t32 = CENTRAL;
3240         }
3241
3242         rvec_inc(fshift[t11], f1_i);
3243         rvec_inc(fshift[CENTRAL], f1_j);
3244         rvec_inc(fshift[t21], f1_k);
3245         rvec_inc(fshift[t31], f1_l);
3246
3247         rvec_inc(fshift[t21], f2_i);
3248         rvec_inc(fshift[CENTRAL], f2_j);
3249         rvec_inc(fshift[t22], f2_k);
3250         rvec_inc(fshift[t32], f2_l);
3251     }
3252     return vtot;
3253 }
3254
3255
3256 //! \cond
3257 /***********************************************************
3258  *
3259  *   G R O M O S  9 6   F U N C T I O N S
3260  *
3261  ***********************************************************/
3262 static real g96harmonic(real kA, real kB, real xA, real xB, real x, real lambda,
3263                         real *V, real *F)
3264 {
3265     const real half = 0.5;
3266     real       L1, kk, x0, dx, dx2;
3267     real       v, f, dvdlambda;
3268
3269     L1    = 1.0-lambda;
3270     kk    = L1*kA+lambda*kB;
3271     x0    = L1*xA+lambda*xB;
3272
3273     dx    = x-x0;
3274     dx2   = dx*dx;
3275
3276     f          = -kk*dx;
3277     v          = half*kk*dx2;
3278     dvdlambda  = half*(kB-kA)*dx2 + (xA-xB)*kk*dx;
3279
3280     *F    = f;
3281     *V    = v;
3282
3283     return dvdlambda;
3284
3285     /* That was 21 flops */
3286 }
3287
3288 real g96bonds(int nbonds,
3289               const t_iatom forceatoms[], const t_iparams forceparams[],
3290               const rvec x[], rvec4 f[], rvec fshift[],
3291               const t_pbc *pbc, const t_graph *g,
3292               real lambda, real *dvdlambda,
3293               const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
3294               int gmx_unused *global_atom_index)
3295 {
3296     int  i, m, ki, ai, aj, type;
3297     real dr2, fbond, vbond, fij, vtot;
3298     rvec dx;
3299     ivec dt;
3300
3301     vtot = 0.0;
3302     for (i = 0; (i < nbonds); )
3303     {
3304         type = forceatoms[i++];
3305         ai   = forceatoms[i++];
3306         aj   = forceatoms[i++];
3307
3308         ki   = pbc_rvec_sub(pbc, x[ai], x[aj], dx); /*   3      */
3309         dr2  = iprod(dx, dx);                       /*   5              */
3310
3311         *dvdlambda += g96harmonic(forceparams[type].harmonic.krA,
3312                                   forceparams[type].harmonic.krB,
3313                                   forceparams[type].harmonic.rA,
3314                                   forceparams[type].harmonic.rB,
3315                                   dr2, lambda, &vbond, &fbond);
3316
3317         vtot  += 0.5*vbond;                         /* 1*/
3318 #ifdef DEBUG
3319         if (debug)
3320         {
3321             fprintf(debug, "G96-BONDS: dr = %10g  vbond = %10g  fbond = %10g\n",
3322                     sqrt(dr2), vbond, fbond);
3323         }
3324 #endif
3325
3326         if (g)
3327         {
3328             ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
3329             ki = IVEC2IS(dt);
3330         }
3331         for (m = 0; (m < DIM); m++)     /*  15          */
3332         {
3333             fij                 = fbond*dx[m];
3334             f[ai][m]           += fij;
3335             f[aj][m]           -= fij;
3336             fshift[ki][m]      += fij;
3337             fshift[CENTRAL][m] -= fij;
3338         }
3339     }               /* 44 TOTAL */
3340     return vtot;
3341 }
3342
3343 static real g96bond_angle(const rvec xi, const rvec xj, const rvec xk, const t_pbc *pbc,
3344                           rvec r_ij, rvec r_kj,
3345                           int *t1, int *t2)
3346 /* Return value is the angle between the bonds i-j and j-k */
3347 {
3348     real costh;
3349
3350     *t1 = pbc_rvec_sub(pbc, xi, xj, r_ij); /*  3                */
3351     *t2 = pbc_rvec_sub(pbc, xk, xj, r_kj); /*  3                */
3352
3353     costh = cos_angle(r_ij, r_kj);         /* 25                */
3354     /* 41 TOTAL */
3355     return costh;
3356 }
3357
3358 real g96angles(int nbonds,
3359                const t_iatom forceatoms[], const t_iparams forceparams[],
3360                const rvec x[], rvec4 f[], rvec fshift[],
3361                const t_pbc *pbc, const t_graph *g,
3362                real lambda, real *dvdlambda,
3363                const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
3364                int gmx_unused *global_atom_index)
3365 {
3366     int  i, ai, aj, ak, type, m, t1, t2;
3367     rvec r_ij, r_kj;
3368     real cos_theta, dVdt, va, vtot;
3369     real rij_1, rij_2, rkj_1, rkj_2, rijrkj_1;
3370     rvec f_i, f_j, f_k;
3371     ivec jt, dt_ij, dt_kj;
3372
3373     vtot = 0.0;
3374     for (i = 0; (i < nbonds); )
3375     {
3376         type = forceatoms[i++];
3377         ai   = forceatoms[i++];
3378         aj   = forceatoms[i++];
3379         ak   = forceatoms[i++];
3380
3381         cos_theta  = g96bond_angle(x[ai], x[aj], x[ak], pbc, r_ij, r_kj, &t1, &t2);
3382
3383         *dvdlambda += g96harmonic(forceparams[type].harmonic.krA,
3384                                   forceparams[type].harmonic.krB,
3385                                   forceparams[type].harmonic.rA,
3386                                   forceparams[type].harmonic.rB,
3387                                   cos_theta, lambda, &va, &dVdt);
3388         vtot    += va;
3389
3390         rij_1    = gmx::invsqrt(iprod(r_ij, r_ij));
3391         rkj_1    = gmx::invsqrt(iprod(r_kj, r_kj));
3392         rij_2    = rij_1*rij_1;
3393         rkj_2    = rkj_1*rkj_1;
3394         rijrkj_1 = rij_1*rkj_1;                 /* 23 */
3395
3396 #ifdef DEBUG
3397         if (debug)
3398         {
3399             fprintf(debug, "G96ANGLES: costheta = %10g  vth = %10g  dV/dct = %10g\n",
3400                     cos_theta, va, dVdt);
3401         }
3402 #endif
3403         for (m = 0; (m < DIM); m++)     /*  42  */
3404         {
3405             f_i[m]    = dVdt*(r_kj[m]*rijrkj_1 - r_ij[m]*rij_2*cos_theta);
3406             f_k[m]    = dVdt*(r_ij[m]*rijrkj_1 - r_kj[m]*rkj_2*cos_theta);
3407             f_j[m]    = -f_i[m]-f_k[m];
3408             f[ai][m] += f_i[m];
3409             f[aj][m] += f_j[m];
3410             f[ak][m] += f_k[m];
3411         }
3412
3413         if (g)
3414         {
3415             copy_ivec(SHIFT_IVEC(g, aj), jt);
3416
3417             ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
3418             ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
3419             t1 = IVEC2IS(dt_ij);
3420             t2 = IVEC2IS(dt_kj);
3421         }
3422         rvec_inc(fshift[t1], f_i);
3423         rvec_inc(fshift[CENTRAL], f_j);
3424         rvec_inc(fshift[t2], f_k);          /* 9 */
3425         /* 163 TOTAL    */
3426     }
3427     return vtot;
3428 }
3429
3430 real cross_bond_bond(int nbonds,
3431                      const t_iatom forceatoms[], const t_iparams forceparams[],
3432                      const rvec x[], rvec4 f[], rvec fshift[],
3433                      const t_pbc *pbc, const t_graph *g,
3434                      real gmx_unused lambda, real gmx_unused *dvdlambda,
3435                      const t_mdatoms gmx_unused *md, t_fcdata gmx_unused  *fcd,
3436                      int gmx_unused *global_atom_index)
3437 {
3438     /* Potential from Lawrence and Skimmer, Chem. Phys. Lett. 372 (2003)
3439      * pp. 842-847
3440      */
3441     int  i, ai, aj, ak, type, m, t1, t2;
3442     rvec r_ij, r_kj;
3443     real vtot, vrr, s1, s2, r1, r2, r1e, r2e, krr;
3444     rvec f_i, f_j, f_k;
3445     ivec jt, dt_ij, dt_kj;
3446
3447     vtot = 0.0;
3448     for (i = 0; (i < nbonds); )
3449     {
3450         type = forceatoms[i++];
3451         ai   = forceatoms[i++];
3452         aj   = forceatoms[i++];
3453         ak   = forceatoms[i++];
3454         r1e  = forceparams[type].cross_bb.r1e;
3455         r2e  = forceparams[type].cross_bb.r2e;
3456         krr  = forceparams[type].cross_bb.krr;
3457
3458         /* Compute distance vectors ... */
3459         t1 = pbc_rvec_sub(pbc, x[ai], x[aj], r_ij);
3460         t2 = pbc_rvec_sub(pbc, x[ak], x[aj], r_kj);
3461
3462         /* ... and their lengths */
3463         r1 = norm(r_ij);
3464         r2 = norm(r_kj);
3465
3466         /* Deviations from ideality */
3467         s1 = r1-r1e;
3468         s2 = r2-r2e;
3469
3470         /* Energy (can be negative!) */
3471         vrr   = krr*s1*s2;
3472         vtot += vrr;
3473
3474         /* Forces */
3475         svmul(-krr*s2/r1, r_ij, f_i);
3476         svmul(-krr*s1/r2, r_kj, f_k);
3477
3478         for (m = 0; (m < DIM); m++)     /*  12  */
3479         {
3480             f_j[m]    = -f_i[m] - f_k[m];
3481             f[ai][m] += f_i[m];
3482             f[aj][m] += f_j[m];
3483             f[ak][m] += f_k[m];
3484         }
3485
3486         /* Virial stuff */
3487         if (g)
3488         {
3489             copy_ivec(SHIFT_IVEC(g, aj), jt);
3490
3491             ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
3492             ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
3493             t1 = IVEC2IS(dt_ij);
3494             t2 = IVEC2IS(dt_kj);
3495         }
3496         rvec_inc(fshift[t1], f_i);
3497         rvec_inc(fshift[CENTRAL], f_j);
3498         rvec_inc(fshift[t2], f_k);          /* 9 */
3499         /* 163 TOTAL    */
3500     }
3501     return vtot;
3502 }
3503
3504 real cross_bond_angle(int nbonds,
3505                       const t_iatom forceatoms[], const t_iparams forceparams[],
3506                       const rvec x[], rvec4 f[], rvec fshift[],
3507                       const t_pbc *pbc, const t_graph *g,
3508                       real gmx_unused lambda, real gmx_unused *dvdlambda,
3509                       const t_mdatoms gmx_unused *md, t_fcdata gmx_unused *fcd,
3510                       int gmx_unused *global_atom_index)
3511 {
3512     /* Potential from Lawrence and Skimmer, Chem. Phys. Lett. 372 (2003)
3513      * pp. 842-847
3514      */
3515     int  i, ai, aj, ak, type, m, t1, t2;
3516     rvec r_ij, r_kj, r_ik;
3517     real vtot, vrt, s1, s2, s3, r1, r2, r3, r1e, r2e, r3e, krt, k1, k2, k3;
3518     rvec f_i, f_j, f_k;
3519     ivec jt, dt_ij, dt_kj;
3520
3521     vtot = 0.0;
3522     for (i = 0; (i < nbonds); )
3523     {
3524         type = forceatoms[i++];
3525         ai   = forceatoms[i++];
3526         aj   = forceatoms[i++];
3527         ak   = forceatoms[i++];
3528         r1e  = forceparams[type].cross_ba.r1e;
3529         r2e  = forceparams[type].cross_ba.r2e;
3530         r3e  = forceparams[type].cross_ba.r3e;
3531         krt  = forceparams[type].cross_ba.krt;
3532
3533         /* Compute distance vectors ... */
3534         t1 = pbc_rvec_sub(pbc, x[ai], x[aj], r_ij);
3535         t2 = pbc_rvec_sub(pbc, x[ak], x[aj], r_kj);
3536         pbc_rvec_sub(pbc, x[ai], x[ak], r_ik);
3537
3538         /* ... and their lengths */
3539         r1 = norm(r_ij);
3540         r2 = norm(r_kj);
3541         r3 = norm(r_ik);
3542
3543         /* Deviations from ideality */
3544         s1 = r1-r1e;
3545         s2 = r2-r2e;
3546         s3 = r3-r3e;
3547
3548         /* Energy (can be negative!) */
3549         vrt   = krt*s3*(s1+s2);
3550         vtot += vrt;
3551
3552         /* Forces */
3553         k1 = -krt*(s3/r1);
3554         k2 = -krt*(s3/r2);
3555         k3 = -krt*(s1+s2)/r3;
3556         for (m = 0; (m < DIM); m++)
3557         {
3558             f_i[m] = k1*r_ij[m] + k3*r_ik[m];
3559             f_k[m] = k2*r_kj[m] - k3*r_ik[m];
3560             f_j[m] = -f_i[m] - f_k[m];
3561         }
3562
3563         for (m = 0; (m < DIM); m++)     /*  12  */
3564         {
3565             f[ai][m] += f_i[m];
3566             f[aj][m] += f_j[m];
3567             f[ak][m] += f_k[m];
3568         }
3569
3570         /* Virial stuff */
3571         if (g)
3572         {
3573             copy_ivec(SHIFT_IVEC(g, aj), jt);
3574
3575             ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
3576             ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
3577             t1 = IVEC2IS(dt_ij);
3578             t2 = IVEC2IS(dt_kj);
3579         }
3580         rvec_inc(fshift[t1], f_i);
3581         rvec_inc(fshift[CENTRAL], f_j);
3582         rvec_inc(fshift[t2], f_k);          /* 9 */
3583         /* 163 TOTAL    */
3584     }
3585     return vtot;
3586 }
3587
3588 static real bonded_tab(const char *type, int table_nr,
3589                        const bondedtable_t *table, real kA, real kB, real r,
3590                        real lambda, real *V, real *F)
3591 {
3592     real k, tabscale, *VFtab, rt, eps, eps2, Yt, Ft, Geps, Heps2, Fp, VV, FF;
3593     int  n0, nnn;
3594     real dvdlambda;
3595
3596     k = (1.0 - lambda)*kA + lambda*kB;
3597
3598     tabscale = table->scale;
3599     VFtab    = table->data;
3600
3601     rt    = r*tabscale;
3602     n0    = static_cast<int>(rt);
3603     if (n0 >= table->n)
3604     {
3605         gmx_fatal(FARGS, "A tabulated %s interaction table number %d is out of the table range: r %f, between table indices %d and %d, table length %d",
3606                   type, table_nr, r, n0, n0+1, table->n);
3607     }
3608     eps   = rt - n0;
3609     eps2  = eps*eps;
3610     nnn   = 4*n0;
3611     Yt    = VFtab[nnn];
3612     Ft    = VFtab[nnn+1];
3613     Geps  = VFtab[nnn+2]*eps;
3614     Heps2 = VFtab[nnn+3]*eps2;
3615     Fp    = Ft + Geps + Heps2;
3616     VV    = Yt + Fp*eps;
3617     FF    = Fp + Geps + 2.0*Heps2;
3618
3619     *F         = -k*FF*tabscale;
3620     *V         = k*VV;
3621     dvdlambda  = (kB - kA)*VV;
3622
3623     return dvdlambda;
3624
3625     /* That was 22 flops */
3626 }
3627
3628 real tab_bonds(int nbonds,
3629                const t_iatom forceatoms[], const t_iparams forceparams[],
3630                const rvec x[], rvec4 f[], rvec fshift[],
3631                const t_pbc *pbc, const t_graph *g,
3632                real lambda, real *dvdlambda,
3633                const t_mdatoms gmx_unused *md, t_fcdata *fcd,
3634                int gmx_unused  *global_atom_index)
3635 {
3636     int  i, m, ki, ai, aj, type, table;
3637     real dr, dr2, fbond, vbond, fij, vtot;
3638     rvec dx;
3639     ivec dt;
3640
3641     vtot = 0.0;
3642     for (i = 0; (i < nbonds); )
3643     {
3644         type = forceatoms[i++];
3645         ai   = forceatoms[i++];
3646         aj   = forceatoms[i++];
3647
3648         ki   = pbc_rvec_sub(pbc, x[ai], x[aj], dx); /*   3      */
3649         dr2  = iprod(dx, dx);                       /*   5              */
3650         dr   = dr2*gmx::invsqrt(dr2);               /*  10              */
3651
3652         table = forceparams[type].tab.table;
3653
3654         *dvdlambda += bonded_tab("bond", table,
3655                                  &fcd->bondtab[table],
3656                                  forceparams[type].tab.kA,
3657                                  forceparams[type].tab.kB,
3658                                  dr, lambda, &vbond, &fbond); /*  22 */
3659
3660         if (dr2 == 0.0)
3661         {
3662             continue;
3663         }
3664
3665
3666         vtot  += vbond;             /* 1*/
3667         fbond *= gmx::invsqrt(dr2); /*   6              */
3668 #ifdef DEBUG
3669         if (debug)
3670         {
3671             fprintf(debug, "TABBONDS: dr = %10g  vbond = %10g  fbond = %10g\n",
3672                     dr, vbond, fbond);
3673         }
3674 #endif
3675         if (g)
3676         {
3677             ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
3678             ki = IVEC2IS(dt);
3679         }
3680         for (m = 0; (m < DIM); m++)     /*  15          */
3681         {
3682             fij                 = fbond*dx[m];
3683             f[ai][m]           += fij;
3684             f[aj][m]           -= fij;
3685             fshift[ki][m]      += fij;
3686             fshift[CENTRAL][m] -= fij;
3687         }
3688     }               /* 62 TOTAL */
3689     return vtot;
3690 }
3691
3692 real tab_angles(int nbonds,
3693                 const t_iatom forceatoms[], const t_iparams forceparams[],
3694                 const rvec x[], rvec4 f[], rvec fshift[],
3695                 const t_pbc *pbc, const t_graph *g,
3696                 real lambda, real *dvdlambda,
3697                 const t_mdatoms gmx_unused  *md, t_fcdata *fcd,
3698                 int gmx_unused *global_atom_index)
3699 {
3700     int  i, ai, aj, ak, t1, t2, type, table;
3701     rvec r_ij, r_kj;
3702     real cos_theta, cos_theta2, theta, dVdt, va, vtot;
3703     ivec jt, dt_ij, dt_kj;
3704
3705     vtot = 0.0;
3706     for (i = 0; (i < nbonds); )
3707     {
3708         type = forceatoms[i++];
3709         ai   = forceatoms[i++];
3710         aj   = forceatoms[i++];
3711         ak   = forceatoms[i++];
3712
3713         theta  = bond_angle(x[ai], x[aj], x[ak], pbc,
3714                             r_ij, r_kj, &cos_theta, &t1, &t2); /*  41           */
3715
3716         table = forceparams[type].tab.table;
3717
3718         *dvdlambda += bonded_tab("angle", table,
3719                                  &fcd->angletab[table],
3720                                  forceparams[type].tab.kA,
3721                                  forceparams[type].tab.kB,
3722                                  theta, lambda, &va, &dVdt); /*  22  */
3723         vtot += va;
3724
3725         cos_theta2 = gmx::square(cos_theta);            /*   1          */
3726         if (cos_theta2 < 1)
3727         {
3728             int  m;
3729             real st, sth;
3730             real cik, cii, ckk;
3731             real nrkj2, nrij2;
3732             rvec f_i, f_j, f_k;
3733
3734             st  = dVdt*gmx::invsqrt(1 - cos_theta2); /*  12             */
3735             sth = st*cos_theta;                      /*   1             */
3736 #ifdef DEBUG
3737             if (debug)
3738             {
3739                 fprintf(debug, "ANGLES: theta = %10g  vth = %10g  dV/dtheta = %10g\n",
3740                         theta*RAD2DEG, va, dVdt);
3741             }
3742 #endif
3743             nrkj2 = iprod(r_kj, r_kj);  /*   5          */
3744             nrij2 = iprod(r_ij, r_ij);
3745
3746             cik = st*gmx::invsqrt(nrkj2*nrij2); /*  12          */
3747             cii = sth/nrij2;                    /*  10          */
3748             ckk = sth/nrkj2;                    /*  10          */
3749
3750             for (m = 0; (m < DIM); m++)         /*  39          */
3751             {
3752                 f_i[m]    = -(cik*r_kj[m]-cii*r_ij[m]);
3753                 f_k[m]    = -(cik*r_ij[m]-ckk*r_kj[m]);
3754                 f_j[m]    = -f_i[m]-f_k[m];
3755                 f[ai][m] += f_i[m];
3756                 f[aj][m] += f_j[m];
3757                 f[ak][m] += f_k[m];
3758             }
3759             if (g)
3760             {
3761                 copy_ivec(SHIFT_IVEC(g, aj), jt);
3762
3763                 ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
3764                 ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
3765                 t1 = IVEC2IS(dt_ij);
3766                 t2 = IVEC2IS(dt_kj);
3767             }
3768             rvec_inc(fshift[t1], f_i);
3769             rvec_inc(fshift[CENTRAL], f_j);
3770             rvec_inc(fshift[t2], f_k);
3771         }                                       /* 169 TOTAL    */
3772     }
3773     return vtot;
3774 }
3775
3776 real tab_dihs(int nbonds,
3777               const t_iatom forceatoms[], const t_iparams forceparams[],
3778               const rvec x[], rvec4 f[], rvec fshift[],
3779               const t_pbc *pbc, const t_graph *g,
3780               real lambda, real *dvdlambda,
3781               const t_mdatoms gmx_unused *md, t_fcdata *fcd,
3782               int gmx_unused *global_atom_index)
3783 {
3784     int  i, type, ai, aj, ak, al, table;
3785     int  t1, t2, t3;
3786     rvec r_ij, r_kj, r_kl, m, n;
3787     real phi, sign, ddphi, vpd, vtot;
3788
3789     vtot = 0.0;
3790     for (i = 0; (i < nbonds); )
3791     {
3792         type = forceatoms[i++];
3793         ai   = forceatoms[i++];
3794         aj   = forceatoms[i++];
3795         ak   = forceatoms[i++];
3796         al   = forceatoms[i++];
3797
3798         phi = dih_angle(x[ai], x[aj], x[ak], x[al], pbc, r_ij, r_kj, r_kl, m, n,
3799                         &sign, &t1, &t2, &t3);  /*  84  */
3800
3801         table = forceparams[type].tab.table;
3802
3803         /* Hopefully phi+M_PI never results in values < 0 */
3804         *dvdlambda += bonded_tab("dihedral", table,
3805                                  &fcd->dihtab[table],
3806                                  forceparams[type].tab.kA,
3807                                  forceparams[type].tab.kB,
3808                                  phi+M_PI, lambda, &vpd, &ddphi);
3809
3810         vtot += vpd;
3811         do_dih_fup(ai, aj, ak, al, -ddphi, r_ij, r_kj, r_kl, m, n,
3812                    f, fshift, pbc, g, x, t1, t2, t3); /* 112    */
3813
3814 #ifdef DEBUG
3815         fprintf(debug, "pdih: (%d,%d,%d,%d) phi=%g\n",
3816                 ai, aj, ak, al, phi);
3817 #endif
3818     } /* 227 TOTAL  */
3819
3820     return vtot;
3821 }
3822
3823 //! \endcond