2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
39 * \brief This file defines low-level functions necessary for
40 * computing energies and forces for listed interactions.
42 * \author Mark Abraham <mark.j.abraham@gmail.com>
44 * \ingroup module_listed-forces
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"
74 #include "listed-internal.h"
77 using namespace gmx
; // TODO: Remove when this file is moved into gmx namespace
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
100 /*! \brief Compute dx = xi - xj, modulo PBC if non-NULL
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
)
107 return pbc_dx_aiuc(pbc
, xi
, xj
, dx
);
111 rvec_sub(xi
, xj
, dx
);
116 /*! \brief Morse potential bond
118 * By Frank Everdij. Three parameters needed:
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
124 * Note: the potential is referenced to be +cb at infinite separation
125 * and zero at the equilibrium distance!
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
)
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
;
140 int i
, m
, ki
, type
, ai
, aj
;
144 for (i
= 0; (i
< nbonds
); )
146 type
= forceatoms
[i
++];
147 ai
= forceatoms
[i
++];
148 aj
= forceatoms
[i
++];
150 b0A
= forceparams
[type
].morse
.b0A
;
151 beA
= forceparams
[type
].morse
.betaA
;
152 cbA
= forceparams
[type
].morse
.cbA
;
154 b0B
= forceparams
[type
].morse
.b0B
;
155 beB
= forceparams
[type
].morse
.betaB
;
156 cbB
= forceparams
[type
].morse
.cbB
;
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 */
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 */
170 /* bonds are constrainted. This may _not_ include bond constraints if they are lambda dependent */
171 *dvdlambda
+= cbB
-cbA
;
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 */
181 *dvdlambda
+= (cbB
- cbA
) * omtemp
* omtemp
- (2-2*omtemp
)*omtemp
* cb
* ((b0B
-b0A
)*be
- (beB
-beA
)*(dr
-b0
)); /* 15 */
185 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, aj
), dt
);
189 for (m
= 0; (m
< DIM
); m
++) /* 15 */
194 fshift
[ki
][m
] += fij
;
195 fshift
[CENTRAL
][m
] -= fij
;
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
)
210 const real three
= 3.0;
211 const real two
= 2.0;
213 real dr
, dr2
, dist
, kdist
, kdist2
, fbond
, vbond
, fij
, vtot
;
215 int i
, m
, ki
, type
, ai
, aj
;
219 for (i
= 0; (i
< nbonds
); )
221 type
= forceatoms
[i
++];
222 ai
= forceatoms
[i
++];
223 aj
= forceatoms
[i
++];
225 b0
= forceparams
[type
].cubic
.b0
;
226 kb
= forceparams
[type
].cubic
.kb
;
227 kcub
= forceparams
[type
].cubic
.kcub
;
229 ki
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], dx
); /* 3 */
230 dr2
= iprod(dx
, dx
); /* 5 */
237 dr
= dr2
*gmx::invsqrt(dr2
); /* 10 */
242 vbond
= kdist2
+ kcub
*kdist2
*dist
;
243 fbond
= -(two
*kdist
+ three
*kdist2
*kcub
)/dr
;
245 vtot
+= vbond
; /* 21 */
249 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, aj
), dt
);
252 for (m
= 0; (m
< DIM
); m
++) /* 15 */
257 fshift
[ki
][m
] += fij
;
258 fshift
[CENTRAL
][m
] -= fij
;
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
)
272 const real half
= 0.5;
273 const real one
= 1.0;
275 real dr2
, bm2
, omdr2obm2
, fbond
, vbond
, fij
, vtot
;
277 int i
, m
, ki
, type
, ai
, aj
;
281 for (i
= 0; (i
< nbonds
); )
283 type
= forceatoms
[i
++];
284 ai
= forceatoms
[i
++];
285 aj
= forceatoms
[i
++];
287 bm
= forceparams
[type
].fene
.bm
;
288 kb
= forceparams
[type
].fene
.kb
;
290 ki
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], dx
); /* 3 */
291 dr2
= iprod(dx
, dx
); /* 5 */
303 "r^2 (%f) >= bm^2 (%f) in FENE bond between atoms %d and %d",
305 glatnr(global_atom_index
, ai
),
306 glatnr(global_atom_index
, aj
));
309 omdr2obm2
= one
- dr2
/bm2
;
311 vbond
= -half
*kb
*bm2
*std::log(omdr2obm2
);
312 fbond
= -kb
/omdr2obm2
;
314 vtot
+= vbond
; /* 35 */
318 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, aj
), dt
);
321 for (m
= 0; (m
< DIM
); m
++) /* 15 */
326 fshift
[ki
][m
] += fij
;
327 fshift
[CENTRAL
][m
] -= fij
;
333 static real
harmonic(real kA
, real kB
, real xA
, real xB
, real x
, real lambda
,
336 const real half
= 0.5;
337 real L1
, kk
, x0
, dx
, dx2
;
338 real v
, f
, dvdlambda
;
341 kk
= L1
*kA
+lambda
*kB
;
342 x0
= L1
*xA
+lambda
*xB
;
349 dvdlambda
= half
*(kB
-kA
)*dx2
+ (xA
-xB
)*kk
*dx
;
356 /* That was 19 flops */
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
)
368 int i
, m
, ki
, ai
, aj
, type
;
369 real dr
, dr2
, fbond
, vbond
, fij
, vtot
;
374 for (i
= 0; (i
< nbonds
); )
376 type
= forceatoms
[i
++];
377 ai
= forceatoms
[i
++];
378 aj
= forceatoms
[i
++];
380 ki
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], dx
); /* 3 */
381 dr2
= iprod(dx
, dx
); /* 5 */
382 dr
= std::sqrt(dr2
); /* 10 */
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 */
396 vtot
+= vbond
; /* 1*/
397 fbond
*= gmx::invsqrt(dr2
); /* 6 */
400 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, aj
), dt
);
403 for (m
= 0; (m
< DIM
); m
++) /* 15 */
408 fshift
[ki
][m
] += fij
;
409 fshift
[CENTRAL
][m
] -= fij
;
415 real
restraint_bonds(int nbonds
,
416 const t_iatom forceatoms
[], const t_iparams forceparams
[],
417 const rvec x
[], rvec4 f
[], rvec fshift
[],
418 const t_pbc
*pbc
, const t_graph
*g
,
419 real lambda
, real
*dvdlambda
,
420 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
421 int gmx_unused
*global_atom_index
)
423 int i
, m
, ki
, ai
, aj
, type
;
424 real dr
, dr2
, fbond
, vbond
, fij
, vtot
;
426 real low
, dlow
, up1
, dup1
, up2
, dup2
, k
, dk
;
434 for (i
= 0; (i
< nbonds
); )
436 type
= forceatoms
[i
++];
437 ai
= forceatoms
[i
++];
438 aj
= forceatoms
[i
++];
440 ki
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], dx
); /* 3 */
441 dr2
= iprod(dx
, dx
); /* 5 */
442 dr
= dr2
*gmx::invsqrt(dr2
); /* 10 */
444 low
= L1
*forceparams
[type
].restraint
.lowA
+ lambda
*forceparams
[type
].restraint
.lowB
;
445 dlow
= -forceparams
[type
].restraint
.lowA
+ forceparams
[type
].restraint
.lowB
;
446 up1
= L1
*forceparams
[type
].restraint
.up1A
+ lambda
*forceparams
[type
].restraint
.up1B
;
447 dup1
= -forceparams
[type
].restraint
.up1A
+ forceparams
[type
].restraint
.up1B
;
448 up2
= L1
*forceparams
[type
].restraint
.up2A
+ lambda
*forceparams
[type
].restraint
.up2B
;
449 dup2
= -forceparams
[type
].restraint
.up2A
+ forceparams
[type
].restraint
.up2B
;
450 k
= L1
*forceparams
[type
].restraint
.kA
+ lambda
*forceparams
[type
].restraint
.kB
;
451 dk
= -forceparams
[type
].restraint
.kA
+ forceparams
[type
].restraint
.kB
;
460 *dvdlambda
+= 0.5*dk
*drh2
- k
*dlow
*drh
;
473 *dvdlambda
+= 0.5*dk
*drh2
- k
*dup1
*drh
;
478 vbond
= k
*(up2
- up1
)*(0.5*(up2
- up1
) + drh
);
479 fbond
= -k
*(up2
- up1
);
480 *dvdlambda
+= dk
*(up2
- up1
)*(0.5*(up2
- up1
) + drh
)
481 + k
*(dup2
- dup1
)*(up2
- up1
+ drh
)
482 - k
*(up2
- up1
)*dup2
;
490 vtot
+= vbond
; /* 1*/
491 fbond
*= gmx::invsqrt(dr2
); /* 6 */
494 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, aj
), dt
);
497 for (m
= 0; (m
< DIM
); m
++) /* 15 */
502 fshift
[ki
][m
] += fij
;
503 fshift
[CENTRAL
][m
] -= fij
;
510 real
polarize(int nbonds
,
511 const t_iatom forceatoms
[], const t_iparams forceparams
[],
512 const rvec x
[], rvec4 f
[], rvec fshift
[],
513 const t_pbc
*pbc
, const t_graph
*g
,
514 real lambda
, real
*dvdlambda
,
515 const t_mdatoms
*md
, t_fcdata gmx_unused
*fcd
,
516 int gmx_unused
*global_atom_index
)
518 int i
, m
, ki
, ai
, aj
, type
;
519 real dr
, dr2
, fbond
, vbond
, fij
, vtot
, ksh
;
524 for (i
= 0; (i
< nbonds
); )
526 type
= forceatoms
[i
++];
527 ai
= forceatoms
[i
++];
528 aj
= forceatoms
[i
++];
529 ksh
= gmx::square(md
->chargeA
[aj
])*ONE_4PI_EPS0
/forceparams
[type
].polarize
.alpha
;
531 ki
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], dx
); /* 3 */
532 dr2
= iprod(dx
, dx
); /* 5 */
533 dr
= std::sqrt(dr2
); /* 10 */
535 *dvdlambda
+= harmonic(ksh
, ksh
, 0, 0, dr
, lambda
, &vbond
, &fbond
); /* 19 */
542 vtot
+= vbond
; /* 1*/
543 fbond
*= gmx::invsqrt(dr2
); /* 6 */
547 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, aj
), dt
);
550 for (m
= 0; (m
< DIM
); m
++) /* 15 */
555 fshift
[ki
][m
] += fij
;
556 fshift
[CENTRAL
][m
] -= fij
;
562 real
anharm_polarize(int nbonds
,
563 const t_iatom forceatoms
[], const t_iparams forceparams
[],
564 const rvec x
[], rvec4 f
[], rvec fshift
[],
565 const t_pbc
*pbc
, const t_graph
*g
,
566 real lambda
, real
*dvdlambda
,
567 const t_mdatoms
*md
, t_fcdata gmx_unused
*fcd
,
568 int gmx_unused
*global_atom_index
)
570 int i
, m
, ki
, ai
, aj
, type
;
571 real dr
, dr2
, fbond
, vbond
, fij
, vtot
, ksh
, khyp
, drcut
, ddr
, ddr3
;
576 for (i
= 0; (i
< nbonds
); )
578 type
= forceatoms
[i
++];
579 ai
= forceatoms
[i
++];
580 aj
= forceatoms
[i
++];
581 ksh
= gmx::square(md
->chargeA
[aj
])*ONE_4PI_EPS0
/forceparams
[type
].anharm_polarize
.alpha
; /* 7*/
582 khyp
= forceparams
[type
].anharm_polarize
.khyp
;
583 drcut
= forceparams
[type
].anharm_polarize
.drcut
;
585 ki
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], dx
); /* 3 */
586 dr2
= iprod(dx
, dx
); /* 5 */
587 dr
= dr2
*gmx::invsqrt(dr2
); /* 10 */
589 *dvdlambda
+= harmonic(ksh
, ksh
, 0, 0, dr
, lambda
, &vbond
, &fbond
); /* 19 */
600 vbond
+= khyp
*ddr
*ddr3
;
601 fbond
-= 4*khyp
*ddr3
;
603 fbond
*= gmx::invsqrt(dr2
); /* 6 */
604 vtot
+= vbond
; /* 1*/
608 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, aj
), dt
);
611 for (m
= 0; (m
< DIM
); m
++) /* 15 */
616 fshift
[ki
][m
] += fij
;
617 fshift
[CENTRAL
][m
] -= fij
;
623 real
water_pol(int nbonds
,
624 const t_iatom forceatoms
[], const t_iparams forceparams
[],
625 const rvec x
[], rvec4 f
[], rvec gmx_unused fshift
[],
626 const t_pbc gmx_unused
*pbc
, const t_graph gmx_unused
*g
,
627 real gmx_unused lambda
, real gmx_unused
*dvdlambda
,
628 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
629 int gmx_unused
*global_atom_index
)
631 /* This routine implements anisotropic polarizibility for water, through
632 * a shell connected to a dummy with spring constant that differ in the
633 * three spatial dimensions in the molecular frame.
635 int i
, m
, aO
, aH1
, aH2
, aD
, aS
, type
, type0
, ki
;
637 rvec dOH1
, dOH2
, dHH
, dOD
, dDS
, nW
, kk
, dx
, kdx
, proj
;
638 real vtot
, fij
, r_HH
, r_OD
, r_nW
, tx
, ty
, tz
, qS
;
643 type0
= forceatoms
[0];
645 qS
= md
->chargeA
[aS
];
646 kk
[XX
] = gmx::square(qS
)*ONE_4PI_EPS0
/forceparams
[type0
].wpol
.al_x
;
647 kk
[YY
] = gmx::square(qS
)*ONE_4PI_EPS0
/forceparams
[type0
].wpol
.al_y
;
648 kk
[ZZ
] = gmx::square(qS
)*ONE_4PI_EPS0
/forceparams
[type0
].wpol
.al_z
;
649 r_HH
= 1.0/forceparams
[type0
].wpol
.rHH
;
650 for (i
= 0; (i
< nbonds
); i
+= 6)
652 type
= forceatoms
[i
];
655 gmx_fatal(FARGS
, "Sorry, type = %d, type0 = %d, file = %s, line = %d",
656 type
, type0
, __FILE__
, __LINE__
);
658 aO
= forceatoms
[i
+1];
659 aH1
= forceatoms
[i
+2];
660 aH2
= forceatoms
[i
+3];
661 aD
= forceatoms
[i
+4];
662 aS
= forceatoms
[i
+5];
664 /* Compute vectors describing the water frame */
665 pbc_rvec_sub(pbc
, x
[aH1
], x
[aO
], dOH1
);
666 pbc_rvec_sub(pbc
, x
[aH2
], x
[aO
], dOH2
);
667 pbc_rvec_sub(pbc
, x
[aH2
], x
[aH1
], dHH
);
668 pbc_rvec_sub(pbc
, x
[aD
], x
[aO
], dOD
);
669 ki
= pbc_rvec_sub(pbc
, x
[aS
], x
[aD
], dDS
);
670 cprod(dOH1
, dOH2
, nW
);
672 /* Compute inverse length of normal vector
673 * (this one could be precomputed, but I'm too lazy now)
675 r_nW
= gmx::invsqrt(iprod(nW
, nW
));
676 /* This is for precision, but does not make a big difference,
679 r_OD
= gmx::invsqrt(iprod(dOD
, dOD
));
681 /* Normalize the vectors in the water frame */
683 svmul(r_HH
, dHH
, dHH
);
684 svmul(r_OD
, dOD
, dOD
);
686 /* Compute displacement of shell along components of the vector */
687 dx
[ZZ
] = iprod(dDS
, dOD
);
688 /* Compute projection on the XY plane: dDS - dx[ZZ]*dOD */
689 for (m
= 0; (m
< DIM
); m
++)
691 proj
[m
] = dDS
[m
]-dx
[ZZ
]*dOD
[m
];
694 /*dx[XX] = iprod(dDS,nW);
695 dx[YY] = iprod(dDS,dHH);*/
696 dx
[XX
] = iprod(proj
, nW
);
697 for (m
= 0; (m
< DIM
); m
++)
699 proj
[m
] -= dx
[XX
]*nW
[m
];
701 dx
[YY
] = iprod(proj
, dHH
);
702 /* Now compute the forces and energy */
703 kdx
[XX
] = kk
[XX
]*dx
[XX
];
704 kdx
[YY
] = kk
[YY
]*dx
[YY
];
705 kdx
[ZZ
] = kk
[ZZ
]*dx
[ZZ
];
706 vtot
+= iprod(dx
, kdx
);
710 ivec_sub(SHIFT_IVEC(g
, aS
), SHIFT_IVEC(g
, aD
), dt
);
714 for (m
= 0; (m
< DIM
); m
++)
716 /* This is a tensor operation but written out for speed */
723 fshift
[ki
][m
] += fij
;
724 fshift
[CENTRAL
][m
] -= fij
;
731 static real
do_1_thole(const rvec xi
, const rvec xj
, rvec fi
, rvec fj
,
732 const t_pbc
*pbc
, real qq
,
733 rvec fshift
[], real afac
)
736 real r12sq
, r12_1
, r12bar
, v0
, v1
, fscal
, ebar
, fff
;
739 t
= pbc_rvec_sub(pbc
, xi
, xj
, r12
); /* 3 */
741 r12sq
= iprod(r12
, r12
); /* 5 */
742 r12_1
= gmx::invsqrt(r12sq
); /* 5 */
743 r12bar
= afac
/r12_1
; /* 5 */
744 v0
= qq
*ONE_4PI_EPS0
*r12_1
; /* 2 */
745 ebar
= std::exp(-r12bar
); /* 5 */
746 v1
= (1-(1+0.5*r12bar
)*ebar
); /* 4 */
747 fscal
= ((v0
*r12_1
)*v1
- v0
*0.5*afac
*ebar
*(r12bar
+1))*r12_1
; /* 9 */
749 for (m
= 0; (m
< DIM
); m
++)
755 fshift
[CENTRAL
][m
] -= fff
;
758 return v0
*v1
; /* 1 */
762 real
thole_pol(int nbonds
,
763 const t_iatom forceatoms
[], const t_iparams forceparams
[],
764 const rvec x
[], rvec4 f
[], rvec fshift
[],
765 const t_pbc
*pbc
, const t_graph gmx_unused
*g
,
766 real gmx_unused lambda
, real gmx_unused
*dvdlambda
,
767 const t_mdatoms
*md
, t_fcdata gmx_unused
*fcd
,
768 int gmx_unused
*global_atom_index
)
770 /* Interaction between two pairs of particles with opposite charge */
771 int i
, type
, a1
, da1
, a2
, da2
;
772 real q1
, q2
, qq
, a
, al1
, al2
, afac
;
775 for (i
= 0; (i
< nbonds
); )
777 type
= forceatoms
[i
++];
778 a1
= forceatoms
[i
++];
779 da1
= forceatoms
[i
++];
780 a2
= forceatoms
[i
++];
781 da2
= forceatoms
[i
++];
782 q1
= md
->chargeA
[da1
];
783 q2
= md
->chargeA
[da2
];
784 a
= forceparams
[type
].thole
.a
;
785 al1
= forceparams
[type
].thole
.alpha1
;
786 al2
= forceparams
[type
].thole
.alpha2
;
788 afac
= a
*gmx::invsixthroot(al1
*al2
);
789 V
+= do_1_thole(x
[a1
], x
[a2
], f
[a1
], f
[a2
], pbc
, qq
, fshift
, afac
);
790 V
+= do_1_thole(x
[da1
], x
[a2
], f
[da1
], f
[a2
], pbc
, -qq
, fshift
, afac
);
791 V
+= do_1_thole(x
[a1
], x
[da2
], f
[a1
], f
[da2
], pbc
, -qq
, fshift
, afac
);
792 V
+= do_1_thole(x
[da1
], x
[da2
], f
[da1
], f
[da2
], pbc
, qq
, fshift
, afac
);
798 real
bond_angle(const rvec xi
, const rvec xj
, const rvec xk
, const t_pbc
*pbc
,
799 rvec r_ij
, rvec r_kj
, real
*costh
,
801 /* Return value is the angle between the bonds i-j and j-k */
806 *t1
= pbc_rvec_sub(pbc
, xi
, xj
, r_ij
); /* 3 */
807 *t2
= pbc_rvec_sub(pbc
, xk
, xj
, r_kj
); /* 3 */
809 *costh
= cos_angle(r_ij
, r_kj
); /* 25 */
810 th
= std::acos(*costh
); /* 10 */
815 real
angles(int nbonds
,
816 const t_iatom forceatoms
[], const t_iparams forceparams
[],
817 const rvec x
[], rvec4 f
[], rvec fshift
[],
818 const t_pbc
*pbc
, const t_graph
*g
,
819 real lambda
, real
*dvdlambda
,
820 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
821 int gmx_unused
*global_atom_index
)
823 int i
, ai
, aj
, ak
, t1
, t2
, type
;
825 real cos_theta
, cos_theta2
, theta
, dVdt
, va
, vtot
;
826 ivec jt
, dt_ij
, dt_kj
;
829 for (i
= 0; i
< nbonds
; )
831 type
= forceatoms
[i
++];
832 ai
= forceatoms
[i
++];
833 aj
= forceatoms
[i
++];
834 ak
= forceatoms
[i
++];
836 theta
= bond_angle(x
[ai
], x
[aj
], x
[ak
], pbc
,
837 r_ij
, r_kj
, &cos_theta
, &t1
, &t2
); /* 41 */
839 *dvdlambda
+= harmonic(forceparams
[type
].harmonic
.krA
,
840 forceparams
[type
].harmonic
.krB
,
841 forceparams
[type
].harmonic
.rA
*DEG2RAD
,
842 forceparams
[type
].harmonic
.rB
*DEG2RAD
,
843 theta
, lambda
, &va
, &dVdt
); /* 21 */
846 cos_theta2
= gmx::square(cos_theta
);
856 st
= dVdt
*gmx::invsqrt(1 - cos_theta2
); /* 12 */
857 sth
= st
*cos_theta
; /* 1 */
858 nrij2
= iprod(r_ij
, r_ij
); /* 5 */
859 nrkj2
= iprod(r_kj
, r_kj
); /* 5 */
861 nrij_1
= gmx::invsqrt(nrij2
); /* 10 */
862 nrkj_1
= gmx::invsqrt(nrkj2
); /* 10 */
864 cik
= st
*nrij_1
*nrkj_1
; /* 2 */
865 cii
= sth
*nrij_1
*nrij_1
; /* 2 */
866 ckk
= sth
*nrkj_1
*nrkj_1
; /* 2 */
868 for (m
= 0; m
< DIM
; m
++)
870 f_i
[m
] = -(cik
*r_kj
[m
] - cii
*r_ij
[m
]);
871 f_k
[m
] = -(cik
*r_ij
[m
] - ckk
*r_kj
[m
]);
872 f_j
[m
] = -f_i
[m
] - f_k
[m
];
879 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
881 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
882 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
886 rvec_inc(fshift
[t1
], f_i
);
887 rvec_inc(fshift
[CENTRAL
], f_j
);
888 rvec_inc(fshift
[t2
], f_k
);
895 #if GMX_SIMD_HAVE_REAL
897 /* As angles, but using SIMD to calculate many angles at once.
898 * This routines does not calculate energies and shift forces.
901 angles_noener_simd(int nbonds
,
902 const t_iatom forceatoms
[], const t_iparams forceparams
[],
903 const rvec x
[], rvec4 f
[],
904 const t_pbc
*pbc
, const t_graph gmx_unused
*g
,
905 real gmx_unused lambda
,
906 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
907 int gmx_unused
*global_atom_index
)
912 alignas(GMX_SIMD_ALIGNMENT
) std::int32_t ai
[GMX_SIMD_REAL_WIDTH
];
913 alignas(GMX_SIMD_ALIGNMENT
) std::int32_t aj
[GMX_SIMD_REAL_WIDTH
];
914 alignas(GMX_SIMD_ALIGNMENT
) std::int32_t ak
[GMX_SIMD_REAL_WIDTH
];
915 alignas(GMX_SIMD_ALIGNMENT
) real coeff
[2*GMX_SIMD_REAL_WIDTH
];
916 SimdReal
deg2rad_S(DEG2RAD
);
917 SimdReal xi_S
, yi_S
, zi_S
;
918 SimdReal xj_S
, yj_S
, zj_S
;
919 SimdReal xk_S
, yk_S
, zk_S
;
920 SimdReal k_S
, theta0_S
;
921 SimdReal rijx_S
, rijy_S
, rijz_S
;
922 SimdReal rkjx_S
, rkjy_S
, rkjz_S
;
924 SimdReal
min_one_plus_eps_S(-1.0 + 2.0*GMX_REAL_EPS
); // Smallest number > -1
927 SimdReal nrij2_S
, nrij_1_S
;
928 SimdReal nrkj2_S
, nrkj_1_S
;
929 SimdReal cos_S
, invsin_S
;
931 SimdReal st_S
, sth_S
;
932 SimdReal cik_S
, cii_S
, ckk_S
;
933 SimdReal f_ix_S
, f_iy_S
, f_iz_S
;
934 SimdReal f_kx_S
, f_ky_S
, f_kz_S
;
935 alignas(GMX_SIMD_ALIGNMENT
) real pbc_simd
[9*GMX_SIMD_REAL_WIDTH
];
937 set_pbc_simd(pbc
, pbc_simd
);
939 /* nbonds is the number of angles times nfa1, here we step GMX_SIMD_REAL_WIDTH angles */
940 for (i
= 0; (i
< nbonds
); i
+= GMX_SIMD_REAL_WIDTH
*nfa1
)
942 /* Collect atoms for GMX_SIMD_REAL_WIDTH angles.
943 * iu indexes into forceatoms, we should not let iu go beyond nbonds.
946 for (s
= 0; s
< GMX_SIMD_REAL_WIDTH
; s
++)
948 type
= forceatoms
[iu
];
949 ai
[s
] = forceatoms
[iu
+1];
950 aj
[s
] = forceatoms
[iu
+2];
951 ak
[s
] = forceatoms
[iu
+3];
953 /* At the end fill the arrays with the last atoms and 0 params */
954 if (i
+ s
*nfa1
< nbonds
)
956 coeff
[s
] = forceparams
[type
].harmonic
.krA
;
957 coeff
[GMX_SIMD_REAL_WIDTH
+s
] = forceparams
[type
].harmonic
.rA
;
959 if (iu
+ nfa1
< nbonds
)
967 coeff
[GMX_SIMD_REAL_WIDTH
+s
] = 0;
971 /* Store the non PBC corrected distances packed and aligned */
972 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), ai
, &xi_S
, &yi_S
, &zi_S
);
973 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), aj
, &xj_S
, &yj_S
, &zj_S
);
974 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), ak
, &xk_S
, &yk_S
, &zk_S
);
975 rijx_S
= xi_S
- xj_S
;
976 rijy_S
= yi_S
- yj_S
;
977 rijz_S
= zi_S
- zj_S
;
978 rkjx_S
= xk_S
- xj_S
;
979 rkjy_S
= yk_S
- yj_S
;
980 rkjz_S
= zk_S
- zj_S
;
982 k_S
= load
<SimdReal
>(coeff
);
983 theta0_S
= load
<SimdReal
>(coeff
+GMX_SIMD_REAL_WIDTH
) * deg2rad_S
;
985 pbc_correct_dx_simd(&rijx_S
, &rijy_S
, &rijz_S
, pbc_simd
);
986 pbc_correct_dx_simd(&rkjx_S
, &rkjy_S
, &rkjz_S
, pbc_simd
);
988 rij_rkj_S
= iprod(rijx_S
, rijy_S
, rijz_S
,
989 rkjx_S
, rkjy_S
, rkjz_S
);
991 nrij2_S
= norm2(rijx_S
, rijy_S
, rijz_S
);
992 nrkj2_S
= norm2(rkjx_S
, rkjy_S
, rkjz_S
);
994 nrij_1_S
= invsqrt(nrij2_S
);
995 nrkj_1_S
= invsqrt(nrkj2_S
);
997 cos_S
= rij_rkj_S
* nrij_1_S
* nrkj_1_S
;
999 /* To allow for 180 degrees, we take the max of cos and -1 + 1bit,
1000 * so we can safely get the 1/sin from 1/sqrt(1 - cos^2).
1001 * This also ensures that rounding errors would cause the argument
1002 * of simdAcos to be < -1.
1003 * Note that we do not take precautions for cos(0)=1, so the outer
1004 * atoms in an angle should not be on top of each other.
1006 cos_S
= max(cos_S
, min_one_plus_eps_S
);
1008 theta_S
= acos(cos_S
);
1010 invsin_S
= invsqrt( one_S
- cos_S
* cos_S
);
1012 st_S
= k_S
* (theta0_S
- theta_S
) * invsin_S
;
1013 sth_S
= st_S
* cos_S
;
1015 cik_S
= st_S
* nrij_1_S
* nrkj_1_S
;
1016 cii_S
= sth_S
* nrij_1_S
* nrij_1_S
;
1017 ckk_S
= sth_S
* nrkj_1_S
* nrkj_1_S
;
1019 f_ix_S
= cii_S
* rijx_S
;
1020 f_ix_S
= fnma(cik_S
, rkjx_S
, f_ix_S
);
1021 f_iy_S
= cii_S
* rijy_S
;
1022 f_iy_S
= fnma(cik_S
, rkjy_S
, f_iy_S
);
1023 f_iz_S
= cii_S
* rijz_S
;
1024 f_iz_S
= fnma(cik_S
, rkjz_S
, f_iz_S
);
1025 f_kx_S
= ckk_S
* rkjx_S
;
1026 f_kx_S
= fnma(cik_S
, rijx_S
, f_kx_S
);
1027 f_ky_S
= ckk_S
* rkjy_S
;
1028 f_ky_S
= fnma(cik_S
, rijy_S
, f_ky_S
);
1029 f_kz_S
= ckk_S
* rkjz_S
;
1030 f_kz_S
= fnma(cik_S
, rijz_S
, f_kz_S
);
1032 transposeScatterIncrU
<4>(reinterpret_cast<real
*>(f
), ai
, f_ix_S
, f_iy_S
, f_iz_S
);
1033 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
);
1034 transposeScatterIncrU
<4>(reinterpret_cast<real
*>(f
), ak
, f_kx_S
, f_ky_S
, f_kz_S
);
1038 #endif // GMX_SIMD_HAVE_REAL
1040 real
linear_angles(int nbonds
,
1041 const t_iatom forceatoms
[], const t_iparams forceparams
[],
1042 const rvec x
[], rvec4 f
[], rvec fshift
[],
1043 const t_pbc
*pbc
, const t_graph
*g
,
1044 real lambda
, real
*dvdlambda
,
1045 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
1046 int gmx_unused
*global_atom_index
)
1048 int i
, m
, ai
, aj
, ak
, t1
, t2
, type
;
1050 real L1
, kA
, kB
, aA
, aB
, dr
, dr2
, va
, vtot
, a
, b
, klin
;
1051 ivec jt
, dt_ij
, dt_kj
;
1052 rvec r_ij
, r_kj
, r_ik
, dx
;
1056 for (i
= 0; (i
< nbonds
); )
1058 type
= forceatoms
[i
++];
1059 ai
= forceatoms
[i
++];
1060 aj
= forceatoms
[i
++];
1061 ak
= forceatoms
[i
++];
1063 kA
= forceparams
[type
].linangle
.klinA
;
1064 kB
= forceparams
[type
].linangle
.klinB
;
1065 klin
= L1
*kA
+ lambda
*kB
;
1067 aA
= forceparams
[type
].linangle
.aA
;
1068 aB
= forceparams
[type
].linangle
.aB
;
1069 a
= L1
*aA
+lambda
*aB
;
1072 t1
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], r_ij
);
1073 t2
= pbc_rvec_sub(pbc
, x
[ak
], x
[aj
], r_kj
);
1074 rvec_sub(r_ij
, r_kj
, r_ik
);
1077 for (m
= 0; (m
< DIM
); m
++)
1079 dr
= -a
* r_ij
[m
] - b
* r_kj
[m
];
1084 f_j
[m
] = -(f_i
[m
]+f_k
[m
]);
1090 *dvdlambda
+= 0.5*(kB
-kA
)*dr2
+ klin
*(aB
-aA
)*iprod(dx
, r_ik
);
1096 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
1098 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
1099 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
1100 t1
= IVEC2IS(dt_ij
);
1101 t2
= IVEC2IS(dt_kj
);
1103 rvec_inc(fshift
[t1
], f_i
);
1104 rvec_inc(fshift
[CENTRAL
], f_j
);
1105 rvec_inc(fshift
[t2
], f_k
);
1110 real
urey_bradley(int nbonds
,
1111 const t_iatom forceatoms
[], const t_iparams forceparams
[],
1112 const rvec x
[], rvec4 f
[], rvec fshift
[],
1113 const t_pbc
*pbc
, const t_graph
*g
,
1114 real lambda
, real
*dvdlambda
,
1115 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
1116 int gmx_unused
*global_atom_index
)
1118 int i
, m
, ai
, aj
, ak
, t1
, t2
, type
, ki
;
1119 rvec r_ij
, r_kj
, r_ik
;
1120 real cos_theta
, cos_theta2
, theta
;
1121 real dVdt
, va
, vtot
, dr
, dr2
, vbond
, fbond
, fik
;
1122 real kthA
, th0A
, kUBA
, r13A
, kthB
, th0B
, kUBB
, r13B
;
1123 ivec jt
, dt_ij
, dt_kj
, dt_ik
;
1126 for (i
= 0; (i
< nbonds
); )
1128 type
= forceatoms
[i
++];
1129 ai
= forceatoms
[i
++];
1130 aj
= forceatoms
[i
++];
1131 ak
= forceatoms
[i
++];
1132 th0A
= forceparams
[type
].u_b
.thetaA
*DEG2RAD
;
1133 kthA
= forceparams
[type
].u_b
.kthetaA
;
1134 r13A
= forceparams
[type
].u_b
.r13A
;
1135 kUBA
= forceparams
[type
].u_b
.kUBA
;
1136 th0B
= forceparams
[type
].u_b
.thetaB
*DEG2RAD
;
1137 kthB
= forceparams
[type
].u_b
.kthetaB
;
1138 r13B
= forceparams
[type
].u_b
.r13B
;
1139 kUBB
= forceparams
[type
].u_b
.kUBB
;
1141 theta
= bond_angle(x
[ai
], x
[aj
], x
[ak
], pbc
,
1142 r_ij
, r_kj
, &cos_theta
, &t1
, &t2
); /* 41 */
1144 *dvdlambda
+= harmonic(kthA
, kthB
, th0A
, th0B
, theta
, lambda
, &va
, &dVdt
); /* 21 */
1147 ki
= pbc_rvec_sub(pbc
, x
[ai
], x
[ak
], r_ik
); /* 3 */
1148 dr2
= iprod(r_ik
, r_ik
); /* 5 */
1149 dr
= dr2
*gmx::invsqrt(dr2
); /* 10 */
1151 *dvdlambda
+= harmonic(kUBA
, kUBB
, r13A
, r13B
, dr
, lambda
, &vbond
, &fbond
); /* 19 */
1153 cos_theta2
= gmx::square(cos_theta
); /* 1 */
1161 st
= dVdt
*gmx::invsqrt(1 - cos_theta2
); /* 12 */
1162 sth
= st
*cos_theta
; /* 1 */
1163 nrkj2
= iprod(r_kj
, r_kj
); /* 5 */
1164 nrij2
= iprod(r_ij
, r_ij
);
1166 cik
= st
*gmx::invsqrt(nrkj2
*nrij2
); /* 12 */
1167 cii
= sth
/nrij2
; /* 10 */
1168 ckk
= sth
/nrkj2
; /* 10 */
1170 for (m
= 0; (m
< DIM
); m
++) /* 39 */
1172 f_i
[m
] = -(cik
*r_kj
[m
]-cii
*r_ij
[m
]);
1173 f_k
[m
] = -(cik
*r_ij
[m
]-ckk
*r_kj
[m
]);
1174 f_j
[m
] = -f_i
[m
]-f_k
[m
];
1181 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
1183 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
1184 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
1185 t1
= IVEC2IS(dt_ij
);
1186 t2
= IVEC2IS(dt_kj
);
1188 rvec_inc(fshift
[t1
], f_i
);
1189 rvec_inc(fshift
[CENTRAL
], f_j
);
1190 rvec_inc(fshift
[t2
], f_k
);
1192 /* Time for the bond calculations */
1198 vtot
+= vbond
; /* 1*/
1199 fbond
*= gmx::invsqrt(dr2
); /* 6 */
1203 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, ak
), dt_ik
);
1204 ki
= IVEC2IS(dt_ik
);
1206 for (m
= 0; (m
< DIM
); m
++) /* 15 */
1208 fik
= fbond
*r_ik
[m
];
1211 fshift
[ki
][m
] += fik
;
1212 fshift
[CENTRAL
][m
] -= fik
;
1218 #if GMX_SIMD_HAVE_REAL
1220 /* As urey_bradley, but using SIMD to calculate many potentials at once.
1221 * This routines does not calculate energies and shift forces.
1223 void urey_bradley_noener_simd(int nbonds
,
1224 const t_iatom forceatoms
[], const t_iparams forceparams
[],
1225 const rvec x
[], rvec4 f
[],
1226 const t_pbc
*pbc
, const t_graph gmx_unused
*g
,
1227 real gmx_unused lambda
,
1228 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
1229 int gmx_unused
*global_atom_index
)
1231 constexpr int nfa1
= 4;
1232 alignas(GMX_SIMD_ALIGNMENT
) std::int32_t ai
[GMX_SIMD_REAL_WIDTH
];
1233 alignas(GMX_SIMD_ALIGNMENT
) std::int32_t aj
[GMX_SIMD_REAL_WIDTH
];
1234 alignas(GMX_SIMD_ALIGNMENT
) std::int32_t ak
[GMX_SIMD_REAL_WIDTH
];
1235 alignas(GMX_SIMD_ALIGNMENT
) real coeff
[4*GMX_SIMD_REAL_WIDTH
];
1236 alignas(GMX_SIMD_ALIGNMENT
) real pbc_simd
[9*GMX_SIMD_REAL_WIDTH
];
1238 set_pbc_simd(pbc
, pbc_simd
);
1240 /* nbonds is the number of angles times nfa1, here we step GMX_SIMD_REAL_WIDTH angles */
1241 for (int i
= 0; i
< nbonds
; i
+= GMX_SIMD_REAL_WIDTH
*nfa1
)
1243 /* Collect atoms for GMX_SIMD_REAL_WIDTH angles.
1244 * iu indexes into forceatoms, we should not let iu go beyond nbonds.
1247 for (int s
= 0; s
< GMX_SIMD_REAL_WIDTH
; s
++)
1249 const int type
= forceatoms
[iu
];
1250 ai
[s
] = forceatoms
[iu
+1];
1251 aj
[s
] = forceatoms
[iu
+2];
1252 ak
[s
] = forceatoms
[iu
+3];
1254 /* At the end fill the arrays with the last atoms and 0 params */
1255 if (i
+ s
*nfa1
< nbonds
)
1257 coeff
[s
] = forceparams
[type
].u_b
.kthetaA
;
1258 coeff
[GMX_SIMD_REAL_WIDTH
+s
] = forceparams
[type
].u_b
.thetaA
;
1259 coeff
[GMX_SIMD_REAL_WIDTH
*2+s
] = forceparams
[type
].u_b
.kUBA
;
1260 coeff
[GMX_SIMD_REAL_WIDTH
*3+s
] = forceparams
[type
].u_b
.r13A
;
1262 if (iu
+ nfa1
< nbonds
)
1270 coeff
[GMX_SIMD_REAL_WIDTH
+s
] = 0;
1271 coeff
[GMX_SIMD_REAL_WIDTH
*2+s
] = 0;
1272 coeff
[GMX_SIMD_REAL_WIDTH
*3+s
] = 0;
1276 SimdReal xi_S
, yi_S
, zi_S
;
1277 SimdReal xj_S
, yj_S
, zj_S
;
1278 SimdReal xk_S
, yk_S
, zk_S
;
1280 /* Store the non PBC corrected distances packed and aligned */
1281 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), ai
, &xi_S
, &yi_S
, &zi_S
);
1282 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), aj
, &xj_S
, &yj_S
, &zj_S
);
1283 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), ak
, &xk_S
, &yk_S
, &zk_S
);
1284 SimdReal rijx_S
= xi_S
- xj_S
;
1285 SimdReal rijy_S
= yi_S
- yj_S
;
1286 SimdReal rijz_S
= zi_S
- zj_S
;
1287 SimdReal rkjx_S
= xk_S
- xj_S
;
1288 SimdReal rkjy_S
= yk_S
- yj_S
;
1289 SimdReal rkjz_S
= zk_S
- zj_S
;
1290 SimdReal rikx_S
= xi_S
- xk_S
;
1291 SimdReal riky_S
= yi_S
- yk_S
;
1292 SimdReal rikz_S
= zi_S
- zk_S
;
1294 const SimdReal ktheta_S
= load
<SimdReal
>(coeff
);
1295 const SimdReal theta0_S
= load
<SimdReal
>(coeff
+GMX_SIMD_REAL_WIDTH
) * DEG2RAD
;
1296 const SimdReal kUB_S
= load
<SimdReal
>(coeff
+2*GMX_SIMD_REAL_WIDTH
);
1297 const SimdReal r13_S
= load
<SimdReal
>(coeff
+3*GMX_SIMD_REAL_WIDTH
);
1299 pbc_correct_dx_simd(&rijx_S
, &rijy_S
, &rijz_S
, pbc_simd
);
1300 pbc_correct_dx_simd(&rkjx_S
, &rkjy_S
, &rkjz_S
, pbc_simd
);
1301 pbc_correct_dx_simd(&rikx_S
, &riky_S
, &rikz_S
, pbc_simd
);
1303 const SimdReal rij_rkj_S
= iprod(rijx_S
, rijy_S
, rijz_S
,
1304 rkjx_S
, rkjy_S
, rkjz_S
);
1306 const SimdReal dr2_S
= iprod(rikx_S
, riky_S
, rikz_S
,
1307 rikx_S
, riky_S
, rikz_S
);
1309 const SimdReal nrij2_S
= norm2(rijx_S
, rijy_S
, rijz_S
);
1310 const SimdReal nrkj2_S
= norm2(rkjx_S
, rkjy_S
, rkjz_S
);
1312 const SimdReal nrij_1_S
= invsqrt(nrij2_S
);
1313 const SimdReal nrkj_1_S
= invsqrt(nrkj2_S
);
1314 const SimdReal invdr2_S
= invsqrt(dr2_S
);
1315 const SimdReal dr_S
= dr2_S
*invdr2_S
;
1317 constexpr real min_one_plus_eps
= -1.0 + 2.0*GMX_REAL_EPS
; // Smallest number > -1
1319 /* To allow for 180 degrees, we take the max of cos and -1 + 1bit,
1320 * so we can safely get the 1/sin from 1/sqrt(1 - cos^2).
1321 * This also ensures that rounding errors would cause the argument
1322 * of simdAcos to be < -1.
1323 * Note that we do not take precautions for cos(0)=1, so the bonds
1324 * in an angle should not align at an angle of 0 degrees.
1326 const SimdReal cos_S
= max(rij_rkj_S
* nrij_1_S
* nrkj_1_S
, min_one_plus_eps
);
1328 const SimdReal theta_S
= acos(cos_S
);
1329 const SimdReal invsin_S
= invsqrt( 1.0 - cos_S
* cos_S
);
1330 const SimdReal st_S
= ktheta_S
* (theta0_S
- theta_S
) * invsin_S
;
1331 const SimdReal sth_S
= st_S
* cos_S
;
1333 const SimdReal cik_S
= st_S
* nrij_1_S
* nrkj_1_S
;
1334 const SimdReal cii_S
= sth_S
* nrij_1_S
* nrij_1_S
;
1335 const SimdReal ckk_S
= sth_S
* nrkj_1_S
* nrkj_1_S
;
1337 const SimdReal sUB_S
= kUB_S
* (r13_S
- dr_S
) * invdr2_S
;
1339 const SimdReal f_ikx_S
= sUB_S
* rikx_S
;
1340 const SimdReal f_iky_S
= sUB_S
* riky_S
;
1341 const SimdReal f_ikz_S
= sUB_S
* rikz_S
;
1343 const SimdReal f_ix_S
= fnma(cik_S
, rkjx_S
, cii_S
* rijx_S
) + f_ikx_S
;
1344 const SimdReal f_iy_S
= fnma(cik_S
, rkjy_S
, cii_S
* rijy_S
) + f_iky_S
;
1345 const SimdReal f_iz_S
= fnma(cik_S
, rkjz_S
, cii_S
* rijz_S
) + f_ikz_S
;
1346 const SimdReal f_kx_S
= fnma(cik_S
, rijx_S
, ckk_S
* rkjx_S
) - f_ikx_S
;
1347 const SimdReal f_ky_S
= fnma(cik_S
, rijy_S
, ckk_S
* rkjy_S
) - f_iky_S
;
1348 const SimdReal f_kz_S
= fnma(cik_S
, rijz_S
, ckk_S
* rkjz_S
) - f_ikz_S
;
1350 transposeScatterIncrU
<4>(reinterpret_cast<real
*>(f
), ai
, f_ix_S
, f_iy_S
, f_iz_S
);
1351 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
);
1352 transposeScatterIncrU
<4>(reinterpret_cast<real
*>(f
), ak
, f_kx_S
, f_ky_S
, f_kz_S
);
1356 #endif // GMX_SIMD_HAVE_REAL
1358 real
quartic_angles(int nbonds
,
1359 const t_iatom forceatoms
[], const t_iparams forceparams
[],
1360 const rvec x
[], rvec4 f
[], rvec fshift
[],
1361 const t_pbc
*pbc
, const t_graph
*g
,
1362 real gmx_unused lambda
, real gmx_unused
*dvdlambda
,
1363 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
1364 int gmx_unused
*global_atom_index
)
1366 int i
, j
, ai
, aj
, ak
, t1
, t2
, type
;
1368 real cos_theta
, cos_theta2
, theta
, dt
, dVdt
, va
, dtp
, c
, vtot
;
1369 ivec jt
, dt_ij
, dt_kj
;
1372 for (i
= 0; (i
< nbonds
); )
1374 type
= forceatoms
[i
++];
1375 ai
= forceatoms
[i
++];
1376 aj
= forceatoms
[i
++];
1377 ak
= forceatoms
[i
++];
1379 theta
= bond_angle(x
[ai
], x
[aj
], x
[ak
], pbc
,
1380 r_ij
, r_kj
, &cos_theta
, &t1
, &t2
); /* 41 */
1382 dt
= theta
- forceparams
[type
].qangle
.theta
*DEG2RAD
; /* 2 */
1385 va
= forceparams
[type
].qangle
.c
[0];
1387 for (j
= 1; j
<= 4; j
++)
1389 c
= forceparams
[type
].qangle
.c
[j
];
1398 cos_theta2
= gmx::square(cos_theta
); /* 1 */
1407 st
= dVdt
*gmx::invsqrt(1 - cos_theta2
); /* 12 */
1408 sth
= st
*cos_theta
; /* 1 */
1409 nrkj2
= iprod(r_kj
, r_kj
); /* 5 */
1410 nrij2
= iprod(r_ij
, r_ij
);
1412 cik
= st
*gmx::invsqrt(nrkj2
*nrij2
); /* 12 */
1413 cii
= sth
/nrij2
; /* 10 */
1414 ckk
= sth
/nrkj2
; /* 10 */
1416 for (m
= 0; (m
< DIM
); m
++) /* 39 */
1418 f_i
[m
] = -(cik
*r_kj
[m
]-cii
*r_ij
[m
]);
1419 f_k
[m
] = -(cik
*r_ij
[m
]-ckk
*r_kj
[m
]);
1420 f_j
[m
] = -f_i
[m
]-f_k
[m
];
1427 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
1429 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
1430 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
1431 t1
= IVEC2IS(dt_ij
);
1432 t2
= IVEC2IS(dt_kj
);
1434 rvec_inc(fshift
[t1
], f_i
);
1435 rvec_inc(fshift
[CENTRAL
], f_j
);
1436 rvec_inc(fshift
[t2
], f_k
);
1442 real
dih_angle(const rvec xi
, const rvec xj
, const rvec xk
, const rvec xl
,
1444 rvec r_ij
, rvec r_kj
, rvec r_kl
, rvec m
, rvec n
,
1445 int *t1
, int *t2
, int *t3
)
1447 *t1
= pbc_rvec_sub(pbc
, xi
, xj
, r_ij
); /* 3 */
1448 *t2
= pbc_rvec_sub(pbc
, xk
, xj
, r_kj
); /* 3 */
1449 *t3
= pbc_rvec_sub(pbc
, xk
, xl
, r_kl
); /* 3 */
1451 cprod(r_ij
, r_kj
, m
); /* 9 */
1452 cprod(r_kj
, r_kl
, n
); /* 9 */
1453 real phi
= gmx_angle(m
, n
); /* 49 (assuming 25 for atan2) */
1454 real ipr
= iprod(r_ij
, n
); /* 5 */
1455 real sign
= (ipr
< 0.0) ? -1.0 : 1.0;
1456 phi
= sign
*phi
; /* 1 */
1462 #if GMX_SIMD_HAVE_REAL
1464 /* As dih_angle above, but calculates 4 dihedral angles at once using SIMD,
1465 * also calculates the pre-factor required for the dihedral force update.
1466 * Note that bv and buf should be register aligned.
1469 dih_angle_simd(const rvec
*x
,
1470 const int *ai
, const int *aj
, const int *ak
, const int *al
,
1471 const real
*pbc_simd
,
1473 SimdReal
*mx_S
, SimdReal
*my_S
, SimdReal
*mz_S
,
1474 SimdReal
*nx_S
, SimdReal
*ny_S
, SimdReal
*nz_S
,
1475 SimdReal
*nrkj_m2_S
,
1476 SimdReal
*nrkj_n2_S
,
1480 SimdReal xi_S
, yi_S
, zi_S
;
1481 SimdReal xj_S
, yj_S
, zj_S
;
1482 SimdReal xk_S
, yk_S
, zk_S
;
1483 SimdReal xl_S
, yl_S
, zl_S
;
1484 SimdReal rijx_S
, rijy_S
, rijz_S
;
1485 SimdReal rkjx_S
, rkjy_S
, rkjz_S
;
1486 SimdReal rklx_S
, rkly_S
, rklz_S
;
1487 SimdReal cx_S
, cy_S
, cz_S
;
1491 SimdReal iprm_S
, iprn_S
;
1492 SimdReal nrkj2_S
, nrkj_1_S
, nrkj_2_S
, nrkj_S
;
1494 SimdReal nrkj2_min_S
;
1495 SimdReal real_eps_S
;
1497 /* Used to avoid division by zero.
1498 * We take into acount that we multiply the result by real_eps_S.
1500 nrkj2_min_S
= SimdReal(GMX_REAL_MIN
/(2*GMX_REAL_EPS
));
1502 /* The value of the last significant bit (GMX_REAL_EPS is half of that) */
1503 real_eps_S
= SimdReal(2*GMX_REAL_EPS
);
1505 /* Store the non PBC corrected distances packed and aligned */
1506 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), ai
, &xi_S
, &yi_S
, &zi_S
);
1507 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), aj
, &xj_S
, &yj_S
, &zj_S
);
1508 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), ak
, &xk_S
, &yk_S
, &zk_S
);
1509 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), al
, &xl_S
, &yl_S
, &zl_S
);
1510 rijx_S
= xi_S
- xj_S
;
1511 rijy_S
= yi_S
- yj_S
;
1512 rijz_S
= zi_S
- zj_S
;
1513 rkjx_S
= xk_S
- xj_S
;
1514 rkjy_S
= yk_S
- yj_S
;
1515 rkjz_S
= zk_S
- zj_S
;
1516 rklx_S
= xk_S
- xl_S
;
1517 rkly_S
= yk_S
- yl_S
;
1518 rklz_S
= zk_S
- zl_S
;
1520 pbc_correct_dx_simd(&rijx_S
, &rijy_S
, &rijz_S
, pbc_simd
);
1521 pbc_correct_dx_simd(&rkjx_S
, &rkjy_S
, &rkjz_S
, pbc_simd
);
1522 pbc_correct_dx_simd(&rklx_S
, &rkly_S
, &rklz_S
, pbc_simd
);
1524 cprod(rijx_S
, rijy_S
, rijz_S
,
1525 rkjx_S
, rkjy_S
, rkjz_S
,
1528 cprod(rkjx_S
, rkjy_S
, rkjz_S
,
1529 rklx_S
, rkly_S
, rklz_S
,
1532 cprod(*mx_S
, *my_S
, *mz_S
,
1533 *nx_S
, *ny_S
, *nz_S
,
1534 &cx_S
, &cy_S
, &cz_S
);
1536 cn_S
= sqrt(norm2(cx_S
, cy_S
, cz_S
));
1538 s_S
= iprod(*mx_S
, *my_S
, *mz_S
, *nx_S
, *ny_S
, *nz_S
);
1540 /* Determine the dihedral angle, the sign might need correction */
1541 *phi_S
= atan2(cn_S
, s_S
);
1543 ipr_S
= iprod(rijx_S
, rijy_S
, rijz_S
,
1544 *nx_S
, *ny_S
, *nz_S
);
1546 iprm_S
= norm2(*mx_S
, *my_S
, *mz_S
);
1547 iprn_S
= norm2(*nx_S
, *ny_S
, *nz_S
);
1549 nrkj2_S
= norm2(rkjx_S
, rkjy_S
, rkjz_S
);
1551 /* Avoid division by zero. When zero, the result is multiplied by 0
1552 * anyhow, so the 3 max below do not affect the final result.
1554 nrkj2_S
= max(nrkj2_S
, nrkj2_min_S
);
1555 nrkj_1_S
= invsqrt(nrkj2_S
);
1556 nrkj_2_S
= nrkj_1_S
* nrkj_1_S
;
1557 nrkj_S
= nrkj2_S
* nrkj_1_S
;
1559 toler_S
= nrkj2_S
* real_eps_S
;
1561 /* Here the plain-C code uses a conditional, but we can't do that in SIMD.
1562 * So we take a max with the tolerance instead. Since we multiply with
1563 * m or n later, the max does not affect the results.
1565 iprm_S
= max(iprm_S
, toler_S
);
1566 iprn_S
= max(iprn_S
, toler_S
);
1567 *nrkj_m2_S
= nrkj_S
* inv(iprm_S
);
1568 *nrkj_n2_S
= nrkj_S
* inv(iprn_S
);
1570 /* Set sign of phi_S with the sign of ipr_S; phi_S is currently positive */
1571 *phi_S
= copysign(*phi_S
, ipr_S
);
1572 *p_S
= iprod(rijx_S
, rijy_S
, rijz_S
, rkjx_S
, rkjy_S
, rkjz_S
);
1573 *p_S
= *p_S
* nrkj_2_S
;
1575 *q_S
= iprod(rklx_S
, rkly_S
, rklz_S
, rkjx_S
, rkjy_S
, rkjz_S
);
1576 *q_S
= *q_S
* nrkj_2_S
;
1579 #endif // GMX_SIMD_HAVE_REAL
1581 void do_dih_fup(int i
, int j
, int k
, int l
, real ddphi
,
1582 rvec r_ij
, rvec r_kj
, rvec r_kl
,
1583 rvec m
, rvec n
, rvec4 f
[], rvec fshift
[],
1584 const t_pbc
*pbc
, const t_graph
*g
,
1585 const rvec x
[], int t1
, int t2
, int t3
)
1588 rvec f_i
, f_j
, f_k
, f_l
;
1589 rvec uvec
, vvec
, svec
, dx_jl
;
1590 real iprm
, iprn
, nrkj
, nrkj2
, nrkj_1
, nrkj_2
;
1591 real a
, b
, p
, q
, toler
;
1592 ivec jt
, dt_ij
, dt_kj
, dt_lj
;
1594 iprm
= iprod(m
, m
); /* 5 */
1595 iprn
= iprod(n
, n
); /* 5 */
1596 nrkj2
= iprod(r_kj
, r_kj
); /* 5 */
1597 toler
= nrkj2
*GMX_REAL_EPS
;
1598 if ((iprm
> toler
) && (iprn
> toler
))
1600 nrkj_1
= gmx::invsqrt(nrkj2
); /* 10 */
1601 nrkj_2
= nrkj_1
*nrkj_1
; /* 1 */
1602 nrkj
= nrkj2
*nrkj_1
; /* 1 */
1603 a
= -ddphi
*nrkj
/iprm
; /* 11 */
1604 svmul(a
, m
, f_i
); /* 3 */
1605 b
= ddphi
*nrkj
/iprn
; /* 11 */
1606 svmul(b
, n
, f_l
); /* 3 */
1607 p
= iprod(r_ij
, r_kj
); /* 5 */
1608 p
*= nrkj_2
; /* 1 */
1609 q
= iprod(r_kl
, r_kj
); /* 5 */
1610 q
*= nrkj_2
; /* 1 */
1611 svmul(p
, f_i
, uvec
); /* 3 */
1612 svmul(q
, f_l
, vvec
); /* 3 */
1613 rvec_sub(uvec
, vvec
, svec
); /* 3 */
1614 rvec_sub(f_i
, svec
, f_j
); /* 3 */
1615 rvec_add(f_l
, svec
, f_k
); /* 3 */
1616 rvec_inc(f
[i
], f_i
); /* 3 */
1617 rvec_dec(f
[j
], f_j
); /* 3 */
1618 rvec_dec(f
[k
], f_k
); /* 3 */
1619 rvec_inc(f
[l
], f_l
); /* 3 */
1623 copy_ivec(SHIFT_IVEC(g
, j
), jt
);
1624 ivec_sub(SHIFT_IVEC(g
, i
), jt
, dt_ij
);
1625 ivec_sub(SHIFT_IVEC(g
, k
), jt
, dt_kj
);
1626 ivec_sub(SHIFT_IVEC(g
, l
), jt
, dt_lj
);
1627 t1
= IVEC2IS(dt_ij
);
1628 t2
= IVEC2IS(dt_kj
);
1629 t3
= IVEC2IS(dt_lj
);
1633 t3
= pbc_rvec_sub(pbc
, x
[l
], x
[j
], dx_jl
);
1640 rvec_inc(fshift
[t1
], f_i
);
1641 rvec_dec(fshift
[CENTRAL
], f_j
);
1642 rvec_dec(fshift
[t2
], f_k
);
1643 rvec_inc(fshift
[t3
], f_l
);
1648 /* As do_dih_fup above, but without shift forces */
1650 do_dih_fup_noshiftf(int i
, int j
, int k
, int l
, real ddphi
,
1651 rvec r_ij
, rvec r_kj
, rvec r_kl
,
1652 rvec m
, rvec n
, rvec4 f
[])
1654 rvec f_i
, f_j
, f_k
, f_l
;
1655 rvec uvec
, vvec
, svec
;
1656 real iprm
, iprn
, nrkj
, nrkj2
, nrkj_1
, nrkj_2
;
1657 real a
, b
, p
, q
, toler
;
1659 iprm
= iprod(m
, m
); /* 5 */
1660 iprn
= iprod(n
, n
); /* 5 */
1661 nrkj2
= iprod(r_kj
, r_kj
); /* 5 */
1662 toler
= nrkj2
*GMX_REAL_EPS
;
1663 if ((iprm
> toler
) && (iprn
> toler
))
1665 nrkj_1
= gmx::invsqrt(nrkj2
); /* 10 */
1666 nrkj_2
= nrkj_1
*nrkj_1
; /* 1 */
1667 nrkj
= nrkj2
*nrkj_1
; /* 1 */
1668 a
= -ddphi
*nrkj
/iprm
; /* 11 */
1669 svmul(a
, m
, f_i
); /* 3 */
1670 b
= ddphi
*nrkj
/iprn
; /* 11 */
1671 svmul(b
, n
, f_l
); /* 3 */
1672 p
= iprod(r_ij
, r_kj
); /* 5 */
1673 p
*= nrkj_2
; /* 1 */
1674 q
= iprod(r_kl
, r_kj
); /* 5 */
1675 q
*= nrkj_2
; /* 1 */
1676 svmul(p
, f_i
, uvec
); /* 3 */
1677 svmul(q
, f_l
, vvec
); /* 3 */
1678 rvec_sub(uvec
, vvec
, svec
); /* 3 */
1679 rvec_sub(f_i
, svec
, f_j
); /* 3 */
1680 rvec_add(f_l
, svec
, f_k
); /* 3 */
1681 rvec_inc(f
[i
], f_i
); /* 3 */
1682 rvec_dec(f
[j
], f_j
); /* 3 */
1683 rvec_dec(f
[k
], f_k
); /* 3 */
1684 rvec_inc(f
[l
], f_l
); /* 3 */
1688 #if GMX_SIMD_HAVE_REAL
1689 /* As do_dih_fup_noshiftf above, but with SIMD and pre-calculated pre-factors */
1690 static inline void gmx_simdcall
1691 do_dih_fup_noshiftf_simd(const int *ai
, const int *aj
, const int *ak
, const int *al
,
1692 SimdReal p
, SimdReal q
,
1693 SimdReal f_i_x
, SimdReal f_i_y
, SimdReal f_i_z
,
1694 SimdReal mf_l_x
, SimdReal mf_l_y
, SimdReal mf_l_z
,
1697 SimdReal sx
= p
* f_i_x
+ q
* mf_l_x
;
1698 SimdReal sy
= p
* f_i_y
+ q
* mf_l_y
;
1699 SimdReal sz
= p
* f_i_z
+ q
* mf_l_z
;
1700 SimdReal f_j_x
= f_i_x
- sx
;
1701 SimdReal f_j_y
= f_i_y
- sy
;
1702 SimdReal f_j_z
= f_i_z
- sz
;
1703 SimdReal f_k_x
= mf_l_x
- sx
;
1704 SimdReal f_k_y
= mf_l_y
- sy
;
1705 SimdReal f_k_z
= mf_l_z
- sz
;
1706 transposeScatterIncrU
<4>(reinterpret_cast<real
*>(f
), ai
, f_i_x
, f_i_y
, f_i_z
);
1707 transposeScatterDecrU
<4>(reinterpret_cast<real
*>(f
), aj
, f_j_x
, f_j_y
, f_j_z
);
1708 transposeScatterIncrU
<4>(reinterpret_cast<real
*>(f
), ak
, f_k_x
, f_k_y
, f_k_z
);
1709 transposeScatterDecrU
<4>(reinterpret_cast<real
*>(f
), al
, mf_l_x
, mf_l_y
, mf_l_z
);
1711 #endif // GMX_SIMD_HAVE_REAL
1713 static real
dopdihs(real cpA
, real cpB
, real phiA
, real phiB
, int mult
,
1714 real phi
, real lambda
, real
*V
, real
*F
)
1716 real v
, dvdlambda
, mdphi
, v1
, sdphi
, ddphi
;
1717 real L1
= 1.0 - lambda
;
1718 real ph0
= (L1
*phiA
+ lambda
*phiB
)*DEG2RAD
;
1719 real dph0
= (phiB
- phiA
)*DEG2RAD
;
1720 real cp
= L1
*cpA
+ lambda
*cpB
;
1722 mdphi
= mult
*phi
- ph0
;
1723 sdphi
= std::sin(mdphi
);
1724 ddphi
= -cp
*mult
*sdphi
;
1725 v1
= 1.0 + std::cos(mdphi
);
1728 dvdlambda
= (cpB
- cpA
)*v1
+ cp
*dph0
*sdphi
;
1735 /* That was 40 flops */
1739 dopdihs_noener(real cpA
, real cpB
, real phiA
, real phiB
, int mult
,
1740 real phi
, real lambda
, real
*F
)
1742 real mdphi
, sdphi
, ddphi
;
1743 real L1
= 1.0 - lambda
;
1744 real ph0
= (L1
*phiA
+ lambda
*phiB
)*DEG2RAD
;
1745 real cp
= L1
*cpA
+ lambda
*cpB
;
1747 mdphi
= mult
*phi
- ph0
;
1748 sdphi
= std::sin(mdphi
);
1749 ddphi
= -cp
*mult
*sdphi
;
1753 /* That was 20 flops */
1756 static real
dopdihs_min(real cpA
, real cpB
, real phiA
, real phiB
, int mult
,
1757 real phi
, real lambda
, real
*V
, real
*F
)
1758 /* similar to dopdihs, except for a minus sign *
1759 * and a different treatment of mult/phi0 */
1761 real v
, dvdlambda
, mdphi
, v1
, sdphi
, ddphi
;
1762 real L1
= 1.0 - lambda
;
1763 real ph0
= (L1
*phiA
+ lambda
*phiB
)*DEG2RAD
;
1764 real dph0
= (phiB
- phiA
)*DEG2RAD
;
1765 real cp
= L1
*cpA
+ lambda
*cpB
;
1767 mdphi
= mult
*(phi
-ph0
);
1768 sdphi
= std::sin(mdphi
);
1769 ddphi
= cp
*mult
*sdphi
;
1770 v1
= 1.0-std::cos(mdphi
);
1773 dvdlambda
= (cpB
-cpA
)*v1
+ cp
*dph0
*sdphi
;
1780 /* That was 40 flops */
1783 real
pdihs(int nbonds
,
1784 const t_iatom forceatoms
[], const t_iparams forceparams
[],
1785 const rvec x
[], rvec4 f
[], rvec fshift
[],
1786 const t_pbc
*pbc
, const t_graph
*g
,
1787 real lambda
, real
*dvdlambda
,
1788 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
1789 int gmx_unused
*global_atom_index
)
1791 int i
, type
, ai
, aj
, ak
, al
;
1793 rvec r_ij
, r_kj
, r_kl
, m
, n
;
1794 real phi
, ddphi
, vpd
, vtot
;
1798 for (i
= 0; (i
< nbonds
); )
1800 type
= forceatoms
[i
++];
1801 ai
= forceatoms
[i
++];
1802 aj
= forceatoms
[i
++];
1803 ak
= forceatoms
[i
++];
1804 al
= forceatoms
[i
++];
1806 phi
= dih_angle(x
[ai
], x
[aj
], x
[ak
], x
[al
], pbc
, r_ij
, r_kj
, r_kl
, m
, n
,
1807 &t1
, &t2
, &t3
); /* 84 */
1808 *dvdlambda
+= dopdihs(forceparams
[type
].pdihs
.cpA
,
1809 forceparams
[type
].pdihs
.cpB
,
1810 forceparams
[type
].pdihs
.phiA
,
1811 forceparams
[type
].pdihs
.phiB
,
1812 forceparams
[type
].pdihs
.mult
,
1813 phi
, lambda
, &vpd
, &ddphi
);
1816 do_dih_fup(ai
, aj
, ak
, al
, ddphi
, r_ij
, r_kj
, r_kl
, m
, n
,
1817 f
, fshift
, pbc
, g
, x
, t1
, t2
, t3
); /* 112 */
1824 void make_dp_periodic(real
*dp
) /* 1 flop? */
1826 /* dp cannot be outside (-pi,pi) */
1831 else if (*dp
< -M_PI
)
1838 /* As pdihs above, but without calculating energies and shift forces */
1840 pdihs_noener(int nbonds
,
1841 const t_iatom forceatoms
[], const t_iparams forceparams
[],
1842 const rvec x
[], rvec4 f
[],
1843 const t_pbc gmx_unused
*pbc
, const t_graph gmx_unused
*g
,
1845 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
1846 int gmx_unused
*global_atom_index
)
1848 int i
, type
, ai
, aj
, ak
, al
;
1850 rvec r_ij
, r_kj
, r_kl
, m
, n
;
1851 real phi
, ddphi_tot
, ddphi
;
1853 for (i
= 0; (i
< nbonds
); )
1855 ai
= forceatoms
[i
+1];
1856 aj
= forceatoms
[i
+2];
1857 ak
= forceatoms
[i
+3];
1858 al
= forceatoms
[i
+4];
1860 phi
= dih_angle(x
[ai
], x
[aj
], x
[ak
], x
[al
], pbc
, r_ij
, r_kj
, r_kl
, m
, n
,
1865 /* Loop over dihedrals working on the same atoms,
1866 * so we avoid recalculating angles and force distributions.
1870 type
= forceatoms
[i
];
1871 dopdihs_noener(forceparams
[type
].pdihs
.cpA
,
1872 forceparams
[type
].pdihs
.cpB
,
1873 forceparams
[type
].pdihs
.phiA
,
1874 forceparams
[type
].pdihs
.phiB
,
1875 forceparams
[type
].pdihs
.mult
,
1876 phi
, lambda
, &ddphi
);
1881 while (i
< nbonds
&&
1882 forceatoms
[i
+1] == ai
&&
1883 forceatoms
[i
+2] == aj
&&
1884 forceatoms
[i
+3] == ak
&&
1885 forceatoms
[i
+4] == al
);
1887 do_dih_fup_noshiftf(ai
, aj
, ak
, al
, ddphi_tot
, r_ij
, r_kj
, r_kl
, m
, n
, f
);
1892 #if GMX_SIMD_HAVE_REAL
1894 /* As pdihs_noner above, but using SIMD to calculate many dihedrals at once */
1896 pdihs_noener_simd(int nbonds
,
1897 const t_iatom forceatoms
[], const t_iparams forceparams
[],
1898 const rvec x
[], rvec4 f
[],
1899 const t_pbc
*pbc
, const t_graph gmx_unused
*g
,
1900 real gmx_unused lambda
,
1901 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
1902 int gmx_unused
*global_atom_index
)
1907 alignas(GMX_SIMD_ALIGNMENT
) std::int32_t ai
[GMX_SIMD_REAL_WIDTH
];
1908 alignas(GMX_SIMD_ALIGNMENT
) std::int32_t aj
[GMX_SIMD_REAL_WIDTH
];
1909 alignas(GMX_SIMD_ALIGNMENT
) std::int32_t ak
[GMX_SIMD_REAL_WIDTH
];
1910 alignas(GMX_SIMD_ALIGNMENT
) std::int32_t al
[GMX_SIMD_REAL_WIDTH
];
1911 alignas(GMX_SIMD_ALIGNMENT
) real buf
[3*GMX_SIMD_REAL_WIDTH
];
1912 real
*cp
, *phi0
, *mult
;
1913 SimdReal
deg2rad_S(DEG2RAD
);
1915 SimdReal phi0_S
, phi_S
;
1916 SimdReal mx_S
, my_S
, mz_S
;
1917 SimdReal nx_S
, ny_S
, nz_S
;
1918 SimdReal nrkj_m2_S
, nrkj_n2_S
;
1919 SimdReal cp_S
, mdphi_S
, mult_S
;
1920 SimdReal sin_S
, cos_S
;
1922 SimdReal sf_i_S
, msf_l_S
;
1923 alignas(GMX_SIMD_ALIGNMENT
) real pbc_simd
[9*GMX_SIMD_REAL_WIDTH
];
1925 /* Extract aligned pointer for parameters and variables */
1926 cp
= buf
+ 0*GMX_SIMD_REAL_WIDTH
;
1927 phi0
= buf
+ 1*GMX_SIMD_REAL_WIDTH
;
1928 mult
= buf
+ 2*GMX_SIMD_REAL_WIDTH
;
1930 set_pbc_simd(pbc
, pbc_simd
);
1932 /* nbonds is the number of dihedrals times nfa1, here we step GMX_SIMD_REAL_WIDTH dihs */
1933 for (i
= 0; (i
< nbonds
); i
+= GMX_SIMD_REAL_WIDTH
*nfa1
)
1935 /* Collect atoms quadruplets for GMX_SIMD_REAL_WIDTH dihedrals.
1936 * iu indexes into forceatoms, we should not let iu go beyond nbonds.
1939 for (s
= 0; s
< GMX_SIMD_REAL_WIDTH
; s
++)
1941 type
= forceatoms
[iu
];
1942 ai
[s
] = forceatoms
[iu
+1];
1943 aj
[s
] = forceatoms
[iu
+2];
1944 ak
[s
] = forceatoms
[iu
+3];
1945 al
[s
] = forceatoms
[iu
+4];
1947 /* At the end fill the arrays with the last atoms and 0 params */
1948 if (i
+ s
*nfa1
< nbonds
)
1950 cp
[s
] = forceparams
[type
].pdihs
.cpA
;
1951 phi0
[s
] = forceparams
[type
].pdihs
.phiA
;
1952 mult
[s
] = forceparams
[type
].pdihs
.mult
;
1954 if (iu
+ nfa1
< nbonds
)
1967 /* Caclulate GMX_SIMD_REAL_WIDTH dihedral angles at once */
1968 dih_angle_simd(x
, ai
, aj
, ak
, al
, pbc_simd
,
1970 &mx_S
, &my_S
, &mz_S
,
1971 &nx_S
, &ny_S
, &nz_S
,
1976 cp_S
= load
<SimdReal
>(cp
);
1977 phi0_S
= load
<SimdReal
>(phi0
) * deg2rad_S
;
1978 mult_S
= load
<SimdReal
>(mult
);
1980 mdphi_S
= fms(mult_S
, phi_S
, phi0_S
);
1982 /* Calculate GMX_SIMD_REAL_WIDTH sines at once */
1983 sincos(mdphi_S
, &sin_S
, &cos_S
);
1984 mddphi_S
= cp_S
* mult_S
* sin_S
;
1985 sf_i_S
= mddphi_S
* nrkj_m2_S
;
1986 msf_l_S
= mddphi_S
* nrkj_n2_S
;
1988 /* After this m?_S will contain f[i] */
1989 mx_S
= sf_i_S
* mx_S
;
1990 my_S
= sf_i_S
* my_S
;
1991 mz_S
= sf_i_S
* mz_S
;
1993 /* After this m?_S will contain -f[l] */
1994 nx_S
= msf_l_S
* nx_S
;
1995 ny_S
= msf_l_S
* ny_S
;
1996 nz_S
= msf_l_S
* nz_S
;
1998 do_dih_fup_noshiftf_simd(ai
, aj
, ak
, al
,
2006 /* This is mostly a copy of pdihs_noener_simd above, but with using
2007 * the RB potential instead of a harmonic potential.
2008 * This function can replace rbdihs() when no energy and virial are needed.
2011 rbdihs_noener_simd(int nbonds
,
2012 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2013 const rvec x
[], rvec4 f
[],
2014 const t_pbc
*pbc
, const t_graph gmx_unused
*g
,
2015 real gmx_unused lambda
,
2016 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2017 int gmx_unused
*global_atom_index
)
2022 alignas(GMX_SIMD_ALIGNMENT
) std::int32_t ai
[GMX_SIMD_REAL_WIDTH
];
2023 alignas(GMX_SIMD_ALIGNMENT
) std::int32_t aj
[GMX_SIMD_REAL_WIDTH
];
2024 alignas(GMX_SIMD_ALIGNMENT
) std::int32_t ak
[GMX_SIMD_REAL_WIDTH
];
2025 alignas(GMX_SIMD_ALIGNMENT
) std::int32_t al
[GMX_SIMD_REAL_WIDTH
];
2026 alignas(GMX_SIMD_ALIGNMENT
) real parm
[NR_RBDIHS
*GMX_SIMD_REAL_WIDTH
];
2030 SimdReal ddphi_S
, cosfac_S
;
2031 SimdReal mx_S
, my_S
, mz_S
;
2032 SimdReal nx_S
, ny_S
, nz_S
;
2033 SimdReal nrkj_m2_S
, nrkj_n2_S
;
2034 SimdReal parm_S
, c_S
;
2035 SimdReal sin_S
, cos_S
;
2036 SimdReal sf_i_S
, msf_l_S
;
2037 alignas(GMX_SIMD_ALIGNMENT
) real pbc_simd
[9*GMX_SIMD_REAL_WIDTH
];
2039 SimdReal
pi_S(M_PI
);
2040 SimdReal
one_S(1.0);
2042 set_pbc_simd(pbc
, pbc_simd
);
2044 /* nbonds is the number of dihedrals times nfa1, here we step GMX_SIMD_REAL_WIDTH dihs */
2045 for (i
= 0; (i
< nbonds
); i
+= GMX_SIMD_REAL_WIDTH
*nfa1
)
2047 /* Collect atoms quadruplets for GMX_SIMD_REAL_WIDTH dihedrals.
2048 * iu indexes into forceatoms, we should not let iu go beyond nbonds.
2051 for (s
= 0; s
< GMX_SIMD_REAL_WIDTH
; s
++)
2053 type
= forceatoms
[iu
];
2054 ai
[s
] = forceatoms
[iu
+1];
2055 aj
[s
] = forceatoms
[iu
+2];
2056 ak
[s
] = forceatoms
[iu
+3];
2057 al
[s
] = forceatoms
[iu
+4];
2059 /* At the end fill the arrays with the last atoms and 0 params */
2060 if (i
+ s
*nfa1
< nbonds
)
2062 /* We don't need the first parameter, since that's a constant
2063 * which only affects the energies, not the forces.
2065 for (j
= 1; j
< NR_RBDIHS
; j
++)
2067 parm
[j
*GMX_SIMD_REAL_WIDTH
+ s
] =
2068 forceparams
[type
].rbdihs
.rbcA
[j
];
2071 if (iu
+ nfa1
< nbonds
)
2078 for (j
= 1; j
< NR_RBDIHS
; j
++)
2080 parm
[j
*GMX_SIMD_REAL_WIDTH
+ s
] = 0;
2085 /* Caclulate GMX_SIMD_REAL_WIDTH dihedral angles at once */
2086 dih_angle_simd(x
, ai
, aj
, ak
, al
, pbc_simd
,
2088 &mx_S
, &my_S
, &mz_S
,
2089 &nx_S
, &ny_S
, &nz_S
,
2094 /* Change to polymer convention */
2095 phi_S
= phi_S
- pi_S
;
2097 sincos(phi_S
, &sin_S
, &cos_S
);
2099 ddphi_S
= setZero();
2102 for (j
= 1; j
< NR_RBDIHS
; j
++)
2104 parm_S
= load
<SimdReal
>(parm
+ j
*GMX_SIMD_REAL_WIDTH
);
2105 ddphi_S
= fma(c_S
* parm_S
, cosfac_S
, ddphi_S
);
2106 cosfac_S
= cosfac_S
* cos_S
;
2110 /* Note that here we do not use the minus sign which is present
2111 * in the normal RB code. This is corrected for through (m)sf below.
2113 ddphi_S
= ddphi_S
* sin_S
;
2115 sf_i_S
= ddphi_S
* nrkj_m2_S
;
2116 msf_l_S
= ddphi_S
* nrkj_n2_S
;
2118 /* After this m?_S will contain f[i] */
2119 mx_S
= sf_i_S
* mx_S
;
2120 my_S
= sf_i_S
* my_S
;
2121 mz_S
= sf_i_S
* mz_S
;
2123 /* After this m?_S will contain -f[l] */
2124 nx_S
= msf_l_S
* nx_S
;
2125 ny_S
= msf_l_S
* ny_S
;
2126 nz_S
= msf_l_S
* nz_S
;
2128 do_dih_fup_noshiftf_simd(ai
, aj
, ak
, al
,
2136 #endif // GMX_SIMD_HAVE_REAL
2139 real
idihs(int nbonds
,
2140 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2141 const rvec x
[], rvec4 f
[], rvec fshift
[],
2142 const t_pbc
*pbc
, const t_graph
*g
,
2143 real lambda
, real
*dvdlambda
,
2144 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2145 int gmx_unused
*global_atom_index
)
2147 int i
, type
, ai
, aj
, ak
, al
;
2149 real phi
, phi0
, dphi0
, ddphi
, vtot
;
2150 rvec r_ij
, r_kj
, r_kl
, m
, n
;
2151 real L1
, kk
, dp
, dp2
, kA
, kB
, pA
, pB
, dvdl_term
;
2156 for (i
= 0; (i
< nbonds
); )
2158 type
= forceatoms
[i
++];
2159 ai
= forceatoms
[i
++];
2160 aj
= forceatoms
[i
++];
2161 ak
= forceatoms
[i
++];
2162 al
= forceatoms
[i
++];
2164 phi
= dih_angle(x
[ai
], x
[aj
], x
[ak
], x
[al
], pbc
, r_ij
, r_kj
, r_kl
, m
, n
,
2165 &t1
, &t2
, &t3
); /* 84 */
2167 /* phi can jump if phi0 is close to Pi/-Pi, which will cause huge
2168 * force changes if we just apply a normal harmonic.
2169 * Instead, we first calculate phi-phi0 and take it modulo (-Pi,Pi).
2170 * This means we will never have the periodicity problem, unless
2171 * the dihedral is Pi away from phiO, which is very unlikely due to
2174 kA
= forceparams
[type
].harmonic
.krA
;
2175 kB
= forceparams
[type
].harmonic
.krB
;
2176 pA
= forceparams
[type
].harmonic
.rA
;
2177 pB
= forceparams
[type
].harmonic
.rB
;
2179 kk
= L1
*kA
+ lambda
*kB
;
2180 phi0
= (L1
*pA
+ lambda
*pB
)*DEG2RAD
;
2181 dphi0
= (pB
- pA
)*DEG2RAD
;
2185 make_dp_periodic(&dp
);
2192 dvdl_term
+= 0.5*(kB
- kA
)*dp2
- kk
*dphi0
*dp
;
2194 do_dih_fup(ai
, aj
, ak
, al
, -ddphi
, r_ij
, r_kj
, r_kl
, m
, n
,
2195 f
, fshift
, pbc
, g
, x
, t1
, t2
, t3
); /* 112 */
2199 *dvdlambda
+= dvdl_term
;
2203 static real
low_angres(int nbonds
,
2204 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2205 const rvec x
[], rvec4 f
[], rvec fshift
[],
2206 const t_pbc
*pbc
, const t_graph
*g
,
2207 real lambda
, real
*dvdlambda
,
2210 int i
, m
, type
, ai
, aj
, ak
, al
;
2212 real phi
, cos_phi
, cos_phi2
, vid
, vtot
, dVdphi
;
2213 rvec r_ij
, r_kl
, f_i
, f_k
= {0, 0, 0};
2214 real st
, sth
, nrij2
, nrkl2
, c
, cij
, ckl
;
2217 t2
= 0; /* avoid warning with gcc-3.3. It is never used uninitialized */
2220 ak
= al
= 0; /* to avoid warnings */
2221 for (i
= 0; i
< nbonds
; )
2223 type
= forceatoms
[i
++];
2224 ai
= forceatoms
[i
++];
2225 aj
= forceatoms
[i
++];
2226 t1
= pbc_rvec_sub(pbc
, x
[aj
], x
[ai
], r_ij
); /* 3 */
2229 ak
= forceatoms
[i
++];
2230 al
= forceatoms
[i
++];
2231 t2
= pbc_rvec_sub(pbc
, x
[al
], x
[ak
], r_kl
); /* 3 */
2240 cos_phi
= cos_angle(r_ij
, r_kl
); /* 25 */
2241 phi
= std::acos(cos_phi
); /* 10 */
2243 *dvdlambda
+= dopdihs_min(forceparams
[type
].pdihs
.cpA
,
2244 forceparams
[type
].pdihs
.cpB
,
2245 forceparams
[type
].pdihs
.phiA
,
2246 forceparams
[type
].pdihs
.phiB
,
2247 forceparams
[type
].pdihs
.mult
,
2248 phi
, lambda
, &vid
, &dVdphi
); /* 40 */
2252 cos_phi2
= gmx::square(cos_phi
); /* 1 */
2255 st
= -dVdphi
*gmx::invsqrt(1 - cos_phi2
); /* 12 */
2256 sth
= st
*cos_phi
; /* 1 */
2257 nrij2
= iprod(r_ij
, r_ij
); /* 5 */
2258 nrkl2
= iprod(r_kl
, r_kl
); /* 5 */
2260 c
= st
*gmx::invsqrt(nrij2
*nrkl2
); /* 11 */
2261 cij
= sth
/nrij2
; /* 10 */
2262 ckl
= sth
/nrkl2
; /* 10 */
2264 for (m
= 0; m
< DIM
; m
++) /* 18+18 */
2266 f_i
[m
] = (c
*r_kl
[m
]-cij
*r_ij
[m
]);
2271 f_k
[m
] = (c
*r_ij
[m
]-ckl
*r_kl
[m
]);
2279 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, aj
), dt
);
2282 rvec_inc(fshift
[t1
], f_i
);
2283 rvec_dec(fshift
[CENTRAL
], f_i
);
2288 ivec_sub(SHIFT_IVEC(g
, ak
), SHIFT_IVEC(g
, al
), dt
);
2291 rvec_inc(fshift
[t2
], f_k
);
2292 rvec_dec(fshift
[CENTRAL
], f_k
);
2297 return vtot
; /* 184 / 157 (bZAxis) total */
2300 real
angres(int nbonds
,
2301 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2302 const rvec x
[], rvec4 f
[], rvec fshift
[],
2303 const t_pbc
*pbc
, const t_graph
*g
,
2304 real lambda
, real
*dvdlambda
,
2305 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2306 int gmx_unused
*global_atom_index
)
2308 return low_angres(nbonds
, forceatoms
, forceparams
, x
, f
, fshift
, pbc
, g
,
2309 lambda
, dvdlambda
, FALSE
);
2312 real
angresz(int nbonds
,
2313 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2314 const rvec x
[], rvec4 f
[], rvec fshift
[],
2315 const t_pbc
*pbc
, const t_graph
*g
,
2316 real lambda
, real
*dvdlambda
,
2317 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2318 int gmx_unused
*global_atom_index
)
2320 return low_angres(nbonds
, forceatoms
, forceparams
, x
, f
, fshift
, pbc
, g
,
2321 lambda
, dvdlambda
, TRUE
);
2324 real
dihres(int nbonds
,
2325 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2326 const rvec x
[], rvec4 f
[], rvec fshift
[],
2327 const t_pbc
*pbc
, const t_graph
*g
,
2328 real lambda
, real
*dvdlambda
,
2329 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2330 int gmx_unused
*global_atom_index
)
2333 int ai
, aj
, ak
, al
, i
, type
, t1
, t2
, t3
;
2334 real phi0A
, phi0B
, dphiA
, dphiB
, kfacA
, kfacB
, phi0
, dphi
, kfac
;
2335 real phi
, ddphi
, ddp
, ddp2
, dp
, d2r
, L1
;
2336 rvec r_ij
, r_kj
, r_kl
, m
, n
;
2342 for (i
= 0; (i
< nbonds
); )
2344 type
= forceatoms
[i
++];
2345 ai
= forceatoms
[i
++];
2346 aj
= forceatoms
[i
++];
2347 ak
= forceatoms
[i
++];
2348 al
= forceatoms
[i
++];
2350 phi0A
= forceparams
[type
].dihres
.phiA
*d2r
;
2351 dphiA
= forceparams
[type
].dihres
.dphiA
*d2r
;
2352 kfacA
= forceparams
[type
].dihres
.kfacA
;
2354 phi0B
= forceparams
[type
].dihres
.phiB
*d2r
;
2355 dphiB
= forceparams
[type
].dihres
.dphiB
*d2r
;
2356 kfacB
= forceparams
[type
].dihres
.kfacB
;
2358 phi0
= L1
*phi0A
+ lambda
*phi0B
;
2359 dphi
= L1
*dphiA
+ lambda
*dphiB
;
2360 kfac
= L1
*kfacA
+ lambda
*kfacB
;
2362 phi
= dih_angle(x
[ai
], x
[aj
], x
[ak
], x
[al
], pbc
, r_ij
, r_kj
, r_kl
, m
, n
,
2366 /* phi can jump if phi0 is close to Pi/-Pi, which will cause huge
2367 * force changes if we just apply a normal harmonic.
2368 * Instead, we first calculate phi-phi0 and take it modulo (-Pi,Pi).
2369 * This means we will never have the periodicity problem, unless
2370 * the dihedral is Pi away from phiO, which is very unlikely due to
2374 make_dp_periodic(&dp
);
2380 else if (dp
< -dphi
)
2392 vtot
+= 0.5*kfac
*ddp2
;
2395 *dvdlambda
+= 0.5*(kfacB
- kfacA
)*ddp2
;
2396 /* lambda dependence from changing restraint distances */
2399 *dvdlambda
-= kfac
*ddp
*((dphiB
- dphiA
)+(phi0B
- phi0A
));
2403 *dvdlambda
+= kfac
*ddp
*((dphiB
- dphiA
)-(phi0B
- phi0A
));
2405 do_dih_fup(ai
, aj
, ak
, al
, ddphi
, r_ij
, r_kj
, r_kl
, m
, n
,
2406 f
, fshift
, pbc
, g
, x
, t1
, t2
, t3
); /* 112 */
2413 real
unimplemented(int gmx_unused nbonds
,
2414 const t_iatom gmx_unused forceatoms
[], const t_iparams gmx_unused forceparams
[],
2415 const rvec gmx_unused x
[], rvec4 gmx_unused f
[], rvec gmx_unused fshift
[],
2416 const t_pbc gmx_unused
*pbc
, const t_graph gmx_unused
*g
,
2417 real gmx_unused lambda
, real gmx_unused
*dvdlambda
,
2418 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2419 int gmx_unused
*global_atom_index
)
2421 gmx_impl("*** you are using a not implemented function");
2423 return 0.0; /* To make the compiler happy */
2426 real
restrangles(int nbonds
,
2427 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2428 const rvec x
[], rvec4 f
[], rvec fshift
[],
2429 const t_pbc
*pbc
, const t_graph
*g
,
2430 real gmx_unused lambda
, real gmx_unused
*dvdlambda
,
2431 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2432 int gmx_unused
*global_atom_index
)
2434 int i
, d
, ai
, aj
, ak
, type
, m
;
2437 ivec jt
, dt_ij
, dt_kj
;
2439 real prefactor
, ratio_ante
, ratio_post
;
2440 rvec delta_ante
, delta_post
, vec_temp
;
2443 for (i
= 0; (i
< nbonds
); )
2445 type
= forceatoms
[i
++];
2446 ai
= forceatoms
[i
++];
2447 aj
= forceatoms
[i
++];
2448 ak
= forceatoms
[i
++];
2450 t1
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], vec_temp
);
2451 pbc_rvec_sub(pbc
, x
[aj
], x
[ai
], delta_ante
);
2452 t2
= pbc_rvec_sub(pbc
, x
[ak
], x
[aj
], delta_post
);
2455 /* This function computes factors needed for restricted angle potential.
2456 * The restricted angle potential is used in coarse-grained simulations to avoid singularities
2457 * when three particles align and the dihedral angle and dihedral potential
2458 * cannot be calculated. This potential is calculated using the formula:
2459 real restrangles(int nbonds,
2460 const t_iatom forceatoms[],const t_iparams forceparams[],
2461 const rvec x[],rvec4 f[],rvec fshift[],
2462 const t_pbc *pbc,const t_graph *g,
2463 real gmx_unused lambda,real gmx_unused *dvdlambda,
2464 const t_mdatoms gmx_unused *md,t_fcdata gmx_unused *fcd,
2465 int gmx_unused *global_atom_index)
2467 int i, d, ai, aj, ak, type, m;
2471 ivec jt,dt_ij,dt_kj;
2473 real prefactor, ratio_ante, ratio_post;
2474 rvec delta_ante, delta_post, vec_temp;
2477 for(i=0; (i<nbonds); )
2479 type = forceatoms[i++];
2480 ai = forceatoms[i++];
2481 aj = forceatoms[i++];
2482 ak = forceatoms[i++];
2484 * \f[V_{\rm ReB}(\theta_i) = \frac{1}{2} k_{\theta} \frac{(\cos\theta_i - \cos\theta_0)^2}
2485 * {\sin^2\theta_i}\f] ({eq:ReB} and ref \cite{MonicaGoga2013} from the manual).
2486 * For more explanations see comments file "restcbt.h". */
2488 compute_factors_restangles(type
, forceparams
, delta_ante
, delta_post
,
2489 &prefactor
, &ratio_ante
, &ratio_post
, &v
);
2491 /* Forces are computed per component */
2492 for (d
= 0; d
< DIM
; d
++)
2494 f_i
[d
] = prefactor
* (ratio_ante
* delta_ante
[d
] - delta_post
[d
]);
2495 f_j
[d
] = prefactor
* ((ratio_post
+ 1.0) * delta_post
[d
] - (ratio_ante
+ 1.0) * delta_ante
[d
]);
2496 f_k
[d
] = prefactor
* (delta_ante
[d
] - ratio_post
* delta_post
[d
]);
2499 /* Computation of potential energy */
2505 for (m
= 0; (m
< DIM
); m
++)
2514 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
2515 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
2516 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
2517 t1
= IVEC2IS(dt_ij
);
2518 t2
= IVEC2IS(dt_kj
);
2521 rvec_inc(fshift
[t1
], f_i
);
2522 rvec_inc(fshift
[CENTRAL
], f_j
);
2523 rvec_inc(fshift
[t2
], f_k
);
2529 real
restrdihs(int nbonds
,
2530 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2531 const rvec x
[], rvec4 f
[], rvec fshift
[],
2532 const t_pbc
*pbc
, const t_graph
*g
,
2533 real gmx_unused lambda
, real gmx_unused
*dvlambda
,
2534 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2535 int gmx_unused
*global_atom_index
)
2537 int i
, d
, type
, ai
, aj
, ak
, al
;
2538 rvec f_i
, f_j
, f_k
, f_l
;
2540 ivec jt
, dt_ij
, dt_kj
, dt_lj
;
2543 rvec delta_ante
, delta_crnt
, delta_post
, vec_temp
;
2544 real factor_phi_ai_ante
, factor_phi_ai_crnt
, factor_phi_ai_post
;
2545 real factor_phi_aj_ante
, factor_phi_aj_crnt
, factor_phi_aj_post
;
2546 real factor_phi_ak_ante
, factor_phi_ak_crnt
, factor_phi_ak_post
;
2547 real factor_phi_al_ante
, factor_phi_al_crnt
, factor_phi_al_post
;
2552 for (i
= 0; (i
< nbonds
); )
2554 type
= forceatoms
[i
++];
2555 ai
= forceatoms
[i
++];
2556 aj
= forceatoms
[i
++];
2557 ak
= forceatoms
[i
++];
2558 al
= forceatoms
[i
++];
2560 t1
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], vec_temp
);
2561 pbc_rvec_sub(pbc
, x
[aj
], x
[ai
], delta_ante
);
2562 t2
= pbc_rvec_sub(pbc
, x
[ak
], x
[aj
], delta_crnt
);
2563 pbc_rvec_sub(pbc
, x
[ak
], x
[al
], vec_temp
);
2564 pbc_rvec_sub(pbc
, x
[al
], x
[ak
], delta_post
);
2566 /* This function computes factors needed for restricted angle potential.
2567 * The restricted angle potential is used in coarse-grained simulations to avoid singularities
2568 * when three particles align and the dihedral angle and dihedral potential cannot be calculated.
2569 * This potential is calculated using the formula:
2570 * \f[V_{\rm ReB}(\theta_i) = \frac{1}{2} k_{\theta}
2571 * \frac{(\cos\theta_i - \cos\theta_0)^2}{\sin^2\theta_i}\f]
2572 * ({eq:ReB} and ref \cite{MonicaGoga2013} from the manual).
2573 * For more explanations see comments file "restcbt.h" */
2575 compute_factors_restrdihs(type
, forceparams
,
2576 delta_ante
, delta_crnt
, delta_post
,
2577 &factor_phi_ai_ante
, &factor_phi_ai_crnt
, &factor_phi_ai_post
,
2578 &factor_phi_aj_ante
, &factor_phi_aj_crnt
, &factor_phi_aj_post
,
2579 &factor_phi_ak_ante
, &factor_phi_ak_crnt
, &factor_phi_ak_post
,
2580 &factor_phi_al_ante
, &factor_phi_al_crnt
, &factor_phi_al_post
,
2581 &prefactor_phi
, &v
);
2584 /* Computation of forces per component */
2585 for (d
= 0; d
< DIM
; d
++)
2587 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
]);
2588 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
]);
2589 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
]);
2590 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
]);
2592 /* Computation of the energy */
2598 /* Updating the forces */
2600 rvec_inc(f
[ai
], f_i
);
2601 rvec_inc(f
[aj
], f_j
);
2602 rvec_inc(f
[ak
], f_k
);
2603 rvec_inc(f
[al
], f_l
);
2606 /* Updating the fshift forces for the pressure coupling */
2609 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
2610 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
2611 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
2612 ivec_sub(SHIFT_IVEC(g
, al
), jt
, dt_lj
);
2613 t1
= IVEC2IS(dt_ij
);
2614 t2
= IVEC2IS(dt_kj
);
2615 t3
= IVEC2IS(dt_lj
);
2619 t3
= pbc_rvec_sub(pbc
, x
[al
], x
[aj
], dx_jl
);
2626 rvec_inc(fshift
[t1
], f_i
);
2627 rvec_inc(fshift
[CENTRAL
], f_j
);
2628 rvec_inc(fshift
[t2
], f_k
);
2629 rvec_inc(fshift
[t3
], f_l
);
2637 real
cbtdihs(int nbonds
,
2638 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2639 const rvec x
[], rvec4 f
[], rvec fshift
[],
2640 const t_pbc
*pbc
, const t_graph
*g
,
2641 real gmx_unused lambda
, real gmx_unused
*dvdlambda
,
2642 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2643 int gmx_unused
*global_atom_index
)
2645 int type
, ai
, aj
, ak
, al
, i
, d
;
2649 rvec f_i
, f_j
, f_k
, f_l
;
2650 ivec jt
, dt_ij
, dt_kj
, dt_lj
;
2652 rvec delta_ante
, delta_crnt
, delta_post
;
2653 rvec f_phi_ai
, f_phi_aj
, f_phi_ak
, f_phi_al
;
2654 rvec f_theta_ante_ai
, f_theta_ante_aj
, f_theta_ante_ak
;
2655 rvec f_theta_post_aj
, f_theta_post_ak
, f_theta_post_al
;
2661 for (i
= 0; (i
< nbonds
); )
2663 type
= forceatoms
[i
++];
2664 ai
= forceatoms
[i
++];
2665 aj
= forceatoms
[i
++];
2666 ak
= forceatoms
[i
++];
2667 al
= forceatoms
[i
++];
2670 t1
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], vec_temp
);
2671 pbc_rvec_sub(pbc
, x
[aj
], x
[ai
], delta_ante
);
2672 t2
= pbc_rvec_sub(pbc
, x
[ak
], x
[aj
], vec_temp
);
2673 pbc_rvec_sub(pbc
, x
[ak
], x
[aj
], delta_crnt
);
2674 pbc_rvec_sub(pbc
, x
[ak
], x
[al
], vec_temp
);
2675 pbc_rvec_sub(pbc
, x
[al
], x
[ak
], delta_post
);
2677 /* \brief Compute factors for CBT potential
2678 * The combined bending-torsion potential goes to zero in a very smooth manner, eliminating the numerical
2679 * instabilities, when three coarse-grained particles align and the dihedral angle and standard
2680 * dihedral potentials cannot be calculated. The CBT potential is calculated using the formula:
2681 * \f[V_{\rm CBT}(\theta_{i-1}, \theta_i, \phi_i) = k_{\phi} \sin^3\theta_{i-1} \sin^3\theta_{i}
2682 * \sum_{n=0}^4 { a_n \cos^n\phi_i}\f] ({eq:CBT} and ref \cite{MonicaGoga2013} from the manual).
2683 * It contains in its expression not only the dihedral angle \f$\phi\f$
2684 * but also \f[\theta_{i-1}\f] (theta_ante bellow) and \f[\theta_{i}\f] (theta_post bellow)
2685 * --- the adjacent bending angles.
2686 * For more explanations see comments file "restcbt.h". */
2688 compute_factors_cbtdihs(type
, forceparams
, delta_ante
, delta_crnt
, delta_post
,
2689 f_phi_ai
, f_phi_aj
, f_phi_ak
, f_phi_al
,
2690 f_theta_ante_ai
, f_theta_ante_aj
, f_theta_ante_ak
,
2691 f_theta_post_aj
, f_theta_post_ak
, f_theta_post_al
,
2695 /* Acumulate the resuts per beads */
2696 for (d
= 0; d
< DIM
; d
++)
2698 f_i
[d
] = f_phi_ai
[d
] + f_theta_ante_ai
[d
];
2699 f_j
[d
] = f_phi_aj
[d
] + f_theta_ante_aj
[d
] + f_theta_post_aj
[d
];
2700 f_k
[d
] = f_phi_ak
[d
] + f_theta_ante_ak
[d
] + f_theta_post_ak
[d
];
2701 f_l
[d
] = f_phi_al
[d
] + f_theta_post_al
[d
];
2704 /* Compute the potential energy */
2709 /* Updating the forces */
2710 rvec_inc(f
[ai
], f_i
);
2711 rvec_inc(f
[aj
], f_j
);
2712 rvec_inc(f
[ak
], f_k
);
2713 rvec_inc(f
[al
], f_l
);
2716 /* Updating the fshift forces for the pressure coupling */
2719 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
2720 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
2721 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
2722 ivec_sub(SHIFT_IVEC(g
, al
), jt
, dt_lj
);
2723 t1
= IVEC2IS(dt_ij
);
2724 t2
= IVEC2IS(dt_kj
);
2725 t3
= IVEC2IS(dt_lj
);
2729 t3
= pbc_rvec_sub(pbc
, x
[al
], x
[aj
], dx_jl
);
2736 rvec_inc(fshift
[t1
], f_i
);
2737 rvec_inc(fshift
[CENTRAL
], f_j
);
2738 rvec_inc(fshift
[t2
], f_k
);
2739 rvec_inc(fshift
[t3
], f_l
);
2745 real
rbdihs(int nbonds
,
2746 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2747 const rvec x
[], rvec4 f
[], rvec fshift
[],
2748 const t_pbc
*pbc
, const t_graph
*g
,
2749 real lambda
, real
*dvdlambda
,
2750 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2751 int gmx_unused
*global_atom_index
)
2753 const real c0
= 0.0, c1
= 1.0, c2
= 2.0, c3
= 3.0, c4
= 4.0, c5
= 5.0;
2754 int type
, ai
, aj
, ak
, al
, i
, j
;
2756 rvec r_ij
, r_kj
, r_kl
, m
, n
;
2757 real parmA
[NR_RBDIHS
];
2758 real parmB
[NR_RBDIHS
];
2759 real parm
[NR_RBDIHS
];
2760 real cos_phi
, phi
, rbp
, rbpBA
;
2761 real v
, ddphi
, sin_phi
;
2763 real L1
= 1.0-lambda
;
2767 for (i
= 0; (i
< nbonds
); )
2769 type
= forceatoms
[i
++];
2770 ai
= forceatoms
[i
++];
2771 aj
= forceatoms
[i
++];
2772 ak
= forceatoms
[i
++];
2773 al
= forceatoms
[i
++];
2775 phi
= dih_angle(x
[ai
], x
[aj
], x
[ak
], x
[al
], pbc
, r_ij
, r_kj
, r_kl
, m
, n
,
2776 &t1
, &t2
, &t3
); /* 84 */
2778 /* Change to polymer convention */
2785 phi
-= M_PI
; /* 1 */
2788 cos_phi
= std::cos(phi
);
2789 /* Beware of accuracy loss, cannot use 1-sqrt(cos^2) ! */
2790 sin_phi
= std::sin(phi
);
2792 for (j
= 0; (j
< NR_RBDIHS
); j
++)
2794 parmA
[j
] = forceparams
[type
].rbdihs
.rbcA
[j
];
2795 parmB
[j
] = forceparams
[type
].rbdihs
.rbcB
[j
];
2796 parm
[j
] = L1
*parmA
[j
]+lambda
*parmB
[j
];
2798 /* Calculate cosine powers */
2799 /* Calculate the energy */
2800 /* Calculate the derivative */
2803 dvdl_term
+= (parmB
[0]-parmA
[0]);
2808 rbpBA
= parmB
[1]-parmA
[1];
2809 ddphi
+= rbp
*cosfac
;
2812 dvdl_term
+= cosfac
*rbpBA
;
2814 rbpBA
= parmB
[2]-parmA
[2];
2815 ddphi
+= c2
*rbp
*cosfac
;
2818 dvdl_term
+= cosfac
*rbpBA
;
2820 rbpBA
= parmB
[3]-parmA
[3];
2821 ddphi
+= c3
*rbp
*cosfac
;
2824 dvdl_term
+= cosfac
*rbpBA
;
2826 rbpBA
= parmB
[4]-parmA
[4];
2827 ddphi
+= c4
*rbp
*cosfac
;
2830 dvdl_term
+= cosfac
*rbpBA
;
2832 rbpBA
= parmB
[5]-parmA
[5];
2833 ddphi
+= c5
*rbp
*cosfac
;
2836 dvdl_term
+= cosfac
*rbpBA
;
2838 ddphi
= -ddphi
*sin_phi
; /* 11 */
2840 do_dih_fup(ai
, aj
, ak
, al
, ddphi
, r_ij
, r_kj
, r_kl
, m
, n
,
2841 f
, fshift
, pbc
, g
, x
, t1
, t2
, t3
); /* 112 */
2844 *dvdlambda
+= dvdl_term
;
2851 /*! \brief Mysterious undocumented function */
2853 cmap_setup_grid_index(int ip
, int grid_spacing
, int *ipm1
, int *ipp1
, int *ipp2
)
2859 ip
= ip
+ grid_spacing
- 1;
2861 else if (ip
> grid_spacing
)
2863 ip
= ip
- grid_spacing
- 1;
2872 im1
= grid_spacing
- 1;
2874 else if (ip
== grid_spacing
-2)
2878 else if (ip
== grid_spacing
-1)
2893 cmap_dihs(int nbonds
,
2894 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2895 const gmx_cmap_t
*cmap_grid
,
2896 const rvec x
[], rvec4 f
[], rvec fshift
[],
2897 const struct t_pbc
*pbc
, const struct t_graph
*g
,
2898 real gmx_unused lambda
, real gmx_unused
*dvdlambda
,
2899 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2900 int gmx_unused
*global_atom_index
)
2903 int ai
, aj
, ak
, al
, am
;
2904 int a1i
, a1j
, a1k
, a1l
, a2i
, a2j
, a2k
, a2l
;
2906 int t11
, t21
, t31
, t12
, t22
, t32
;
2907 int iphi1
, ip1m1
, ip1p1
, ip1p2
;
2908 int iphi2
, ip2m1
, ip2p1
, ip2p2
;
2910 int pos1
, pos2
, pos3
, pos4
;
2912 real ty
[4], ty1
[4], ty2
[4], ty12
[4], tx
[16];
2913 real phi1
, cos_phi1
, sin_phi1
, xphi1
;
2914 real phi2
, cos_phi2
, sin_phi2
, xphi2
;
2915 real dx
, tt
, tu
, e
, df1
, df2
, vtot
;
2916 real ra21
, rb21
, rg21
, rg1
, rgr1
, ra2r1
, rb2r1
, rabr1
;
2917 real ra22
, rb22
, rg22
, rg2
, rgr2
, ra2r2
, rb2r2
, rabr2
;
2918 real fg1
, hg1
, fga1
, hgb1
, gaa1
, gbb1
;
2919 real fg2
, hg2
, fga2
, hgb2
, gaa2
, gbb2
;
2922 rvec r1_ij
, r1_kj
, r1_kl
, m1
, n1
;
2923 rvec r2_ij
, r2_kj
, r2_kl
, m2
, n2
;
2924 rvec f1_i
, f1_j
, f1_k
, f1_l
;
2925 rvec f2_i
, f2_j
, f2_k
, f2_l
;
2926 rvec a1
, b1
, a2
, b2
;
2927 rvec f1
, g1
, h1
, f2
, g2
, h2
;
2928 rvec dtf1
, dtg1
, dth1
, dtf2
, dtg2
, dth2
;
2929 ivec jt1
, dt1_ij
, dt1_kj
, dt1_lj
;
2930 ivec jt2
, dt2_ij
, dt2_kj
, dt2_lj
;
2934 int loop_index
[4][4] = {
2941 /* Total CMAP energy */
2944 for (n
= 0; n
< nbonds
; )
2946 /* Five atoms are involved in the two torsions */
2947 type
= forceatoms
[n
++];
2948 ai
= forceatoms
[n
++];
2949 aj
= forceatoms
[n
++];
2950 ak
= forceatoms
[n
++];
2951 al
= forceatoms
[n
++];
2952 am
= forceatoms
[n
++];
2954 /* Which CMAP type is this */
2955 cmapA
= forceparams
[type
].cmap
.cmapA
;
2956 cmapd
= cmap_grid
->cmapdata
[cmapA
].cmap
;
2964 phi1
= dih_angle(x
[a1i
], x
[a1j
], x
[a1k
], x
[a1l
], pbc
, r1_ij
, r1_kj
, r1_kl
, m1
, n1
,
2965 &t11
, &t21
, &t31
); /* 84 */
2967 cos_phi1
= std::cos(phi1
);
2969 a1
[0] = r1_ij
[1]*r1_kj
[2]-r1_ij
[2]*r1_kj
[1];
2970 a1
[1] = r1_ij
[2]*r1_kj
[0]-r1_ij
[0]*r1_kj
[2];
2971 a1
[2] = r1_ij
[0]*r1_kj
[1]-r1_ij
[1]*r1_kj
[0]; /* 9 */
2973 b1
[0] = r1_kl
[1]*r1_kj
[2]-r1_kl
[2]*r1_kj
[1];
2974 b1
[1] = r1_kl
[2]*r1_kj
[0]-r1_kl
[0]*r1_kj
[2];
2975 b1
[2] = r1_kl
[0]*r1_kj
[1]-r1_kl
[1]*r1_kj
[0]; /* 9 */
2977 pbc_rvec_sub(pbc
, x
[a1l
], x
[a1k
], h1
);
2979 ra21
= iprod(a1
, a1
); /* 5 */
2980 rb21
= iprod(b1
, b1
); /* 5 */
2981 rg21
= iprod(r1_kj
, r1_kj
); /* 5 */
2987 rabr1
= sqrt(ra2r1
*rb2r1
);
2989 sin_phi1
= rg1
* rabr1
* iprod(a1
, h1
) * (-1);
2991 if (cos_phi1
< -0.5 || cos_phi1
> 0.5)
2993 phi1
= std::asin(sin_phi1
);
3003 phi1
= -M_PI
- phi1
;
3009 phi1
= std::acos(cos_phi1
);
3017 xphi1
= phi1
+ M_PI
; /* 1 */
3019 /* Second torsion */
3025 phi2
= dih_angle(x
[a2i
], x
[a2j
], x
[a2k
], x
[a2l
], pbc
, r2_ij
, r2_kj
, r2_kl
, m2
, n2
,
3026 &t12
, &t22
, &t32
); /* 84 */
3028 cos_phi2
= std::cos(phi2
);
3030 a2
[0] = r2_ij
[1]*r2_kj
[2]-r2_ij
[2]*r2_kj
[1];
3031 a2
[1] = r2_ij
[2]*r2_kj
[0]-r2_ij
[0]*r2_kj
[2];
3032 a2
[2] = r2_ij
[0]*r2_kj
[1]-r2_ij
[1]*r2_kj
[0]; /* 9 */
3034 b2
[0] = r2_kl
[1]*r2_kj
[2]-r2_kl
[2]*r2_kj
[1];
3035 b2
[1] = r2_kl
[2]*r2_kj
[0]-r2_kl
[0]*r2_kj
[2];
3036 b2
[2] = r2_kl
[0]*r2_kj
[1]-r2_kl
[1]*r2_kj
[0]; /* 9 */
3038 pbc_rvec_sub(pbc
, x
[a2l
], x
[a2k
], h2
);
3040 ra22
= iprod(a2
, a2
); /* 5 */
3041 rb22
= iprod(b2
, b2
); /* 5 */
3042 rg22
= iprod(r2_kj
, r2_kj
); /* 5 */
3048 rabr2
= sqrt(ra2r2
*rb2r2
);
3050 sin_phi2
= rg2
* rabr2
* iprod(a2
, h2
) * (-1);
3052 if (cos_phi2
< -0.5 || cos_phi2
> 0.5)
3054 phi2
= std::asin(sin_phi2
);
3064 phi2
= -M_PI
- phi2
;
3070 phi2
= std::acos(cos_phi2
);
3078 xphi2
= phi2
+ M_PI
; /* 1 */
3080 /* Range mangling */
3083 xphi1
= xphi1
+ 2*M_PI
;
3085 else if (xphi1
>= 2*M_PI
)
3087 xphi1
= xphi1
- 2*M_PI
;
3092 xphi2
= xphi2
+ 2*M_PI
;
3094 else if (xphi2
>= 2*M_PI
)
3096 xphi2
= xphi2
- 2*M_PI
;
3099 /* Number of grid points */
3100 dx
= 2*M_PI
/ cmap_grid
->grid_spacing
;
3102 /* Where on the grid are we */
3103 iphi1
= static_cast<int>(xphi1
/dx
);
3104 iphi2
= static_cast<int>(xphi2
/dx
);
3106 iphi1
= cmap_setup_grid_index(iphi1
, cmap_grid
->grid_spacing
, &ip1m1
, &ip1p1
, &ip1p2
);
3107 iphi2
= cmap_setup_grid_index(iphi2
, cmap_grid
->grid_spacing
, &ip2m1
, &ip2p1
, &ip2p2
);
3109 pos1
= iphi1
*cmap_grid
->grid_spacing
+iphi2
;
3110 pos2
= ip1p1
*cmap_grid
->grid_spacing
+iphi2
;
3111 pos3
= ip1p1
*cmap_grid
->grid_spacing
+ip2p1
;
3112 pos4
= iphi1
*cmap_grid
->grid_spacing
+ip2p1
;
3114 ty
[0] = cmapd
[pos1
*4];
3115 ty
[1] = cmapd
[pos2
*4];
3116 ty
[2] = cmapd
[pos3
*4];
3117 ty
[3] = cmapd
[pos4
*4];
3119 ty1
[0] = cmapd
[pos1
*4+1];
3120 ty1
[1] = cmapd
[pos2
*4+1];
3121 ty1
[2] = cmapd
[pos3
*4+1];
3122 ty1
[3] = cmapd
[pos4
*4+1];
3124 ty2
[0] = cmapd
[pos1
*4+2];
3125 ty2
[1] = cmapd
[pos2
*4+2];
3126 ty2
[2] = cmapd
[pos3
*4+2];
3127 ty2
[3] = cmapd
[pos4
*4+2];
3129 ty12
[0] = cmapd
[pos1
*4+3];
3130 ty12
[1] = cmapd
[pos2
*4+3];
3131 ty12
[2] = cmapd
[pos3
*4+3];
3132 ty12
[3] = cmapd
[pos4
*4+3];
3134 /* Switch to degrees */
3135 dx
= 360.0 / cmap_grid
->grid_spacing
;
3136 xphi1
= xphi1
* RAD2DEG
;
3137 xphi2
= xphi2
* RAD2DEG
;
3139 for (i
= 0; i
< 4; i
++) /* 16 */
3142 tx
[i
+4] = ty1
[i
]*dx
;
3143 tx
[i
+8] = ty2
[i
]*dx
;
3144 tx
[i
+12] = ty12
[i
]*dx
*dx
;
3148 for (int idx
= 0; idx
< 16; idx
++) /* 1056 */
3150 for (int k
= 0; k
< 16; k
++)
3152 tc
[idx
] += cmap_coeff_matrix
[k
*16+idx
]*tx
[k
];
3156 tt
= (xphi1
-iphi1
*dx
)/dx
;
3157 tu
= (xphi2
-iphi2
*dx
)/dx
;
3163 for (i
= 3; i
>= 0; i
--)
3165 l1
= loop_index
[i
][3];
3166 l2
= loop_index
[i
][2];
3167 l3
= loop_index
[i
][1];
3169 e
= tt
* e
+ ((tc
[i
*4+3]*tu
+tc
[i
*4+2])*tu
+ tc
[i
*4+1])*tu
+tc
[i
*4];
3170 df1
= tu
* df1
+ (3.0*tc
[l1
]*tt
+2.0*tc
[l2
])*tt
+tc
[l3
];
3171 df2
= tt
* df2
+ (3.0*tc
[i
*4+3]*tu
+2.0*tc
[i
*4+2])*tu
+tc
[i
*4+1];
3181 /* Do forces - first torsion */
3182 fg1
= iprod(r1_ij
, r1_kj
);
3183 hg1
= iprod(r1_kl
, r1_kj
);
3184 fga1
= fg1
*ra2r1
*rgr1
;
3185 hgb1
= hg1
*rb2r1
*rgr1
;
3189 for (i
= 0; i
< DIM
; i
++)
3191 dtf1
[i
] = gaa1
* a1
[i
];
3192 dtg1
[i
] = fga1
* a1
[i
] - hgb1
* b1
[i
];
3193 dth1
[i
] = gbb1
* b1
[i
];
3195 f1
[i
] = df1
* dtf1
[i
];
3196 g1
[i
] = df1
* dtg1
[i
];
3197 h1
[i
] = df1
* dth1
[i
];
3200 f1_j
[i
] = -f1
[i
] - g1
[i
];
3201 f1_k
[i
] = h1
[i
] + g1
[i
];
3204 f
[a1i
][i
] = f
[a1i
][i
] + f1_i
[i
];
3205 f
[a1j
][i
] = f
[a1j
][i
] + f1_j
[i
]; /* - f1[i] - g1[i] */
3206 f
[a1k
][i
] = f
[a1k
][i
] + f1_k
[i
]; /* h1[i] + g1[i] */
3207 f
[a1l
][i
] = f
[a1l
][i
] + f1_l
[i
]; /* h1[i] */
3210 /* Do forces - second torsion */
3211 fg2
= iprod(r2_ij
, r2_kj
);
3212 hg2
= iprod(r2_kl
, r2_kj
);
3213 fga2
= fg2
*ra2r2
*rgr2
;
3214 hgb2
= hg2
*rb2r2
*rgr2
;
3218 for (i
= 0; i
< DIM
; i
++)
3220 dtf2
[i
] = gaa2
* a2
[i
];
3221 dtg2
[i
] = fga2
* a2
[i
] - hgb2
* b2
[i
];
3222 dth2
[i
] = gbb2
* b2
[i
];
3224 f2
[i
] = df2
* dtf2
[i
];
3225 g2
[i
] = df2
* dtg2
[i
];
3226 h2
[i
] = df2
* dth2
[i
];
3229 f2_j
[i
] = -f2
[i
] - g2
[i
];
3230 f2_k
[i
] = h2
[i
] + g2
[i
];
3233 f
[a2i
][i
] = f
[a2i
][i
] + f2_i
[i
]; /* f2[i] */
3234 f
[a2j
][i
] = f
[a2j
][i
] + f2_j
[i
]; /* - f2[i] - g2[i] */
3235 f
[a2k
][i
] = f
[a2k
][i
] + f2_k
[i
]; /* h2[i] + g2[i] */
3236 f
[a2l
][i
] = f
[a2l
][i
] + f2_l
[i
]; /* - h2[i] */
3242 copy_ivec(SHIFT_IVEC(g
, a1j
), jt1
);
3243 ivec_sub(SHIFT_IVEC(g
, a1i
), jt1
, dt1_ij
);
3244 ivec_sub(SHIFT_IVEC(g
, a1k
), jt1
, dt1_kj
);
3245 ivec_sub(SHIFT_IVEC(g
, a1l
), jt1
, dt1_lj
);
3246 t11
= IVEC2IS(dt1_ij
);
3247 t21
= IVEC2IS(dt1_kj
);
3248 t31
= IVEC2IS(dt1_lj
);
3250 copy_ivec(SHIFT_IVEC(g
, a2j
), jt2
);
3251 ivec_sub(SHIFT_IVEC(g
, a2i
), jt2
, dt2_ij
);
3252 ivec_sub(SHIFT_IVEC(g
, a2k
), jt2
, dt2_kj
);
3253 ivec_sub(SHIFT_IVEC(g
, a2l
), jt2
, dt2_lj
);
3254 t12
= IVEC2IS(dt2_ij
);
3255 t22
= IVEC2IS(dt2_kj
);
3256 t32
= IVEC2IS(dt2_lj
);
3260 t31
= pbc_rvec_sub(pbc
, x
[a1l
], x
[a1j
], h1
);
3261 t32
= pbc_rvec_sub(pbc
, x
[a2l
], x
[a2j
], h2
);
3269 rvec_inc(fshift
[t11
], f1_i
);
3270 rvec_inc(fshift
[CENTRAL
], f1_j
);
3271 rvec_inc(fshift
[t21
], f1_k
);
3272 rvec_inc(fshift
[t31
], f1_l
);
3274 rvec_inc(fshift
[t21
], f2_i
);
3275 rvec_inc(fshift
[CENTRAL
], f2_j
);
3276 rvec_inc(fshift
[t22
], f2_k
);
3277 rvec_inc(fshift
[t32
], f2_l
);
3284 /***********************************************************
3286 * G R O M O S 9 6 F U N C T I O N S
3288 ***********************************************************/
3289 static real
g96harmonic(real kA
, real kB
, real xA
, real xB
, real x
, real lambda
,
3292 const real half
= 0.5;
3293 real L1
, kk
, x0
, dx
, dx2
;
3294 real v
, f
, dvdlambda
;
3297 kk
= L1
*kA
+lambda
*kB
;
3298 x0
= L1
*xA
+lambda
*xB
;
3305 dvdlambda
= half
*(kB
-kA
)*dx2
+ (xA
-xB
)*kk
*dx
;
3312 /* That was 21 flops */
3315 real
g96bonds(int nbonds
,
3316 const t_iatom forceatoms
[], const t_iparams forceparams
[],
3317 const rvec x
[], rvec4 f
[], rvec fshift
[],
3318 const t_pbc
*pbc
, const t_graph
*g
,
3319 real lambda
, real
*dvdlambda
,
3320 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
3321 int gmx_unused
*global_atom_index
)
3323 int i
, m
, ki
, ai
, aj
, type
;
3324 real dr2
, fbond
, vbond
, fij
, vtot
;
3329 for (i
= 0; (i
< nbonds
); )
3331 type
= forceatoms
[i
++];
3332 ai
= forceatoms
[i
++];
3333 aj
= forceatoms
[i
++];
3335 ki
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], dx
); /* 3 */
3336 dr2
= iprod(dx
, dx
); /* 5 */
3338 *dvdlambda
+= g96harmonic(forceparams
[type
].harmonic
.krA
,
3339 forceparams
[type
].harmonic
.krB
,
3340 forceparams
[type
].harmonic
.rA
,
3341 forceparams
[type
].harmonic
.rB
,
3342 dr2
, lambda
, &vbond
, &fbond
);
3344 vtot
+= 0.5*vbond
; /* 1*/
3348 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, aj
), dt
);
3351 for (m
= 0; (m
< DIM
); m
++) /* 15 */
3356 fshift
[ki
][m
] += fij
;
3357 fshift
[CENTRAL
][m
] -= fij
;
3363 static real
g96bond_angle(const rvec xi
, const rvec xj
, const rvec xk
, const t_pbc
*pbc
,
3364 rvec r_ij
, rvec r_kj
,
3366 /* Return value is the angle between the bonds i-j and j-k */
3370 *t1
= pbc_rvec_sub(pbc
, xi
, xj
, r_ij
); /* 3 */
3371 *t2
= pbc_rvec_sub(pbc
, xk
, xj
, r_kj
); /* 3 */
3373 costh
= cos_angle(r_ij
, r_kj
); /* 25 */
3378 real
g96angles(int nbonds
,
3379 const t_iatom forceatoms
[], const t_iparams forceparams
[],
3380 const rvec x
[], rvec4 f
[], rvec fshift
[],
3381 const t_pbc
*pbc
, const t_graph
*g
,
3382 real lambda
, real
*dvdlambda
,
3383 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
3384 int gmx_unused
*global_atom_index
)
3386 int i
, ai
, aj
, ak
, type
, m
, t1
, t2
;
3388 real cos_theta
, dVdt
, va
, vtot
;
3389 real rij_1
, rij_2
, rkj_1
, rkj_2
, rijrkj_1
;
3391 ivec jt
, dt_ij
, dt_kj
;
3394 for (i
= 0; (i
< nbonds
); )
3396 type
= forceatoms
[i
++];
3397 ai
= forceatoms
[i
++];
3398 aj
= forceatoms
[i
++];
3399 ak
= forceatoms
[i
++];
3401 cos_theta
= g96bond_angle(x
[ai
], x
[aj
], x
[ak
], pbc
, r_ij
, r_kj
, &t1
, &t2
);
3403 *dvdlambda
+= g96harmonic(forceparams
[type
].harmonic
.krA
,
3404 forceparams
[type
].harmonic
.krB
,
3405 forceparams
[type
].harmonic
.rA
,
3406 forceparams
[type
].harmonic
.rB
,
3407 cos_theta
, lambda
, &va
, &dVdt
);
3410 rij_1
= gmx::invsqrt(iprod(r_ij
, r_ij
));
3411 rkj_1
= gmx::invsqrt(iprod(r_kj
, r_kj
));
3412 rij_2
= rij_1
*rij_1
;
3413 rkj_2
= rkj_1
*rkj_1
;
3414 rijrkj_1
= rij_1
*rkj_1
; /* 23 */
3416 for (m
= 0; (m
< DIM
); m
++) /* 42 */
3418 f_i
[m
] = dVdt
*(r_kj
[m
]*rijrkj_1
- r_ij
[m
]*rij_2
*cos_theta
);
3419 f_k
[m
] = dVdt
*(r_ij
[m
]*rijrkj_1
- r_kj
[m
]*rkj_2
*cos_theta
);
3420 f_j
[m
] = -f_i
[m
]-f_k
[m
];
3428 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
3430 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
3431 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
3432 t1
= IVEC2IS(dt_ij
);
3433 t2
= IVEC2IS(dt_kj
);
3435 rvec_inc(fshift
[t1
], f_i
);
3436 rvec_inc(fshift
[CENTRAL
], f_j
);
3437 rvec_inc(fshift
[t2
], f_k
); /* 9 */
3443 real
cross_bond_bond(int nbonds
,
3444 const t_iatom forceatoms
[], const t_iparams forceparams
[],
3445 const rvec x
[], rvec4 f
[], rvec fshift
[],
3446 const t_pbc
*pbc
, const t_graph
*g
,
3447 real gmx_unused lambda
, real gmx_unused
*dvdlambda
,
3448 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
3449 int gmx_unused
*global_atom_index
)
3451 /* Potential from Lawrence and Skimmer, Chem. Phys. Lett. 372 (2003)
3454 int i
, ai
, aj
, ak
, type
, m
, t1
, t2
;
3456 real vtot
, vrr
, s1
, s2
, r1
, r2
, r1e
, r2e
, krr
;
3458 ivec jt
, dt_ij
, dt_kj
;
3461 for (i
= 0; (i
< nbonds
); )
3463 type
= forceatoms
[i
++];
3464 ai
= forceatoms
[i
++];
3465 aj
= forceatoms
[i
++];
3466 ak
= forceatoms
[i
++];
3467 r1e
= forceparams
[type
].cross_bb
.r1e
;
3468 r2e
= forceparams
[type
].cross_bb
.r2e
;
3469 krr
= forceparams
[type
].cross_bb
.krr
;
3471 /* Compute distance vectors ... */
3472 t1
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], r_ij
);
3473 t2
= pbc_rvec_sub(pbc
, x
[ak
], x
[aj
], r_kj
);
3475 /* ... and their lengths */
3479 /* Deviations from ideality */
3483 /* Energy (can be negative!) */
3488 svmul(-krr
*s2
/r1
, r_ij
, f_i
);
3489 svmul(-krr
*s1
/r2
, r_kj
, f_k
);
3491 for (m
= 0; (m
< DIM
); m
++) /* 12 */
3493 f_j
[m
] = -f_i
[m
] - f_k
[m
];
3502 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
3504 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
3505 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
3506 t1
= IVEC2IS(dt_ij
);
3507 t2
= IVEC2IS(dt_kj
);
3509 rvec_inc(fshift
[t1
], f_i
);
3510 rvec_inc(fshift
[CENTRAL
], f_j
);
3511 rvec_inc(fshift
[t2
], f_k
); /* 9 */
3517 real
cross_bond_angle(int nbonds
,
3518 const t_iatom forceatoms
[], const t_iparams forceparams
[],
3519 const rvec x
[], rvec4 f
[], rvec fshift
[],
3520 const t_pbc
*pbc
, const t_graph
*g
,
3521 real gmx_unused lambda
, real gmx_unused
*dvdlambda
,
3522 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
3523 int gmx_unused
*global_atom_index
)
3525 /* Potential from Lawrence and Skimmer, Chem. Phys. Lett. 372 (2003)
3528 int i
, ai
, aj
, ak
, type
, m
, t1
, t2
;
3529 rvec r_ij
, r_kj
, r_ik
;
3530 real vtot
, vrt
, s1
, s2
, s3
, r1
, r2
, r3
, r1e
, r2e
, r3e
, krt
, k1
, k2
, k3
;
3532 ivec jt
, dt_ij
, dt_kj
;
3535 for (i
= 0; (i
< nbonds
); )
3537 type
= forceatoms
[i
++];
3538 ai
= forceatoms
[i
++];
3539 aj
= forceatoms
[i
++];
3540 ak
= forceatoms
[i
++];
3541 r1e
= forceparams
[type
].cross_ba
.r1e
;
3542 r2e
= forceparams
[type
].cross_ba
.r2e
;
3543 r3e
= forceparams
[type
].cross_ba
.r3e
;
3544 krt
= forceparams
[type
].cross_ba
.krt
;
3546 /* Compute distance vectors ... */
3547 t1
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], r_ij
);
3548 t2
= pbc_rvec_sub(pbc
, x
[ak
], x
[aj
], r_kj
);
3549 pbc_rvec_sub(pbc
, x
[ai
], x
[ak
], r_ik
);
3551 /* ... and their lengths */
3556 /* Deviations from ideality */
3561 /* Energy (can be negative!) */
3562 vrt
= krt
*s3
*(s1
+s2
);
3568 k3
= -krt
*(s1
+s2
)/r3
;
3569 for (m
= 0; (m
< DIM
); m
++)
3571 f_i
[m
] = k1
*r_ij
[m
] + k3
*r_ik
[m
];
3572 f_k
[m
] = k2
*r_kj
[m
] - k3
*r_ik
[m
];
3573 f_j
[m
] = -f_i
[m
] - f_k
[m
];
3576 for (m
= 0; (m
< DIM
); m
++) /* 12 */
3586 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
3588 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
3589 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
3590 t1
= IVEC2IS(dt_ij
);
3591 t2
= IVEC2IS(dt_kj
);
3593 rvec_inc(fshift
[t1
], f_i
);
3594 rvec_inc(fshift
[CENTRAL
], f_j
);
3595 rvec_inc(fshift
[t2
], f_k
); /* 9 */
3601 static real
bonded_tab(const char *type
, int table_nr
,
3602 const bondedtable_t
*table
, real kA
, real kB
, real r
,
3603 real lambda
, real
*V
, real
*F
)
3605 real k
, tabscale
, *VFtab
, rt
, eps
, eps2
, Yt
, Ft
, Geps
, Heps2
, Fp
, VV
, FF
;
3609 k
= (1.0 - lambda
)*kA
+ lambda
*kB
;
3611 tabscale
= table
->scale
;
3612 VFtab
= table
->data
;
3615 n0
= static_cast<int>(rt
);
3618 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",
3619 type
, table_nr
, r
, n0
, n0
+1, table
->n
);
3626 Geps
= VFtab
[nnn
+2]*eps
;
3627 Heps2
= VFtab
[nnn
+3]*eps2
;
3628 Fp
= Ft
+ Geps
+ Heps2
;
3630 FF
= Fp
+ Geps
+ 2.0*Heps2
;
3632 *F
= -k
*FF
*tabscale
;
3634 dvdlambda
= (kB
- kA
)*VV
;
3638 /* That was 22 flops */
3641 real
tab_bonds(int nbonds
,
3642 const t_iatom forceatoms
[], const t_iparams forceparams
[],
3643 const rvec x
[], rvec4 f
[], rvec fshift
[],
3644 const t_pbc
*pbc
, const t_graph
*g
,
3645 real lambda
, real
*dvdlambda
,
3646 const t_mdatoms gmx_unused
*md
, t_fcdata
*fcd
,
3647 int gmx_unused
*global_atom_index
)
3649 int i
, m
, ki
, ai
, aj
, type
, table
;
3650 real dr
, dr2
, fbond
, vbond
, fij
, vtot
;
3655 for (i
= 0; (i
< nbonds
); )
3657 type
= forceatoms
[i
++];
3658 ai
= forceatoms
[i
++];
3659 aj
= forceatoms
[i
++];
3661 ki
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], dx
); /* 3 */
3662 dr2
= iprod(dx
, dx
); /* 5 */
3663 dr
= dr2
*gmx::invsqrt(dr2
); /* 10 */
3665 table
= forceparams
[type
].tab
.table
;
3667 *dvdlambda
+= bonded_tab("bond", table
,
3668 &fcd
->bondtab
[table
],
3669 forceparams
[type
].tab
.kA
,
3670 forceparams
[type
].tab
.kB
,
3671 dr
, lambda
, &vbond
, &fbond
); /* 22 */
3679 vtot
+= vbond
; /* 1*/
3680 fbond
*= gmx::invsqrt(dr2
); /* 6 */
3683 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, aj
), dt
);
3686 for (m
= 0; (m
< DIM
); m
++) /* 15 */
3691 fshift
[ki
][m
] += fij
;
3692 fshift
[CENTRAL
][m
] -= fij
;
3698 real
tab_angles(int nbonds
,
3699 const t_iatom forceatoms
[], const t_iparams forceparams
[],
3700 const rvec x
[], rvec4 f
[], rvec fshift
[],
3701 const t_pbc
*pbc
, const t_graph
*g
,
3702 real lambda
, real
*dvdlambda
,
3703 const t_mdatoms gmx_unused
*md
, t_fcdata
*fcd
,
3704 int gmx_unused
*global_atom_index
)
3706 int i
, ai
, aj
, ak
, t1
, t2
, type
, table
;
3708 real cos_theta
, cos_theta2
, theta
, dVdt
, va
, vtot
;
3709 ivec jt
, dt_ij
, dt_kj
;
3712 for (i
= 0; (i
< nbonds
); )
3714 type
= forceatoms
[i
++];
3715 ai
= forceatoms
[i
++];
3716 aj
= forceatoms
[i
++];
3717 ak
= forceatoms
[i
++];
3719 theta
= bond_angle(x
[ai
], x
[aj
], x
[ak
], pbc
,
3720 r_ij
, r_kj
, &cos_theta
, &t1
, &t2
); /* 41 */
3722 table
= forceparams
[type
].tab
.table
;
3724 *dvdlambda
+= bonded_tab("angle", table
,
3725 &fcd
->angletab
[table
],
3726 forceparams
[type
].tab
.kA
,
3727 forceparams
[type
].tab
.kB
,
3728 theta
, lambda
, &va
, &dVdt
); /* 22 */
3731 cos_theta2
= gmx::square(cos_theta
); /* 1 */
3740 st
= dVdt
*gmx::invsqrt(1 - cos_theta2
); /* 12 */
3741 sth
= st
*cos_theta
; /* 1 */
3742 nrkj2
= iprod(r_kj
, r_kj
); /* 5 */
3743 nrij2
= iprod(r_ij
, r_ij
);
3745 cik
= st
*gmx::invsqrt(nrkj2
*nrij2
); /* 12 */
3746 cii
= sth
/nrij2
; /* 10 */
3747 ckk
= sth
/nrkj2
; /* 10 */
3749 for (m
= 0; (m
< DIM
); m
++) /* 39 */
3751 f_i
[m
] = -(cik
*r_kj
[m
]-cii
*r_ij
[m
]);
3752 f_k
[m
] = -(cik
*r_ij
[m
]-ckk
*r_kj
[m
]);
3753 f_j
[m
] = -f_i
[m
]-f_k
[m
];
3760 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
3762 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
3763 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
3764 t1
= IVEC2IS(dt_ij
);
3765 t2
= IVEC2IS(dt_kj
);
3767 rvec_inc(fshift
[t1
], f_i
);
3768 rvec_inc(fshift
[CENTRAL
], f_j
);
3769 rvec_inc(fshift
[t2
], f_k
);
3775 real
tab_dihs(int nbonds
,
3776 const t_iatom forceatoms
[], const t_iparams forceparams
[],
3777 const rvec x
[], rvec4 f
[], rvec fshift
[],
3778 const t_pbc
*pbc
, const t_graph
*g
,
3779 real lambda
, real
*dvdlambda
,
3780 const t_mdatoms gmx_unused
*md
, t_fcdata
*fcd
,
3781 int gmx_unused
*global_atom_index
)
3783 int i
, type
, ai
, aj
, ak
, al
, table
;
3785 rvec r_ij
, r_kj
, r_kl
, m
, n
;
3786 real phi
, ddphi
, vpd
, vtot
;
3789 for (i
= 0; (i
< nbonds
); )
3791 type
= forceatoms
[i
++];
3792 ai
= forceatoms
[i
++];
3793 aj
= forceatoms
[i
++];
3794 ak
= forceatoms
[i
++];
3795 al
= forceatoms
[i
++];
3797 phi
= dih_angle(x
[ai
], x
[aj
], x
[ak
], x
[al
], pbc
, r_ij
, r_kj
, r_kl
, m
, n
,
3798 &t1
, &t2
, &t3
); /* 84 */
3800 table
= forceparams
[type
].tab
.table
;
3802 /* Hopefully phi+M_PI never results in values < 0 */
3803 *dvdlambda
+= bonded_tab("dihedral", table
,
3804 &fcd
->dihtab
[table
],
3805 forceparams
[type
].tab
.kA
,
3806 forceparams
[type
].tab
.kB
,
3807 phi
+M_PI
, lambda
, &vpd
, &ddphi
);
3810 do_dih_fup(ai
, aj
, ak
, al
, -ddphi
, r_ij
, r_kj
, r_kl
, m
, n
,
3811 f
, fshift
, pbc
, g
, x
, t1
, t2
, t3
); /* 112 */