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, 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
= dr2
*gmx::invsqrt(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 */
401 fprintf(debug
, "BONDS: dr = %10g vbond = %10g fbond = %10g\n",
407 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, aj
), dt
);
410 for (m
= 0; (m
< DIM
); m
++) /* 15 */
415 fshift
[ki
][m
] += fij
;
416 fshift
[CENTRAL
][m
] -= fij
;
422 real
restraint_bonds(int nbonds
,
423 const t_iatom forceatoms
[], const t_iparams forceparams
[],
424 const rvec x
[], rvec4 f
[], rvec fshift
[],
425 const t_pbc
*pbc
, const t_graph
*g
,
426 real lambda
, real
*dvdlambda
,
427 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
428 int gmx_unused
*global_atom_index
)
430 int i
, m
, ki
, ai
, aj
, type
;
431 real dr
, dr2
, fbond
, vbond
, fij
, vtot
;
433 real low
, dlow
, up1
, dup1
, up2
, dup2
, k
, dk
;
441 for (i
= 0; (i
< nbonds
); )
443 type
= forceatoms
[i
++];
444 ai
= forceatoms
[i
++];
445 aj
= forceatoms
[i
++];
447 ki
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], dx
); /* 3 */
448 dr2
= iprod(dx
, dx
); /* 5 */
449 dr
= dr2
*gmx::invsqrt(dr2
); /* 10 */
451 low
= L1
*forceparams
[type
].restraint
.lowA
+ lambda
*forceparams
[type
].restraint
.lowB
;
452 dlow
= -forceparams
[type
].restraint
.lowA
+ forceparams
[type
].restraint
.lowB
;
453 up1
= L1
*forceparams
[type
].restraint
.up1A
+ lambda
*forceparams
[type
].restraint
.up1B
;
454 dup1
= -forceparams
[type
].restraint
.up1A
+ forceparams
[type
].restraint
.up1B
;
455 up2
= L1
*forceparams
[type
].restraint
.up2A
+ lambda
*forceparams
[type
].restraint
.up2B
;
456 dup2
= -forceparams
[type
].restraint
.up2A
+ forceparams
[type
].restraint
.up2B
;
457 k
= L1
*forceparams
[type
].restraint
.kA
+ lambda
*forceparams
[type
].restraint
.kB
;
458 dk
= -forceparams
[type
].restraint
.kA
+ forceparams
[type
].restraint
.kB
;
467 *dvdlambda
+= 0.5*dk
*drh2
- k
*dlow
*drh
;
480 *dvdlambda
+= 0.5*dk
*drh2
- k
*dup1
*drh
;
485 vbond
= k
*(up2
- up1
)*(0.5*(up2
- up1
) + drh
);
486 fbond
= -k
*(up2
- up1
);
487 *dvdlambda
+= dk
*(up2
- up1
)*(0.5*(up2
- up1
) + drh
)
488 + k
*(dup2
- dup1
)*(up2
- up1
+ drh
)
489 - k
*(up2
- up1
)*dup2
;
497 vtot
+= vbond
; /* 1*/
498 fbond
*= gmx::invsqrt(dr2
); /* 6 */
502 fprintf(debug
, "BONDS: dr = %10g vbond = %10g fbond = %10g\n",
508 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, aj
), dt
);
511 for (m
= 0; (m
< DIM
); m
++) /* 15 */
516 fshift
[ki
][m
] += fij
;
517 fshift
[CENTRAL
][m
] -= fij
;
524 real
polarize(int nbonds
,
525 const t_iatom forceatoms
[], const t_iparams forceparams
[],
526 const rvec x
[], rvec4 f
[], rvec fshift
[],
527 const t_pbc
*pbc
, const t_graph
*g
,
528 real lambda
, real
*dvdlambda
,
529 const t_mdatoms
*md
, t_fcdata gmx_unused
*fcd
,
530 int gmx_unused
*global_atom_index
)
532 int i
, m
, ki
, ai
, aj
, type
;
533 real dr
, dr2
, fbond
, vbond
, fij
, vtot
, ksh
;
538 for (i
= 0; (i
< nbonds
); )
540 type
= forceatoms
[i
++];
541 ai
= forceatoms
[i
++];
542 aj
= forceatoms
[i
++];
543 ksh
= gmx::square(md
->chargeA
[aj
])*ONE_4PI_EPS0
/forceparams
[type
].polarize
.alpha
;
546 fprintf(debug
, "POL: local ai = %d aj = %d ksh = %.3f\n", ai
, aj
, ksh
);
549 ki
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], dx
); /* 3 */
550 dr2
= iprod(dx
, dx
); /* 5 */
551 dr
= std::sqrt(dr2
); /* 10 */
553 *dvdlambda
+= harmonic(ksh
, ksh
, 0, 0, dr
, lambda
, &vbond
, &fbond
); /* 19 */
560 vtot
+= vbond
; /* 1*/
561 fbond
*= gmx::invsqrt(dr2
); /* 6 */
565 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, aj
), dt
);
568 for (m
= 0; (m
< DIM
); m
++) /* 15 */
573 fshift
[ki
][m
] += fij
;
574 fshift
[CENTRAL
][m
] -= fij
;
580 real
anharm_polarize(int nbonds
,
581 const t_iatom forceatoms
[], const t_iparams forceparams
[],
582 const rvec x
[], rvec4 f
[], rvec fshift
[],
583 const t_pbc
*pbc
, const t_graph
*g
,
584 real lambda
, real
*dvdlambda
,
585 const t_mdatoms
*md
, t_fcdata gmx_unused
*fcd
,
586 int gmx_unused
*global_atom_index
)
588 int i
, m
, ki
, ai
, aj
, type
;
589 real dr
, dr2
, fbond
, vbond
, fij
, vtot
, ksh
, khyp
, drcut
, ddr
, ddr3
;
594 for (i
= 0; (i
< nbonds
); )
596 type
= forceatoms
[i
++];
597 ai
= forceatoms
[i
++];
598 aj
= forceatoms
[i
++];
599 ksh
= gmx::square(md
->chargeA
[aj
])*ONE_4PI_EPS0
/forceparams
[type
].anharm_polarize
.alpha
; /* 7*/
600 khyp
= forceparams
[type
].anharm_polarize
.khyp
;
601 drcut
= forceparams
[type
].anharm_polarize
.drcut
;
604 fprintf(debug
, "POL: local ai = %d aj = %d ksh = %.3f\n", ai
, aj
, ksh
);
607 ki
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], dx
); /* 3 */
608 dr2
= iprod(dx
, dx
); /* 5 */
609 dr
= dr2
*gmx::invsqrt(dr2
); /* 10 */
611 *dvdlambda
+= harmonic(ksh
, ksh
, 0, 0, dr
, lambda
, &vbond
, &fbond
); /* 19 */
622 vbond
+= khyp
*ddr
*ddr3
;
623 fbond
-= 4*khyp
*ddr3
;
625 fbond
*= gmx::invsqrt(dr2
); /* 6 */
626 vtot
+= vbond
; /* 1*/
630 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, aj
), dt
);
633 for (m
= 0; (m
< DIM
); m
++) /* 15 */
638 fshift
[ki
][m
] += fij
;
639 fshift
[CENTRAL
][m
] -= fij
;
645 real
water_pol(int nbonds
,
646 const t_iatom forceatoms
[], const t_iparams forceparams
[],
647 const rvec x
[], rvec4 f
[], rvec gmx_unused fshift
[],
648 const t_pbc gmx_unused
*pbc
, const t_graph gmx_unused
*g
,
649 real gmx_unused lambda
, real gmx_unused
*dvdlambda
,
650 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
651 int gmx_unused
*global_atom_index
)
653 /* This routine implements anisotropic polarizibility for water, through
654 * a shell connected to a dummy with spring constant that differ in the
655 * three spatial dimensions in the molecular frame.
657 int i
, m
, aO
, aH1
, aH2
, aD
, aS
, type
, type0
, ki
;
659 rvec dOH1
, dOH2
, dHH
, dOD
, dDS
, nW
, kk
, dx
, kdx
, proj
;
663 real vtot
, fij
, r_HH
, r_OD
, r_nW
, tx
, ty
, tz
, qS
;
668 type0
= forceatoms
[0];
670 qS
= md
->chargeA
[aS
];
671 kk
[XX
] = gmx::square(qS
)*ONE_4PI_EPS0
/forceparams
[type0
].wpol
.al_x
;
672 kk
[YY
] = gmx::square(qS
)*ONE_4PI_EPS0
/forceparams
[type0
].wpol
.al_y
;
673 kk
[ZZ
] = gmx::square(qS
)*ONE_4PI_EPS0
/forceparams
[type0
].wpol
.al_z
;
674 r_HH
= 1.0/forceparams
[type0
].wpol
.rHH
;
677 fprintf(debug
, "WPOL: qS = %10.5f aS = %5d\n", qS
, aS
);
678 fprintf(debug
, "WPOL: kk = %10.3f %10.3f %10.3f\n",
679 kk
[XX
], kk
[YY
], kk
[ZZ
]);
680 fprintf(debug
, "WPOL: rOH = %10.3f rHH = %10.3f rOD = %10.3f\n",
681 forceparams
[type0
].wpol
.rOH
,
682 forceparams
[type0
].wpol
.rHH
,
683 forceparams
[type0
].wpol
.rOD
);
685 for (i
= 0; (i
< nbonds
); i
+= 6)
687 type
= forceatoms
[i
];
690 gmx_fatal(FARGS
, "Sorry, type = %d, type0 = %d, file = %s, line = %d",
691 type
, type0
, __FILE__
, __LINE__
);
693 aO
= forceatoms
[i
+1];
694 aH1
= forceatoms
[i
+2];
695 aH2
= forceatoms
[i
+3];
696 aD
= forceatoms
[i
+4];
697 aS
= forceatoms
[i
+5];
699 /* Compute vectors describing the water frame */
700 pbc_rvec_sub(pbc
, x
[aH1
], x
[aO
], dOH1
);
701 pbc_rvec_sub(pbc
, x
[aH2
], x
[aO
], dOH2
);
702 pbc_rvec_sub(pbc
, x
[aH2
], x
[aH1
], dHH
);
703 pbc_rvec_sub(pbc
, x
[aD
], x
[aO
], dOD
);
704 ki
= pbc_rvec_sub(pbc
, x
[aS
], x
[aD
], dDS
);
705 cprod(dOH1
, dOH2
, nW
);
707 /* Compute inverse length of normal vector
708 * (this one could be precomputed, but I'm too lazy now)
710 r_nW
= gmx::invsqrt(iprod(nW
, nW
));
711 /* This is for precision, but does not make a big difference,
714 r_OD
= gmx::invsqrt(iprod(dOD
, dOD
));
716 /* Normalize the vectors in the water frame */
718 svmul(r_HH
, dHH
, dHH
);
719 svmul(r_OD
, dOD
, dOD
);
721 /* Compute displacement of shell along components of the vector */
722 dx
[ZZ
] = iprod(dDS
, dOD
);
723 /* Compute projection on the XY plane: dDS - dx[ZZ]*dOD */
724 for (m
= 0; (m
< DIM
); m
++)
726 proj
[m
] = dDS
[m
]-dx
[ZZ
]*dOD
[m
];
729 /*dx[XX] = iprod(dDS,nW);
730 dx[YY] = iprod(dDS,dHH);*/
731 dx
[XX
] = iprod(proj
, nW
);
732 for (m
= 0; (m
< DIM
); m
++)
734 proj
[m
] -= dx
[XX
]*nW
[m
];
736 dx
[YY
] = iprod(proj
, dHH
);
741 fprintf(debug
, "WPOL: dx2=%10g dy2=%10g dz2=%10g sum=%10g dDS^2=%10g\n",
742 gmx::square(dx
[XX
]), gmx::square(dx
[YY
]), gmx::square(dx
[ZZ
]), iprod(dx
, dx
), iprod(dDS
, dDS
));
743 fprintf(debug
, "WPOL: dHH=(%10g,%10g,%10g)\n", dHH
[XX
], dHH
[YY
], dHH
[ZZ
]);
744 fprintf(debug
, "WPOL: dOD=(%10g,%10g,%10g), 1/r_OD = %10g\n",
745 dOD
[XX
], dOD
[YY
], dOD
[ZZ
], 1/r_OD
);
746 fprintf(debug
, "WPOL: nW =(%10g,%10g,%10g), 1/r_nW = %10g\n",
747 nW
[XX
], nW
[YY
], nW
[ZZ
], 1/r_nW
);
748 fprintf(debug
, "WPOL: dx =%10g, dy =%10g, dz =%10g\n",
749 dx
[XX
], dx
[YY
], dx
[ZZ
]);
750 fprintf(debug
, "WPOL: dDSx=%10g, dDSy=%10g, dDSz=%10g\n",
751 dDS
[XX
], dDS
[YY
], dDS
[ZZ
]);
754 /* Now compute the forces and energy */
755 kdx
[XX
] = kk
[XX
]*dx
[XX
];
756 kdx
[YY
] = kk
[YY
]*dx
[YY
];
757 kdx
[ZZ
] = kk
[ZZ
]*dx
[ZZ
];
758 vtot
+= iprod(dx
, kdx
);
762 ivec_sub(SHIFT_IVEC(g
, aS
), SHIFT_IVEC(g
, aD
), dt
);
766 for (m
= 0; (m
< DIM
); m
++)
768 /* This is a tensor operation but written out for speed */
778 fshift
[ki
][m
] += fij
;
779 fshift
[CENTRAL
][m
] -= fij
;
784 fprintf(debug
, "WPOL: vwpol=%g\n", 0.5*iprod(dx
, kdx
));
785 fprintf(debug
, "WPOL: df = (%10g, %10g, %10g)\n", df
[XX
], df
[YY
], df
[ZZ
]);
793 static real
do_1_thole(const rvec xi
, const rvec xj
, rvec fi
, rvec fj
,
794 const t_pbc
*pbc
, real qq
,
795 rvec fshift
[], real afac
)
798 real r12sq
, r12_1
, r12bar
, v0
, v1
, fscal
, ebar
, fff
;
801 t
= pbc_rvec_sub(pbc
, xi
, xj
, r12
); /* 3 */
803 r12sq
= iprod(r12
, r12
); /* 5 */
804 r12_1
= gmx::invsqrt(r12sq
); /* 5 */
805 r12bar
= afac
/r12_1
; /* 5 */
806 v0
= qq
*ONE_4PI_EPS0
*r12_1
; /* 2 */
807 ebar
= std::exp(-r12bar
); /* 5 */
808 v1
= (1-(1+0.5*r12bar
)*ebar
); /* 4 */
809 fscal
= ((v0
*r12_1
)*v1
- v0
*0.5*afac
*ebar
*(r12bar
+1))*r12_1
; /* 9 */
812 fprintf(debug
, "THOLE: v0 = %.3f v1 = %.3f r12= % .3f r12bar = %.3f fscal = %.3f ebar = %.3f\n", v0
, v1
, 1/r12_1
, r12bar
, fscal
, ebar
);
815 for (m
= 0; (m
< DIM
); m
++)
821 fshift
[CENTRAL
][m
] -= fff
;
824 return v0
*v1
; /* 1 */
828 real
thole_pol(int nbonds
,
829 const t_iatom forceatoms
[], const t_iparams forceparams
[],
830 const rvec x
[], rvec4 f
[], rvec fshift
[],
831 const t_pbc
*pbc
, const t_graph gmx_unused
*g
,
832 real gmx_unused lambda
, real gmx_unused
*dvdlambda
,
833 const t_mdatoms
*md
, t_fcdata gmx_unused
*fcd
,
834 int gmx_unused
*global_atom_index
)
836 /* Interaction between two pairs of particles with opposite charge */
837 int i
, type
, a1
, da1
, a2
, da2
;
838 real q1
, q2
, qq
, a
, al1
, al2
, afac
;
841 for (i
= 0; (i
< nbonds
); )
843 type
= forceatoms
[i
++];
844 a1
= forceatoms
[i
++];
845 da1
= forceatoms
[i
++];
846 a2
= forceatoms
[i
++];
847 da2
= forceatoms
[i
++];
848 q1
= md
->chargeA
[da1
];
849 q2
= md
->chargeA
[da2
];
850 a
= forceparams
[type
].thole
.a
;
851 al1
= forceparams
[type
].thole
.alpha1
;
852 al2
= forceparams
[type
].thole
.alpha2
;
854 afac
= a
*gmx::invsixthroot(al1
*al2
);
855 V
+= do_1_thole(x
[a1
], x
[a2
], f
[a1
], f
[a2
], pbc
, qq
, fshift
, afac
);
856 V
+= do_1_thole(x
[da1
], x
[a2
], f
[da1
], f
[a2
], pbc
, -qq
, fshift
, afac
);
857 V
+= do_1_thole(x
[a1
], x
[da2
], f
[a1
], f
[da2
], pbc
, -qq
, fshift
, afac
);
858 V
+= do_1_thole(x
[da1
], x
[da2
], f
[da1
], f
[da2
], pbc
, qq
, fshift
, afac
);
864 real
bond_angle(const rvec xi
, const rvec xj
, const rvec xk
, const t_pbc
*pbc
,
865 rvec r_ij
, rvec r_kj
, real
*costh
,
867 /* Return value is the angle between the bonds i-j and j-k */
872 *t1
= pbc_rvec_sub(pbc
, xi
, xj
, r_ij
); /* 3 */
873 *t2
= pbc_rvec_sub(pbc
, xk
, xj
, r_kj
); /* 3 */
875 *costh
= cos_angle(r_ij
, r_kj
); /* 25 */
876 th
= std::acos(*costh
); /* 10 */
881 real
angles(int nbonds
,
882 const t_iatom forceatoms
[], const t_iparams forceparams
[],
883 const rvec x
[], rvec4 f
[], rvec fshift
[],
884 const t_pbc
*pbc
, const t_graph
*g
,
885 real lambda
, real
*dvdlambda
,
886 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
887 int gmx_unused
*global_atom_index
)
889 int i
, ai
, aj
, ak
, t1
, t2
, type
;
891 real cos_theta
, cos_theta2
, theta
, dVdt
, va
, vtot
;
892 ivec jt
, dt_ij
, dt_kj
;
895 for (i
= 0; i
< nbonds
; )
897 type
= forceatoms
[i
++];
898 ai
= forceatoms
[i
++];
899 aj
= forceatoms
[i
++];
900 ak
= forceatoms
[i
++];
902 theta
= bond_angle(x
[ai
], x
[aj
], x
[ak
], pbc
,
903 r_ij
, r_kj
, &cos_theta
, &t1
, &t2
); /* 41 */
905 *dvdlambda
+= harmonic(forceparams
[type
].harmonic
.krA
,
906 forceparams
[type
].harmonic
.krB
,
907 forceparams
[type
].harmonic
.rA
*DEG2RAD
,
908 forceparams
[type
].harmonic
.rB
*DEG2RAD
,
909 theta
, lambda
, &va
, &dVdt
); /* 21 */
912 cos_theta2
= gmx::square(cos_theta
);
922 st
= dVdt
*gmx::invsqrt(1 - cos_theta2
); /* 12 */
923 sth
= st
*cos_theta
; /* 1 */
927 fprintf(debug
, "ANGLES: theta = %10g vth = %10g dV/dtheta = %10g\n",
928 theta
*RAD2DEG
, va
, dVdt
);
931 nrij2
= iprod(r_ij
, r_ij
); /* 5 */
932 nrkj2
= iprod(r_kj
, r_kj
); /* 5 */
934 nrij_1
= gmx::invsqrt(nrij2
); /* 10 */
935 nrkj_1
= gmx::invsqrt(nrkj2
); /* 10 */
937 cik
= st
*nrij_1
*nrkj_1
; /* 2 */
938 cii
= sth
*nrij_1
*nrij_1
; /* 2 */
939 ckk
= sth
*nrkj_1
*nrkj_1
; /* 2 */
941 for (m
= 0; m
< DIM
; m
++)
943 f_i
[m
] = -(cik
*r_kj
[m
] - cii
*r_ij
[m
]);
944 f_k
[m
] = -(cik
*r_ij
[m
] - ckk
*r_kj
[m
]);
945 f_j
[m
] = -f_i
[m
] - f_k
[m
];
952 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
954 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
955 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
959 rvec_inc(fshift
[t1
], f_i
);
960 rvec_inc(fshift
[CENTRAL
], f_j
);
961 rvec_inc(fshift
[t2
], f_k
);
968 #if GMX_SIMD_HAVE_REAL
970 /* As angles, but using SIMD to calculate many angles at once.
971 * This routines does not calculate energies and shift forces.
974 angles_noener_simd(int nbonds
,
975 const t_iatom forceatoms
[], const t_iparams forceparams
[],
976 const rvec x
[], rvec4 f
[],
977 const t_pbc
*pbc
, const t_graph gmx_unused
*g
,
978 real gmx_unused lambda
,
979 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
980 int gmx_unused
*global_atom_index
)
985 GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH
) ai
[GMX_SIMD_REAL_WIDTH
];
986 GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH
) aj
[GMX_SIMD_REAL_WIDTH
];
987 GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH
) ak
[GMX_SIMD_REAL_WIDTH
];
988 GMX_ALIGNED(real
, GMX_SIMD_REAL_WIDTH
) coeff
[2*GMX_SIMD_REAL_WIDTH
];
989 SimdReal
deg2rad_S(DEG2RAD
);
990 SimdReal xi_S
, yi_S
, zi_S
;
991 SimdReal xj_S
, yj_S
, zj_S
;
992 SimdReal xk_S
, yk_S
, zk_S
;
993 SimdReal k_S
, theta0_S
;
994 SimdReal rijx_S
, rijy_S
, rijz_S
;
995 SimdReal rkjx_S
, rkjy_S
, rkjz_S
;
997 SimdReal
min_one_plus_eps_S(-1.0 + 2.0*GMX_REAL_EPS
); // Smallest number > -1
1000 SimdReal nrij2_S
, nrij_1_S
;
1001 SimdReal nrkj2_S
, nrkj_1_S
;
1002 SimdReal cos_S
, invsin_S
;
1004 SimdReal st_S
, sth_S
;
1005 SimdReal cik_S
, cii_S
, ckk_S
;
1006 SimdReal f_ix_S
, f_iy_S
, f_iz_S
;
1007 SimdReal f_kx_S
, f_ky_S
, f_kz_S
;
1008 GMX_ALIGNED(real
, GMX_SIMD_REAL_WIDTH
) pbc_simd
[9*GMX_SIMD_REAL_WIDTH
];
1010 set_pbc_simd(pbc
, pbc_simd
);
1012 /* nbonds is the number of angles times nfa1, here we step GMX_SIMD_REAL_WIDTH angles */
1013 for (i
= 0; (i
< nbonds
); i
+= GMX_SIMD_REAL_WIDTH
*nfa1
)
1015 /* Collect atoms for GMX_SIMD_REAL_WIDTH angles.
1016 * iu indexes into forceatoms, we should not let iu go beyond nbonds.
1019 for (s
= 0; s
< GMX_SIMD_REAL_WIDTH
; s
++)
1021 type
= forceatoms
[iu
];
1022 ai
[s
] = forceatoms
[iu
+1];
1023 aj
[s
] = forceatoms
[iu
+2];
1024 ak
[s
] = forceatoms
[iu
+3];
1026 /* At the end fill the arrays with the last atoms and 0 params */
1027 if (i
+ s
*nfa1
< nbonds
)
1029 coeff
[s
] = forceparams
[type
].harmonic
.krA
;
1030 coeff
[GMX_SIMD_REAL_WIDTH
+s
] = forceparams
[type
].harmonic
.rA
;
1032 if (iu
+ nfa1
< nbonds
)
1040 coeff
[GMX_SIMD_REAL_WIDTH
+s
] = 0;
1044 /* Store the non PBC corrected distances packed and aligned */
1045 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), ai
, &xi_S
, &yi_S
, &zi_S
);
1046 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), aj
, &xj_S
, &yj_S
, &zj_S
);
1047 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), ak
, &xk_S
, &yk_S
, &zk_S
);
1048 rijx_S
= xi_S
- xj_S
;
1049 rijy_S
= yi_S
- yj_S
;
1050 rijz_S
= zi_S
- zj_S
;
1051 rkjx_S
= xk_S
- xj_S
;
1052 rkjy_S
= yk_S
- yj_S
;
1053 rkjz_S
= zk_S
- zj_S
;
1055 k_S
= load
<SimdReal
>(coeff
);
1056 theta0_S
= load
<SimdReal
>(coeff
+GMX_SIMD_REAL_WIDTH
) * deg2rad_S
;
1058 pbc_correct_dx_simd(&rijx_S
, &rijy_S
, &rijz_S
, pbc_simd
);
1059 pbc_correct_dx_simd(&rkjx_S
, &rkjy_S
, &rkjz_S
, pbc_simd
);
1061 rij_rkj_S
= iprod(rijx_S
, rijy_S
, rijz_S
,
1062 rkjx_S
, rkjy_S
, rkjz_S
);
1064 nrij2_S
= norm2(rijx_S
, rijy_S
, rijz_S
);
1065 nrkj2_S
= norm2(rkjx_S
, rkjy_S
, rkjz_S
);
1067 nrij_1_S
= invsqrt(nrij2_S
);
1068 nrkj_1_S
= invsqrt(nrkj2_S
);
1070 cos_S
= rij_rkj_S
* nrij_1_S
* nrkj_1_S
;
1072 /* To allow for 180 degrees, we take the max of cos and -1 + 1bit,
1073 * so we can safely get the 1/sin from 1/sqrt(1 - cos^2).
1074 * This also ensures that rounding errors would cause the argument
1075 * of simdAcos to be < -1.
1076 * Note that we do not take precautions for cos(0)=1, so the outer
1077 * atoms in an angle should not be on top of each other.
1079 cos_S
= max(cos_S
, min_one_plus_eps_S
);
1081 theta_S
= acos(cos_S
);
1083 invsin_S
= invsqrt( one_S
- cos_S
* cos_S
);
1085 st_S
= k_S
* (theta0_S
- theta_S
) * invsin_S
;
1086 sth_S
= st_S
* cos_S
;
1088 cik_S
= st_S
* nrij_1_S
* nrkj_1_S
;
1089 cii_S
= sth_S
* nrij_1_S
* nrij_1_S
;
1090 ckk_S
= sth_S
* nrkj_1_S
* nrkj_1_S
;
1092 f_ix_S
= cii_S
* rijx_S
;
1093 f_ix_S
= fnma(cik_S
, rkjx_S
, f_ix_S
);
1094 f_iy_S
= cii_S
* rijy_S
;
1095 f_iy_S
= fnma(cik_S
, rkjy_S
, f_iy_S
);
1096 f_iz_S
= cii_S
* rijz_S
;
1097 f_iz_S
= fnma(cik_S
, rkjz_S
, f_iz_S
);
1098 f_kx_S
= ckk_S
* rkjx_S
;
1099 f_kx_S
= fnma(cik_S
, rijx_S
, f_kx_S
);
1100 f_ky_S
= ckk_S
* rkjy_S
;
1101 f_ky_S
= fnma(cik_S
, rijy_S
, f_ky_S
);
1102 f_kz_S
= ckk_S
* rkjz_S
;
1103 f_kz_S
= fnma(cik_S
, rijz_S
, f_kz_S
);
1105 transposeScatterIncrU
<4>(reinterpret_cast<real
*>(f
), ai
, f_ix_S
, f_iy_S
, f_iz_S
);
1106 transposeScatterDecrU
<4>(reinterpret_cast<real
*>(f
), aj
, f_ix_S
+ f_kx_S
, f_iy_S
+ f_ky_S
, f_iz_S
+ f_kz_S
);
1107 transposeScatterIncrU
<4>(reinterpret_cast<real
*>(f
), ak
, f_kx_S
, f_ky_S
, f_kz_S
);
1111 #endif // GMX_SIMD_HAVE_REAL
1113 real
linear_angles(int nbonds
,
1114 const t_iatom forceatoms
[], const t_iparams forceparams
[],
1115 const rvec x
[], rvec4 f
[], rvec fshift
[],
1116 const t_pbc
*pbc
, const t_graph
*g
,
1117 real lambda
, real
*dvdlambda
,
1118 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
1119 int gmx_unused
*global_atom_index
)
1121 int i
, m
, ai
, aj
, ak
, t1
, t2
, type
;
1123 real L1
, kA
, kB
, aA
, aB
, dr
, dr2
, va
, vtot
, a
, b
, klin
;
1124 ivec jt
, dt_ij
, dt_kj
;
1125 rvec r_ij
, r_kj
, r_ik
, dx
;
1129 for (i
= 0; (i
< nbonds
); )
1131 type
= forceatoms
[i
++];
1132 ai
= forceatoms
[i
++];
1133 aj
= forceatoms
[i
++];
1134 ak
= forceatoms
[i
++];
1136 kA
= forceparams
[type
].linangle
.klinA
;
1137 kB
= forceparams
[type
].linangle
.klinB
;
1138 klin
= L1
*kA
+ lambda
*kB
;
1140 aA
= forceparams
[type
].linangle
.aA
;
1141 aB
= forceparams
[type
].linangle
.aB
;
1142 a
= L1
*aA
+lambda
*aB
;
1145 t1
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], r_ij
);
1146 t2
= pbc_rvec_sub(pbc
, x
[ak
], x
[aj
], r_kj
);
1147 rvec_sub(r_ij
, r_kj
, r_ik
);
1150 for (m
= 0; (m
< DIM
); m
++)
1152 dr
= -a
* r_ij
[m
] - b
* r_kj
[m
];
1157 f_j
[m
] = -(f_i
[m
]+f_k
[m
]);
1163 *dvdlambda
+= 0.5*(kB
-kA
)*dr2
+ klin
*(aB
-aA
)*iprod(dx
, r_ik
);
1169 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
1171 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
1172 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
1173 t1
= IVEC2IS(dt_ij
);
1174 t2
= IVEC2IS(dt_kj
);
1176 rvec_inc(fshift
[t1
], f_i
);
1177 rvec_inc(fshift
[CENTRAL
], f_j
);
1178 rvec_inc(fshift
[t2
], f_k
);
1183 real
urey_bradley(int nbonds
,
1184 const t_iatom forceatoms
[], const t_iparams forceparams
[],
1185 const rvec x
[], rvec4 f
[], rvec fshift
[],
1186 const t_pbc
*pbc
, const t_graph
*g
,
1187 real lambda
, real
*dvdlambda
,
1188 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
1189 int gmx_unused
*global_atom_index
)
1191 int i
, m
, ai
, aj
, ak
, t1
, t2
, type
, ki
;
1192 rvec r_ij
, r_kj
, r_ik
;
1193 real cos_theta
, cos_theta2
, theta
;
1194 real dVdt
, va
, vtot
, dr
, dr2
, vbond
, fbond
, fik
;
1195 real kthA
, th0A
, kUBA
, r13A
, kthB
, th0B
, kUBB
, r13B
;
1196 ivec jt
, dt_ij
, dt_kj
, dt_ik
;
1199 for (i
= 0; (i
< nbonds
); )
1201 type
= forceatoms
[i
++];
1202 ai
= forceatoms
[i
++];
1203 aj
= forceatoms
[i
++];
1204 ak
= forceatoms
[i
++];
1205 th0A
= forceparams
[type
].u_b
.thetaA
*DEG2RAD
;
1206 kthA
= forceparams
[type
].u_b
.kthetaA
;
1207 r13A
= forceparams
[type
].u_b
.r13A
;
1208 kUBA
= forceparams
[type
].u_b
.kUBA
;
1209 th0B
= forceparams
[type
].u_b
.thetaB
*DEG2RAD
;
1210 kthB
= forceparams
[type
].u_b
.kthetaB
;
1211 r13B
= forceparams
[type
].u_b
.r13B
;
1212 kUBB
= forceparams
[type
].u_b
.kUBB
;
1214 theta
= bond_angle(x
[ai
], x
[aj
], x
[ak
], pbc
,
1215 r_ij
, r_kj
, &cos_theta
, &t1
, &t2
); /* 41 */
1217 *dvdlambda
+= harmonic(kthA
, kthB
, th0A
, th0B
, theta
, lambda
, &va
, &dVdt
); /* 21 */
1220 ki
= pbc_rvec_sub(pbc
, x
[ai
], x
[ak
], r_ik
); /* 3 */
1221 dr2
= iprod(r_ik
, r_ik
); /* 5 */
1222 dr
= dr2
*gmx::invsqrt(dr2
); /* 10 */
1224 *dvdlambda
+= harmonic(kUBA
, kUBB
, r13A
, r13B
, dr
, lambda
, &vbond
, &fbond
); /* 19 */
1226 cos_theta2
= gmx::square(cos_theta
); /* 1 */
1234 st
= dVdt
*gmx::invsqrt(1 - cos_theta2
); /* 12 */
1235 sth
= st
*cos_theta
; /* 1 */
1239 fprintf(debug
, "ANGLES: theta = %10g vth = %10g dV/dtheta = %10g\n",
1240 theta
*RAD2DEG
, va
, dVdt
);
1243 nrkj2
= iprod(r_kj
, r_kj
); /* 5 */
1244 nrij2
= iprod(r_ij
, r_ij
);
1246 cik
= st
*gmx::invsqrt(nrkj2
*nrij2
); /* 12 */
1247 cii
= sth
/nrij2
; /* 10 */
1248 ckk
= sth
/nrkj2
; /* 10 */
1250 for (m
= 0; (m
< DIM
); m
++) /* 39 */
1252 f_i
[m
] = -(cik
*r_kj
[m
]-cii
*r_ij
[m
]);
1253 f_k
[m
] = -(cik
*r_ij
[m
]-ckk
*r_kj
[m
]);
1254 f_j
[m
] = -f_i
[m
]-f_k
[m
];
1261 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
1263 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
1264 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
1265 t1
= IVEC2IS(dt_ij
);
1266 t2
= IVEC2IS(dt_kj
);
1268 rvec_inc(fshift
[t1
], f_i
);
1269 rvec_inc(fshift
[CENTRAL
], f_j
);
1270 rvec_inc(fshift
[t2
], f_k
);
1272 /* Time for the bond calculations */
1278 vtot
+= vbond
; /* 1*/
1279 fbond
*= gmx::invsqrt(dr2
); /* 6 */
1283 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, ak
), dt_ik
);
1284 ki
= IVEC2IS(dt_ik
);
1286 for (m
= 0; (m
< DIM
); m
++) /* 15 */
1288 fik
= fbond
*r_ik
[m
];
1291 fshift
[ki
][m
] += fik
;
1292 fshift
[CENTRAL
][m
] -= fik
;
1298 #if GMX_SIMD_HAVE_REAL
1300 /* As urey_bradley, but using SIMD to calculate many potentials at once.
1301 * This routines does not calculate energies and shift forces.
1303 void urey_bradley_noener_simd(int nbonds
,
1304 const t_iatom forceatoms
[], const t_iparams forceparams
[],
1305 const rvec x
[], rvec4 f
[],
1306 const t_pbc
*pbc
, const t_graph gmx_unused
*g
,
1307 real gmx_unused lambda
,
1308 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
1309 int gmx_unused
*global_atom_index
)
1311 constexpr int nfa1
= 4;
1312 GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH
) ai
[GMX_SIMD_REAL_WIDTH
];
1313 GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH
) aj
[GMX_SIMD_REAL_WIDTH
];
1314 GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH
) ak
[GMX_SIMD_REAL_WIDTH
];
1315 GMX_ALIGNED(real
, GMX_SIMD_REAL_WIDTH
) coeff
[4*GMX_SIMD_REAL_WIDTH
];
1316 GMX_ALIGNED(real
, GMX_SIMD_REAL_WIDTH
) pbc_simd
[9*GMX_SIMD_REAL_WIDTH
];
1318 set_pbc_simd(pbc
, pbc_simd
);
1320 /* nbonds is the number of angles times nfa1, here we step GMX_SIMD_REAL_WIDTH angles */
1321 for (int i
= 0; i
< nbonds
; i
+= GMX_SIMD_REAL_WIDTH
*nfa1
)
1323 /* Collect atoms for GMX_SIMD_REAL_WIDTH angles.
1324 * iu indexes into forceatoms, we should not let iu go beyond nbonds.
1327 for (int s
= 0; s
< GMX_SIMD_REAL_WIDTH
; s
++)
1329 const int type
= forceatoms
[iu
];
1330 ai
[s
] = forceatoms
[iu
+1];
1331 aj
[s
] = forceatoms
[iu
+2];
1332 ak
[s
] = forceatoms
[iu
+3];
1334 /* At the end fill the arrays with the last atoms and 0 params */
1335 if (i
+ s
*nfa1
< nbonds
)
1337 coeff
[s
] = forceparams
[type
].u_b
.kthetaA
;
1338 coeff
[GMX_SIMD_REAL_WIDTH
+s
] = forceparams
[type
].u_b
.thetaA
;
1339 coeff
[GMX_SIMD_REAL_WIDTH
*2+s
] = forceparams
[type
].u_b
.kUBA
;
1340 coeff
[GMX_SIMD_REAL_WIDTH
*3+s
] = forceparams
[type
].u_b
.r13A
;
1342 if (iu
+ nfa1
< nbonds
)
1350 coeff
[GMX_SIMD_REAL_WIDTH
+s
] = 0;
1351 coeff
[GMX_SIMD_REAL_WIDTH
*2+s
] = 0;
1352 coeff
[GMX_SIMD_REAL_WIDTH
*3+s
] = 0;
1356 SimdReal xi_S
, yi_S
, zi_S
;
1357 SimdReal xj_S
, yj_S
, zj_S
;
1358 SimdReal xk_S
, yk_S
, zk_S
;
1360 /* Store the non PBC corrected distances packed and aligned */
1361 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), ai
, &xi_S
, &yi_S
, &zi_S
);
1362 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), aj
, &xj_S
, &yj_S
, &zj_S
);
1363 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), ak
, &xk_S
, &yk_S
, &zk_S
);
1364 SimdReal rijx_S
= xi_S
- xj_S
;
1365 SimdReal rijy_S
= yi_S
- yj_S
;
1366 SimdReal rijz_S
= zi_S
- zj_S
;
1367 SimdReal rkjx_S
= xk_S
- xj_S
;
1368 SimdReal rkjy_S
= yk_S
- yj_S
;
1369 SimdReal rkjz_S
= zk_S
- zj_S
;
1370 SimdReal rikx_S
= xi_S
- xk_S
;
1371 SimdReal riky_S
= yi_S
- yk_S
;
1372 SimdReal rikz_S
= zi_S
- zk_S
;
1374 const SimdReal ktheta_S
= load
<SimdReal
>(coeff
);
1375 const SimdReal theta0_S
= load
<SimdReal
>(coeff
+GMX_SIMD_REAL_WIDTH
) * DEG2RAD
;
1376 const SimdReal kUB_S
= load
<SimdReal
>(coeff
+2*GMX_SIMD_REAL_WIDTH
);
1377 const SimdReal r13_S
= load
<SimdReal
>(coeff
+3*GMX_SIMD_REAL_WIDTH
);
1379 pbc_correct_dx_simd(&rijx_S
, &rijy_S
, &rijz_S
, pbc_simd
);
1380 pbc_correct_dx_simd(&rkjx_S
, &rkjy_S
, &rkjz_S
, pbc_simd
);
1381 pbc_correct_dx_simd(&rikx_S
, &riky_S
, &rikz_S
, pbc_simd
);
1383 const SimdReal rij_rkj_S
= iprod(rijx_S
, rijy_S
, rijz_S
,
1384 rkjx_S
, rkjy_S
, rkjz_S
);
1386 const SimdReal dr2_S
= iprod(rikx_S
, riky_S
, rikz_S
,
1387 rikx_S
, riky_S
, rikz_S
);
1389 const SimdReal nrij2_S
= norm2(rijx_S
, rijy_S
, rijz_S
);
1390 const SimdReal nrkj2_S
= norm2(rkjx_S
, rkjy_S
, rkjz_S
);
1392 const SimdReal nrij_1_S
= invsqrt(nrij2_S
);
1393 const SimdReal nrkj_1_S
= invsqrt(nrkj2_S
);
1394 const SimdReal invdr2_S
= invsqrt(dr2_S
);
1395 const SimdReal dr_S
= dr2_S
*invdr2_S
;
1397 constexpr real min_one_plus_eps
= -1.0 + 2.0*GMX_REAL_EPS
; // Smallest number > -1
1399 /* To allow for 180 degrees, we take the max of cos and -1 + 1bit,
1400 * so we can safely get the 1/sin from 1/sqrt(1 - cos^2).
1401 * This also ensures that rounding errors would cause the argument
1402 * of simdAcos to be < -1.
1403 * Note that we do not take precautions for cos(0)=1, so the bonds
1404 * in an angle should not align at an angle of 0 degrees.
1406 const SimdReal cos_S
= max(rij_rkj_S
* nrij_1_S
* nrkj_1_S
, min_one_plus_eps
);
1408 const SimdReal theta_S
= acos(cos_S
);
1409 const SimdReal invsin_S
= invsqrt( 1.0 - cos_S
* cos_S
);
1410 const SimdReal st_S
= ktheta_S
* (theta0_S
- theta_S
) * invsin_S
;
1411 const SimdReal sth_S
= st_S
* cos_S
;
1413 const SimdReal cik_S
= st_S
* nrij_1_S
* nrkj_1_S
;
1414 const SimdReal cii_S
= sth_S
* nrij_1_S
* nrij_1_S
;
1415 const SimdReal ckk_S
= sth_S
* nrkj_1_S
* nrkj_1_S
;
1417 const SimdReal sUB_S
= kUB_S
* (r13_S
- dr_S
) * invdr2_S
;
1419 const SimdReal f_ikx_S
= sUB_S
* rikx_S
;
1420 const SimdReal f_iky_S
= sUB_S
* riky_S
;
1421 const SimdReal f_ikz_S
= sUB_S
* rikz_S
;
1423 const SimdReal f_ix_S
= fnma(cik_S
, rkjx_S
, cii_S
* rijx_S
) + f_ikx_S
;
1424 const SimdReal f_iy_S
= fnma(cik_S
, rkjy_S
, cii_S
* rijy_S
) + f_iky_S
;
1425 const SimdReal f_iz_S
= fnma(cik_S
, rkjz_S
, cii_S
* rijz_S
) + f_ikz_S
;
1426 const SimdReal f_kx_S
= fnma(cik_S
, rijx_S
, ckk_S
* rkjx_S
) - f_ikx_S
;
1427 const SimdReal f_ky_S
= fnma(cik_S
, rijy_S
, ckk_S
* rkjy_S
) - f_iky_S
;
1428 const SimdReal f_kz_S
= fnma(cik_S
, rijz_S
, ckk_S
* rkjz_S
) - f_ikz_S
;
1430 transposeScatterIncrU
<4>(reinterpret_cast<real
*>(f
), ai
, f_ix_S
, f_iy_S
, f_iz_S
);
1431 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
);
1432 transposeScatterIncrU
<4>(reinterpret_cast<real
*>(f
), ak
, f_kx_S
, f_ky_S
, f_kz_S
);
1436 #endif // GMX_SIMD_HAVE_REAL
1438 real
quartic_angles(int nbonds
,
1439 const t_iatom forceatoms
[], const t_iparams forceparams
[],
1440 const rvec x
[], rvec4 f
[], rvec fshift
[],
1441 const t_pbc
*pbc
, const t_graph
*g
,
1442 real gmx_unused lambda
, real gmx_unused
*dvdlambda
,
1443 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
1444 int gmx_unused
*global_atom_index
)
1446 int i
, j
, ai
, aj
, ak
, t1
, t2
, type
;
1448 real cos_theta
, cos_theta2
, theta
, dt
, dVdt
, va
, dtp
, c
, vtot
;
1449 ivec jt
, dt_ij
, dt_kj
;
1452 for (i
= 0; (i
< nbonds
); )
1454 type
= forceatoms
[i
++];
1455 ai
= forceatoms
[i
++];
1456 aj
= forceatoms
[i
++];
1457 ak
= forceatoms
[i
++];
1459 theta
= bond_angle(x
[ai
], x
[aj
], x
[ak
], pbc
,
1460 r_ij
, r_kj
, &cos_theta
, &t1
, &t2
); /* 41 */
1462 dt
= theta
- forceparams
[type
].qangle
.theta
*DEG2RAD
; /* 2 */
1465 va
= forceparams
[type
].qangle
.c
[0];
1467 for (j
= 1; j
<= 4; j
++)
1469 c
= forceparams
[type
].qangle
.c
[j
];
1478 cos_theta2
= gmx::square(cos_theta
); /* 1 */
1487 st
= dVdt
*gmx::invsqrt(1 - cos_theta2
); /* 12 */
1488 sth
= st
*cos_theta
; /* 1 */
1492 fprintf(debug
, "ANGLES: theta = %10g vth = %10g dV/dtheta = %10g\n",
1493 theta
*RAD2DEG
, va
, dVdt
);
1496 nrkj2
= iprod(r_kj
, r_kj
); /* 5 */
1497 nrij2
= iprod(r_ij
, r_ij
);
1499 cik
= st
*gmx::invsqrt(nrkj2
*nrij2
); /* 12 */
1500 cii
= sth
/nrij2
; /* 10 */
1501 ckk
= sth
/nrkj2
; /* 10 */
1503 for (m
= 0; (m
< DIM
); m
++) /* 39 */
1505 f_i
[m
] = -(cik
*r_kj
[m
]-cii
*r_ij
[m
]);
1506 f_k
[m
] = -(cik
*r_ij
[m
]-ckk
*r_kj
[m
]);
1507 f_j
[m
] = -f_i
[m
]-f_k
[m
];
1514 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
1516 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
1517 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
1518 t1
= IVEC2IS(dt_ij
);
1519 t2
= IVEC2IS(dt_kj
);
1521 rvec_inc(fshift
[t1
], f_i
);
1522 rvec_inc(fshift
[CENTRAL
], f_j
);
1523 rvec_inc(fshift
[t2
], f_k
);
1529 real
dih_angle(const rvec xi
, const rvec xj
, const rvec xk
, const rvec xl
,
1531 rvec r_ij
, rvec r_kj
, rvec r_kl
, rvec m
, rvec n
,
1532 int *t1
, int *t2
, int *t3
)
1534 *t1
= pbc_rvec_sub(pbc
, xi
, xj
, r_ij
); /* 3 */
1535 *t2
= pbc_rvec_sub(pbc
, xk
, xj
, r_kj
); /* 3 */
1536 *t3
= pbc_rvec_sub(pbc
, xk
, xl
, r_kl
); /* 3 */
1538 cprod(r_ij
, r_kj
, m
); /* 9 */
1539 cprod(r_kj
, r_kl
, n
); /* 9 */
1540 real phi
= gmx_angle(m
, n
); /* 49 (assuming 25 for atan2) */
1541 real ipr
= iprod(r_ij
, n
); /* 5 */
1542 real sign
= (ipr
< 0.0) ? -1.0 : 1.0;
1543 phi
= sign
*phi
; /* 1 */
1549 #if GMX_SIMD_HAVE_REAL
1551 /* As dih_angle above, but calculates 4 dihedral angles at once using SIMD,
1552 * also calculates the pre-factor required for the dihedral force update.
1553 * Note that bv and buf should be register aligned.
1555 static gmx_inline
void
1556 dih_angle_simd(const rvec
*x
,
1557 const int *ai
, const int *aj
, const int *ak
, const int *al
,
1558 const real
*pbc_simd
,
1560 SimdReal
*mx_S
, SimdReal
*my_S
, SimdReal
*mz_S
,
1561 SimdReal
*nx_S
, SimdReal
*ny_S
, SimdReal
*nz_S
,
1562 SimdReal
*nrkj_m2_S
,
1563 SimdReal
*nrkj_n2_S
,
1567 SimdReal xi_S
, yi_S
, zi_S
;
1568 SimdReal xj_S
, yj_S
, zj_S
;
1569 SimdReal xk_S
, yk_S
, zk_S
;
1570 SimdReal xl_S
, yl_S
, zl_S
;
1571 SimdReal rijx_S
, rijy_S
, rijz_S
;
1572 SimdReal rkjx_S
, rkjy_S
, rkjz_S
;
1573 SimdReal rklx_S
, rkly_S
, rklz_S
;
1574 SimdReal cx_S
, cy_S
, cz_S
;
1578 SimdReal iprm_S
, iprn_S
;
1579 SimdReal nrkj2_S
, nrkj_1_S
, nrkj_2_S
, nrkj_S
;
1581 SimdReal nrkj2_min_S
;
1582 SimdReal real_eps_S
;
1584 /* Used to avoid division by zero.
1585 * We take into acount that we multiply the result by real_eps_S.
1587 nrkj2_min_S
= SimdReal(GMX_REAL_MIN
/(2*GMX_REAL_EPS
));
1589 /* The value of the last significant bit (GMX_REAL_EPS is half of that) */
1590 real_eps_S
= SimdReal(2*GMX_REAL_EPS
);
1592 /* Store the non PBC corrected distances packed and aligned */
1593 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), ai
, &xi_S
, &yi_S
, &zi_S
);
1594 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), aj
, &xj_S
, &yj_S
, &zj_S
);
1595 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), ak
, &xk_S
, &yk_S
, &zk_S
);
1596 gatherLoadUTranspose
<3>(reinterpret_cast<const real
*>(x
), al
, &xl_S
, &yl_S
, &zl_S
);
1597 rijx_S
= xi_S
- xj_S
;
1598 rijy_S
= yi_S
- yj_S
;
1599 rijz_S
= zi_S
- zj_S
;
1600 rkjx_S
= xk_S
- xj_S
;
1601 rkjy_S
= yk_S
- yj_S
;
1602 rkjz_S
= zk_S
- zj_S
;
1603 rklx_S
= xk_S
- xl_S
;
1604 rkly_S
= yk_S
- yl_S
;
1605 rklz_S
= zk_S
- zl_S
;
1607 pbc_correct_dx_simd(&rijx_S
, &rijy_S
, &rijz_S
, pbc_simd
);
1608 pbc_correct_dx_simd(&rkjx_S
, &rkjy_S
, &rkjz_S
, pbc_simd
);
1609 pbc_correct_dx_simd(&rklx_S
, &rkly_S
, &rklz_S
, pbc_simd
);
1611 cprod(rijx_S
, rijy_S
, rijz_S
,
1612 rkjx_S
, rkjy_S
, rkjz_S
,
1615 cprod(rkjx_S
, rkjy_S
, rkjz_S
,
1616 rklx_S
, rkly_S
, rklz_S
,
1619 cprod(*mx_S
, *my_S
, *mz_S
,
1620 *nx_S
, *ny_S
, *nz_S
,
1621 &cx_S
, &cy_S
, &cz_S
);
1623 cn_S
= sqrt(norm2(cx_S
, cy_S
, cz_S
));
1625 s_S
= iprod(*mx_S
, *my_S
, *mz_S
, *nx_S
, *ny_S
, *nz_S
);
1627 /* Determine the dihedral angle, the sign might need correction */
1628 *phi_S
= atan2(cn_S
, s_S
);
1630 ipr_S
= iprod(rijx_S
, rijy_S
, rijz_S
,
1631 *nx_S
, *ny_S
, *nz_S
);
1633 iprm_S
= norm2(*mx_S
, *my_S
, *mz_S
);
1634 iprn_S
= norm2(*nx_S
, *ny_S
, *nz_S
);
1636 nrkj2_S
= norm2(rkjx_S
, rkjy_S
, rkjz_S
);
1638 /* Avoid division by zero. When zero, the result is multiplied by 0
1639 * anyhow, so the 3 max below do not affect the final result.
1641 nrkj2_S
= max(nrkj2_S
, nrkj2_min_S
);
1642 nrkj_1_S
= invsqrt(nrkj2_S
);
1643 nrkj_2_S
= nrkj_1_S
* nrkj_1_S
;
1644 nrkj_S
= nrkj2_S
* nrkj_1_S
;
1646 toler_S
= nrkj2_S
* real_eps_S
;
1648 /* Here the plain-C code uses a conditional, but we can't do that in SIMD.
1649 * So we take a max with the tolerance instead. Since we multiply with
1650 * m or n later, the max does not affect the results.
1652 iprm_S
= max(iprm_S
, toler_S
);
1653 iprn_S
= max(iprn_S
, toler_S
);
1654 *nrkj_m2_S
= nrkj_S
* inv(iprm_S
);
1655 *nrkj_n2_S
= nrkj_S
* inv(iprn_S
);
1657 /* Set sign of phi_S with the sign of ipr_S; phi_S is currently positive */
1658 *phi_S
= copysign(*phi_S
, ipr_S
);
1659 *p_S
= iprod(rijx_S
, rijy_S
, rijz_S
, rkjx_S
, rkjy_S
, rkjz_S
);
1660 *p_S
= *p_S
* nrkj_2_S
;
1662 *q_S
= iprod(rklx_S
, rkly_S
, rklz_S
, rkjx_S
, rkjy_S
, rkjz_S
);
1663 *q_S
= *q_S
* nrkj_2_S
;
1666 #endif // GMX_SIMD_HAVE_REAL
1668 void do_dih_fup(int i
, int j
, int k
, int l
, real ddphi
,
1669 rvec r_ij
, rvec r_kj
, rvec r_kl
,
1670 rvec m
, rvec n
, rvec4 f
[], rvec fshift
[],
1671 const t_pbc
*pbc
, const t_graph
*g
,
1672 const rvec x
[], int t1
, int t2
, int t3
)
1675 rvec f_i
, f_j
, f_k
, f_l
;
1676 rvec uvec
, vvec
, svec
, dx_jl
;
1677 real iprm
, iprn
, nrkj
, nrkj2
, nrkj_1
, nrkj_2
;
1678 real a
, b
, p
, q
, toler
;
1679 ivec jt
, dt_ij
, dt_kj
, dt_lj
;
1681 iprm
= iprod(m
, m
); /* 5 */
1682 iprn
= iprod(n
, n
); /* 5 */
1683 nrkj2
= iprod(r_kj
, r_kj
); /* 5 */
1684 toler
= nrkj2
*GMX_REAL_EPS
;
1685 if ((iprm
> toler
) && (iprn
> toler
))
1687 nrkj_1
= gmx::invsqrt(nrkj2
); /* 10 */
1688 nrkj_2
= nrkj_1
*nrkj_1
; /* 1 */
1689 nrkj
= nrkj2
*nrkj_1
; /* 1 */
1690 a
= -ddphi
*nrkj
/iprm
; /* 11 */
1691 svmul(a
, m
, f_i
); /* 3 */
1692 b
= ddphi
*nrkj
/iprn
; /* 11 */
1693 svmul(b
, n
, f_l
); /* 3 */
1694 p
= iprod(r_ij
, r_kj
); /* 5 */
1695 p
*= nrkj_2
; /* 1 */
1696 q
= iprod(r_kl
, r_kj
); /* 5 */
1697 q
*= nrkj_2
; /* 1 */
1698 svmul(p
, f_i
, uvec
); /* 3 */
1699 svmul(q
, f_l
, vvec
); /* 3 */
1700 rvec_sub(uvec
, vvec
, svec
); /* 3 */
1701 rvec_sub(f_i
, svec
, f_j
); /* 3 */
1702 rvec_add(f_l
, svec
, f_k
); /* 3 */
1703 rvec_inc(f
[i
], f_i
); /* 3 */
1704 rvec_dec(f
[j
], f_j
); /* 3 */
1705 rvec_dec(f
[k
], f_k
); /* 3 */
1706 rvec_inc(f
[l
], f_l
); /* 3 */
1710 copy_ivec(SHIFT_IVEC(g
, j
), jt
);
1711 ivec_sub(SHIFT_IVEC(g
, i
), jt
, dt_ij
);
1712 ivec_sub(SHIFT_IVEC(g
, k
), jt
, dt_kj
);
1713 ivec_sub(SHIFT_IVEC(g
, l
), jt
, dt_lj
);
1714 t1
= IVEC2IS(dt_ij
);
1715 t2
= IVEC2IS(dt_kj
);
1716 t3
= IVEC2IS(dt_lj
);
1720 t3
= pbc_rvec_sub(pbc
, x
[l
], x
[j
], dx_jl
);
1727 rvec_inc(fshift
[t1
], f_i
);
1728 rvec_dec(fshift
[CENTRAL
], f_j
);
1729 rvec_dec(fshift
[t2
], f_k
);
1730 rvec_inc(fshift
[t3
], f_l
);
1735 /* As do_dih_fup above, but without shift forces */
1737 do_dih_fup_noshiftf(int i
, int j
, int k
, int l
, real ddphi
,
1738 rvec r_ij
, rvec r_kj
, rvec r_kl
,
1739 rvec m
, rvec n
, rvec4 f
[])
1741 rvec f_i
, f_j
, f_k
, f_l
;
1742 rvec uvec
, vvec
, svec
;
1743 real iprm
, iprn
, nrkj
, nrkj2
, nrkj_1
, nrkj_2
;
1744 real a
, b
, p
, q
, toler
;
1746 iprm
= iprod(m
, m
); /* 5 */
1747 iprn
= iprod(n
, n
); /* 5 */
1748 nrkj2
= iprod(r_kj
, r_kj
); /* 5 */
1749 toler
= nrkj2
*GMX_REAL_EPS
;
1750 if ((iprm
> toler
) && (iprn
> toler
))
1752 nrkj_1
= gmx::invsqrt(nrkj2
); /* 10 */
1753 nrkj_2
= nrkj_1
*nrkj_1
; /* 1 */
1754 nrkj
= nrkj2
*nrkj_1
; /* 1 */
1755 a
= -ddphi
*nrkj
/iprm
; /* 11 */
1756 svmul(a
, m
, f_i
); /* 3 */
1757 b
= ddphi
*nrkj
/iprn
; /* 11 */
1758 svmul(b
, n
, f_l
); /* 3 */
1759 p
= iprod(r_ij
, r_kj
); /* 5 */
1760 p
*= nrkj_2
; /* 1 */
1761 q
= iprod(r_kl
, r_kj
); /* 5 */
1762 q
*= nrkj_2
; /* 1 */
1763 svmul(p
, f_i
, uvec
); /* 3 */
1764 svmul(q
, f_l
, vvec
); /* 3 */
1765 rvec_sub(uvec
, vvec
, svec
); /* 3 */
1766 rvec_sub(f_i
, svec
, f_j
); /* 3 */
1767 rvec_add(f_l
, svec
, f_k
); /* 3 */
1768 rvec_inc(f
[i
], f_i
); /* 3 */
1769 rvec_dec(f
[j
], f_j
); /* 3 */
1770 rvec_dec(f
[k
], f_k
); /* 3 */
1771 rvec_inc(f
[l
], f_l
); /* 3 */
1775 #if GMX_SIMD_HAVE_REAL
1776 /* As do_dih_fup_noshiftf above, but with SIMD and pre-calculated pre-factors */
1777 static gmx_inline
void gmx_simdcall
1778 do_dih_fup_noshiftf_simd(const int *ai
, const int *aj
, const int *ak
, const int *al
,
1779 SimdReal p
, SimdReal q
,
1780 SimdReal f_i_x
, SimdReal f_i_y
, SimdReal f_i_z
,
1781 SimdReal mf_l_x
, SimdReal mf_l_y
, SimdReal mf_l_z
,
1784 SimdReal sx
= p
* f_i_x
+ q
* mf_l_x
;
1785 SimdReal sy
= p
* f_i_y
+ q
* mf_l_y
;
1786 SimdReal sz
= p
* f_i_z
+ q
* mf_l_z
;
1787 SimdReal f_j_x
= f_i_x
- sx
;
1788 SimdReal f_j_y
= f_i_y
- sy
;
1789 SimdReal f_j_z
= f_i_z
- sz
;
1790 SimdReal f_k_x
= mf_l_x
- sx
;
1791 SimdReal f_k_y
= mf_l_y
- sy
;
1792 SimdReal f_k_z
= mf_l_z
- sz
;
1793 transposeScatterIncrU
<4>(reinterpret_cast<real
*>(f
), ai
, f_i_x
, f_i_y
, f_i_z
);
1794 transposeScatterDecrU
<4>(reinterpret_cast<real
*>(f
), aj
, f_j_x
, f_j_y
, f_j_z
);
1795 transposeScatterIncrU
<4>(reinterpret_cast<real
*>(f
), ak
, f_k_x
, f_k_y
, f_k_z
);
1796 transposeScatterDecrU
<4>(reinterpret_cast<real
*>(f
), al
, mf_l_x
, mf_l_y
, mf_l_z
);
1798 #endif // GMX_SIMD_HAVE_REAL
1800 static real
dopdihs(real cpA
, real cpB
, real phiA
, real phiB
, int mult
,
1801 real phi
, real lambda
, real
*V
, real
*F
)
1803 real v
, dvdlambda
, mdphi
, v1
, sdphi
, ddphi
;
1804 real L1
= 1.0 - lambda
;
1805 real ph0
= (L1
*phiA
+ lambda
*phiB
)*DEG2RAD
;
1806 real dph0
= (phiB
- phiA
)*DEG2RAD
;
1807 real cp
= L1
*cpA
+ lambda
*cpB
;
1809 mdphi
= mult
*phi
- ph0
;
1810 sdphi
= std::sin(mdphi
);
1811 ddphi
= -cp
*mult
*sdphi
;
1812 v1
= 1.0 + std::cos(mdphi
);
1815 dvdlambda
= (cpB
- cpA
)*v1
+ cp
*dph0
*sdphi
;
1822 /* That was 40 flops */
1826 dopdihs_noener(real cpA
, real cpB
, real phiA
, real phiB
, int mult
,
1827 real phi
, real lambda
, real
*F
)
1829 real mdphi
, sdphi
, ddphi
;
1830 real L1
= 1.0 - lambda
;
1831 real ph0
= (L1
*phiA
+ lambda
*phiB
)*DEG2RAD
;
1832 real cp
= L1
*cpA
+ lambda
*cpB
;
1834 mdphi
= mult
*phi
- ph0
;
1835 sdphi
= std::sin(mdphi
);
1836 ddphi
= -cp
*mult
*sdphi
;
1840 /* That was 20 flops */
1843 static real
dopdihs_min(real cpA
, real cpB
, real phiA
, real phiB
, int mult
,
1844 real phi
, real lambda
, real
*V
, real
*F
)
1845 /* similar to dopdihs, except for a minus sign *
1846 * and a different treatment of mult/phi0 */
1848 real v
, dvdlambda
, mdphi
, v1
, sdphi
, ddphi
;
1849 real L1
= 1.0 - lambda
;
1850 real ph0
= (L1
*phiA
+ lambda
*phiB
)*DEG2RAD
;
1851 real dph0
= (phiB
- phiA
)*DEG2RAD
;
1852 real cp
= L1
*cpA
+ lambda
*cpB
;
1854 mdphi
= mult
*(phi
-ph0
);
1855 sdphi
= std::sin(mdphi
);
1856 ddphi
= cp
*mult
*sdphi
;
1857 v1
= 1.0-std::cos(mdphi
);
1860 dvdlambda
= (cpB
-cpA
)*v1
+ cp
*dph0
*sdphi
;
1867 /* That was 40 flops */
1870 real
pdihs(int nbonds
,
1871 const t_iatom forceatoms
[], const t_iparams forceparams
[],
1872 const rvec x
[], rvec4 f
[], rvec fshift
[],
1873 const t_pbc
*pbc
, const t_graph
*g
,
1874 real lambda
, real
*dvdlambda
,
1875 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
1876 int gmx_unused
*global_atom_index
)
1878 int i
, type
, ai
, aj
, ak
, al
;
1880 rvec r_ij
, r_kj
, r_kl
, m
, n
;
1881 real phi
, ddphi
, vpd
, vtot
;
1885 for (i
= 0; (i
< nbonds
); )
1887 type
= forceatoms
[i
++];
1888 ai
= forceatoms
[i
++];
1889 aj
= forceatoms
[i
++];
1890 ak
= forceatoms
[i
++];
1891 al
= forceatoms
[i
++];
1893 phi
= dih_angle(x
[ai
], x
[aj
], x
[ak
], x
[al
], pbc
, r_ij
, r_kj
, r_kl
, m
, n
,
1894 &t1
, &t2
, &t3
); /* 84 */
1895 *dvdlambda
+= dopdihs(forceparams
[type
].pdihs
.cpA
,
1896 forceparams
[type
].pdihs
.cpB
,
1897 forceparams
[type
].pdihs
.phiA
,
1898 forceparams
[type
].pdihs
.phiB
,
1899 forceparams
[type
].pdihs
.mult
,
1900 phi
, lambda
, &vpd
, &ddphi
);
1903 do_dih_fup(ai
, aj
, ak
, al
, ddphi
, r_ij
, r_kj
, r_kl
, m
, n
,
1904 f
, fshift
, pbc
, g
, x
, t1
, t2
, t3
); /* 112 */
1907 fprintf(debug
, "pdih: (%d,%d,%d,%d) phi=%g\n",
1908 ai
, aj
, ak
, al
, phi
);
1915 void make_dp_periodic(real
*dp
) /* 1 flop? */
1917 /* dp cannot be outside (-pi,pi) */
1922 else if (*dp
< -M_PI
)
1929 /* As pdihs above, but without calculating energies and shift forces */
1931 pdihs_noener(int nbonds
,
1932 const t_iatom forceatoms
[], const t_iparams forceparams
[],
1933 const rvec x
[], rvec4 f
[],
1934 const t_pbc gmx_unused
*pbc
, const t_graph gmx_unused
*g
,
1936 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
1937 int gmx_unused
*global_atom_index
)
1939 int i
, type
, ai
, aj
, ak
, al
;
1941 rvec r_ij
, r_kj
, r_kl
, m
, n
;
1942 real phi
, ddphi_tot
, ddphi
;
1944 for (i
= 0; (i
< nbonds
); )
1946 ai
= forceatoms
[i
+1];
1947 aj
= forceatoms
[i
+2];
1948 ak
= forceatoms
[i
+3];
1949 al
= forceatoms
[i
+4];
1951 phi
= dih_angle(x
[ai
], x
[aj
], x
[ak
], x
[al
], pbc
, r_ij
, r_kj
, r_kl
, m
, n
,
1956 /* Loop over dihedrals working on the same atoms,
1957 * so we avoid recalculating angles and force distributions.
1961 type
= forceatoms
[i
];
1962 dopdihs_noener(forceparams
[type
].pdihs
.cpA
,
1963 forceparams
[type
].pdihs
.cpB
,
1964 forceparams
[type
].pdihs
.phiA
,
1965 forceparams
[type
].pdihs
.phiB
,
1966 forceparams
[type
].pdihs
.mult
,
1967 phi
, lambda
, &ddphi
);
1972 while (i
< nbonds
&&
1973 forceatoms
[i
+1] == ai
&&
1974 forceatoms
[i
+2] == aj
&&
1975 forceatoms
[i
+3] == ak
&&
1976 forceatoms
[i
+4] == al
);
1978 do_dih_fup_noshiftf(ai
, aj
, ak
, al
, ddphi_tot
, r_ij
, r_kj
, r_kl
, m
, n
, f
);
1983 #if GMX_SIMD_HAVE_REAL
1985 /* As pdihs_noner above, but using SIMD to calculate many dihedrals at once */
1987 pdihs_noener_simd(int nbonds
,
1988 const t_iatom forceatoms
[], const t_iparams forceparams
[],
1989 const rvec x
[], rvec4 f
[],
1990 const t_pbc
*pbc
, const t_graph gmx_unused
*g
,
1991 real gmx_unused lambda
,
1992 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
1993 int gmx_unused
*global_atom_index
)
1998 GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH
) ai
[GMX_SIMD_REAL_WIDTH
];
1999 GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH
) aj
[GMX_SIMD_REAL_WIDTH
];
2000 GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH
) ak
[GMX_SIMD_REAL_WIDTH
];
2001 GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH
) al
[GMX_SIMD_REAL_WIDTH
];
2002 GMX_ALIGNED(real
, GMX_SIMD_REAL_WIDTH
) buf
[3*GMX_SIMD_REAL_WIDTH
];
2003 real
*cp
, *phi0
, *mult
;
2004 SimdReal
deg2rad_S(DEG2RAD
);
2006 SimdReal phi0_S
, phi_S
;
2007 SimdReal mx_S
, my_S
, mz_S
;
2008 SimdReal nx_S
, ny_S
, nz_S
;
2009 SimdReal nrkj_m2_S
, nrkj_n2_S
;
2010 SimdReal cp_S
, mdphi_S
, mult_S
;
2011 SimdReal sin_S
, cos_S
;
2013 SimdReal sf_i_S
, msf_l_S
;
2014 GMX_ALIGNED(real
, GMX_SIMD_REAL_WIDTH
) pbc_simd
[9*GMX_SIMD_REAL_WIDTH
];
2016 /* Extract aligned pointer for parameters and variables */
2017 cp
= buf
+ 0*GMX_SIMD_REAL_WIDTH
;
2018 phi0
= buf
+ 1*GMX_SIMD_REAL_WIDTH
;
2019 mult
= buf
+ 2*GMX_SIMD_REAL_WIDTH
;
2021 set_pbc_simd(pbc
, pbc_simd
);
2023 /* nbonds is the number of dihedrals times nfa1, here we step GMX_SIMD_REAL_WIDTH dihs */
2024 for (i
= 0; (i
< nbonds
); i
+= GMX_SIMD_REAL_WIDTH
*nfa1
)
2026 /* Collect atoms quadruplets for GMX_SIMD_REAL_WIDTH dihedrals.
2027 * iu indexes into forceatoms, we should not let iu go beyond nbonds.
2030 for (s
= 0; s
< GMX_SIMD_REAL_WIDTH
; s
++)
2032 type
= forceatoms
[iu
];
2033 ai
[s
] = forceatoms
[iu
+1];
2034 aj
[s
] = forceatoms
[iu
+2];
2035 ak
[s
] = forceatoms
[iu
+3];
2036 al
[s
] = forceatoms
[iu
+4];
2038 /* At the end fill the arrays with the last atoms and 0 params */
2039 if (i
+ s
*nfa1
< nbonds
)
2041 cp
[s
] = forceparams
[type
].pdihs
.cpA
;
2042 phi0
[s
] = forceparams
[type
].pdihs
.phiA
;
2043 mult
[s
] = forceparams
[type
].pdihs
.mult
;
2045 if (iu
+ nfa1
< nbonds
)
2058 /* Caclulate GMX_SIMD_REAL_WIDTH dihedral angles at once */
2059 dih_angle_simd(x
, ai
, aj
, ak
, al
, pbc_simd
,
2061 &mx_S
, &my_S
, &mz_S
,
2062 &nx_S
, &ny_S
, &nz_S
,
2067 cp_S
= load
<SimdReal
>(cp
);
2068 phi0_S
= load
<SimdReal
>(phi0
) * deg2rad_S
;
2069 mult_S
= load
<SimdReal
>(mult
);
2071 mdphi_S
= fms(mult_S
, phi_S
, phi0_S
);
2073 /* Calculate GMX_SIMD_REAL_WIDTH sines at once */
2074 sincos(mdphi_S
, &sin_S
, &cos_S
);
2075 mddphi_S
= cp_S
* mult_S
* sin_S
;
2076 sf_i_S
= mddphi_S
* nrkj_m2_S
;
2077 msf_l_S
= mddphi_S
* nrkj_n2_S
;
2079 /* After this m?_S will contain f[i] */
2080 mx_S
= sf_i_S
* mx_S
;
2081 my_S
= sf_i_S
* my_S
;
2082 mz_S
= sf_i_S
* mz_S
;
2084 /* After this m?_S will contain -f[l] */
2085 nx_S
= msf_l_S
* nx_S
;
2086 ny_S
= msf_l_S
* ny_S
;
2087 nz_S
= msf_l_S
* nz_S
;
2089 do_dih_fup_noshiftf_simd(ai
, aj
, ak
, al
,
2097 /* This is mostly a copy of pdihs_noener_simd above, but with using
2098 * the RB potential instead of a harmonic potential.
2099 * This function can replace rbdihs() when no energy and virial are needed.
2102 rbdihs_noener_simd(int nbonds
,
2103 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2104 const rvec x
[], rvec4 f
[],
2105 const t_pbc
*pbc
, const t_graph gmx_unused
*g
,
2106 real gmx_unused lambda
,
2107 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2108 int gmx_unused
*global_atom_index
)
2113 GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH
) ai
[GMX_SIMD_REAL_WIDTH
];
2114 GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH
) aj
[GMX_SIMD_REAL_WIDTH
];
2115 GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH
) ak
[GMX_SIMD_REAL_WIDTH
];
2116 GMX_ALIGNED(int, GMX_SIMD_REAL_WIDTH
) al
[GMX_SIMD_REAL_WIDTH
];
2117 GMX_ALIGNED(real
, GMX_SIMD_REAL_WIDTH
) parm
[NR_RBDIHS
*GMX_SIMD_REAL_WIDTH
];
2121 SimdReal ddphi_S
, cosfac_S
;
2122 SimdReal mx_S
, my_S
, mz_S
;
2123 SimdReal nx_S
, ny_S
, nz_S
;
2124 SimdReal nrkj_m2_S
, nrkj_n2_S
;
2125 SimdReal parm_S
, c_S
;
2126 SimdReal sin_S
, cos_S
;
2127 SimdReal sf_i_S
, msf_l_S
;
2128 GMX_ALIGNED(real
, GMX_SIMD_REAL_WIDTH
) pbc_simd
[9*GMX_SIMD_REAL_WIDTH
];
2130 SimdReal
pi_S(M_PI
);
2131 SimdReal
one_S(1.0);
2133 set_pbc_simd(pbc
, pbc_simd
);
2135 /* nbonds is the number of dihedrals times nfa1, here we step GMX_SIMD_REAL_WIDTH dihs */
2136 for (i
= 0; (i
< nbonds
); i
+= GMX_SIMD_REAL_WIDTH
*nfa1
)
2138 /* Collect atoms quadruplets for GMX_SIMD_REAL_WIDTH dihedrals.
2139 * iu indexes into forceatoms, we should not let iu go beyond nbonds.
2142 for (s
= 0; s
< GMX_SIMD_REAL_WIDTH
; s
++)
2144 type
= forceatoms
[iu
];
2145 ai
[s
] = forceatoms
[iu
+1];
2146 aj
[s
] = forceatoms
[iu
+2];
2147 ak
[s
] = forceatoms
[iu
+3];
2148 al
[s
] = forceatoms
[iu
+4];
2150 /* At the end fill the arrays with the last atoms and 0 params */
2151 if (i
+ s
*nfa1
< nbonds
)
2153 /* We don't need the first parameter, since that's a constant
2154 * which only affects the energies, not the forces.
2156 for (j
= 1; j
< NR_RBDIHS
; j
++)
2158 parm
[j
*GMX_SIMD_REAL_WIDTH
+ s
] =
2159 forceparams
[type
].rbdihs
.rbcA
[j
];
2162 if (iu
+ nfa1
< nbonds
)
2169 for (j
= 1; j
< NR_RBDIHS
; j
++)
2171 parm
[j
*GMX_SIMD_REAL_WIDTH
+ s
] = 0;
2176 /* Caclulate GMX_SIMD_REAL_WIDTH dihedral angles at once */
2177 dih_angle_simd(x
, ai
, aj
, ak
, al
, pbc_simd
,
2179 &mx_S
, &my_S
, &mz_S
,
2180 &nx_S
, &ny_S
, &nz_S
,
2185 /* Change to polymer convention */
2186 phi_S
= phi_S
- pi_S
;
2188 sincos(phi_S
, &sin_S
, &cos_S
);
2190 ddphi_S
= setZero();
2193 for (j
= 1; j
< NR_RBDIHS
; j
++)
2195 parm_S
= load
<SimdReal
>(parm
+ j
*GMX_SIMD_REAL_WIDTH
);
2196 ddphi_S
= fma(c_S
* parm_S
, cosfac_S
, ddphi_S
);
2197 cosfac_S
= cosfac_S
* cos_S
;
2201 /* Note that here we do not use the minus sign which is present
2202 * in the normal RB code. This is corrected for through (m)sf below.
2204 ddphi_S
= ddphi_S
* sin_S
;
2206 sf_i_S
= ddphi_S
* nrkj_m2_S
;
2207 msf_l_S
= ddphi_S
* nrkj_n2_S
;
2209 /* After this m?_S will contain f[i] */
2210 mx_S
= sf_i_S
* mx_S
;
2211 my_S
= sf_i_S
* my_S
;
2212 mz_S
= sf_i_S
* mz_S
;
2214 /* After this m?_S will contain -f[l] */
2215 nx_S
= msf_l_S
* nx_S
;
2216 ny_S
= msf_l_S
* ny_S
;
2217 nz_S
= msf_l_S
* nz_S
;
2219 do_dih_fup_noshiftf_simd(ai
, aj
, ak
, al
,
2227 #endif // GMX_SIMD_HAVE_REAL
2230 real
idihs(int nbonds
,
2231 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2232 const rvec x
[], rvec4 f
[], rvec fshift
[],
2233 const t_pbc
*pbc
, const t_graph
*g
,
2234 real lambda
, real
*dvdlambda
,
2235 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2236 int gmx_unused
*global_atom_index
)
2238 int i
, type
, ai
, aj
, ak
, al
;
2240 real phi
, phi0
, dphi0
, ddphi
, vtot
;
2241 rvec r_ij
, r_kj
, r_kl
, m
, n
;
2242 real L1
, kk
, dp
, dp2
, kA
, kB
, pA
, pB
, dvdl_term
;
2247 for (i
= 0; (i
< nbonds
); )
2249 type
= forceatoms
[i
++];
2250 ai
= forceatoms
[i
++];
2251 aj
= forceatoms
[i
++];
2252 ak
= forceatoms
[i
++];
2253 al
= forceatoms
[i
++];
2255 phi
= dih_angle(x
[ai
], x
[aj
], x
[ak
], x
[al
], pbc
, r_ij
, r_kj
, r_kl
, m
, n
,
2256 &t1
, &t2
, &t3
); /* 84 */
2258 /* phi can jump if phi0 is close to Pi/-Pi, which will cause huge
2259 * force changes if we just apply a normal harmonic.
2260 * Instead, we first calculate phi-phi0 and take it modulo (-Pi,Pi).
2261 * This means we will never have the periodicity problem, unless
2262 * the dihedral is Pi away from phiO, which is very unlikely due to
2265 kA
= forceparams
[type
].harmonic
.krA
;
2266 kB
= forceparams
[type
].harmonic
.krB
;
2267 pA
= forceparams
[type
].harmonic
.rA
;
2268 pB
= forceparams
[type
].harmonic
.rB
;
2270 kk
= L1
*kA
+ lambda
*kB
;
2271 phi0
= (L1
*pA
+ lambda
*pB
)*DEG2RAD
;
2272 dphi0
= (pB
- pA
)*DEG2RAD
;
2276 make_dp_periodic(&dp
);
2283 dvdl_term
+= 0.5*(kB
- kA
)*dp2
- kk
*dphi0
*dp
;
2285 do_dih_fup(ai
, aj
, ak
, al
, -ddphi
, r_ij
, r_kj
, r_kl
, m
, n
,
2286 f
, fshift
, pbc
, g
, x
, t1
, t2
, t3
); /* 112 */
2291 fprintf(debug
, "idih: (%d,%d,%d,%d) phi=%g\n",
2292 ai
, aj
, ak
, al
, phi
);
2297 *dvdlambda
+= dvdl_term
;
2301 static real
low_angres(int nbonds
,
2302 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2303 const rvec x
[], rvec4 f
[], rvec fshift
[],
2304 const t_pbc
*pbc
, const t_graph
*g
,
2305 real lambda
, real
*dvdlambda
,
2308 int i
, m
, type
, ai
, aj
, ak
, al
;
2310 real phi
, cos_phi
, cos_phi2
, vid
, vtot
, dVdphi
;
2311 rvec r_ij
, r_kl
, f_i
, f_k
= {0, 0, 0};
2312 real st
, sth
, nrij2
, nrkl2
, c
, cij
, ckl
;
2315 t2
= 0; /* avoid warning with gcc-3.3. It is never used uninitialized */
2318 ak
= al
= 0; /* to avoid warnings */
2319 for (i
= 0; i
< nbonds
; )
2321 type
= forceatoms
[i
++];
2322 ai
= forceatoms
[i
++];
2323 aj
= forceatoms
[i
++];
2324 t1
= pbc_rvec_sub(pbc
, x
[aj
], x
[ai
], r_ij
); /* 3 */
2327 ak
= forceatoms
[i
++];
2328 al
= forceatoms
[i
++];
2329 t2
= pbc_rvec_sub(pbc
, x
[al
], x
[ak
], r_kl
); /* 3 */
2338 cos_phi
= cos_angle(r_ij
, r_kl
); /* 25 */
2339 phi
= std::acos(cos_phi
); /* 10 */
2341 *dvdlambda
+= dopdihs_min(forceparams
[type
].pdihs
.cpA
,
2342 forceparams
[type
].pdihs
.cpB
,
2343 forceparams
[type
].pdihs
.phiA
,
2344 forceparams
[type
].pdihs
.phiB
,
2345 forceparams
[type
].pdihs
.mult
,
2346 phi
, lambda
, &vid
, &dVdphi
); /* 40 */
2350 cos_phi2
= gmx::square(cos_phi
); /* 1 */
2353 st
= -dVdphi
*gmx::invsqrt(1 - cos_phi2
); /* 12 */
2354 sth
= st
*cos_phi
; /* 1 */
2355 nrij2
= iprod(r_ij
, r_ij
); /* 5 */
2356 nrkl2
= iprod(r_kl
, r_kl
); /* 5 */
2358 c
= st
*gmx::invsqrt(nrij2
*nrkl2
); /* 11 */
2359 cij
= sth
/nrij2
; /* 10 */
2360 ckl
= sth
/nrkl2
; /* 10 */
2362 for (m
= 0; m
< DIM
; m
++) /* 18+18 */
2364 f_i
[m
] = (c
*r_kl
[m
]-cij
*r_ij
[m
]);
2369 f_k
[m
] = (c
*r_ij
[m
]-ckl
*r_kl
[m
]);
2377 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, aj
), dt
);
2380 rvec_inc(fshift
[t1
], f_i
);
2381 rvec_dec(fshift
[CENTRAL
], f_i
);
2386 ivec_sub(SHIFT_IVEC(g
, ak
), SHIFT_IVEC(g
, al
), dt
);
2389 rvec_inc(fshift
[t2
], f_k
);
2390 rvec_dec(fshift
[CENTRAL
], f_k
);
2395 return vtot
; /* 184 / 157 (bZAxis) total */
2398 real
angres(int nbonds
,
2399 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2400 const rvec x
[], rvec4 f
[], rvec fshift
[],
2401 const t_pbc
*pbc
, const t_graph
*g
,
2402 real lambda
, real
*dvdlambda
,
2403 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2404 int gmx_unused
*global_atom_index
)
2406 return low_angres(nbonds
, forceatoms
, forceparams
, x
, f
, fshift
, pbc
, g
,
2407 lambda
, dvdlambda
, FALSE
);
2410 real
angresz(int nbonds
,
2411 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2412 const rvec x
[], rvec4 f
[], rvec fshift
[],
2413 const t_pbc
*pbc
, const t_graph
*g
,
2414 real lambda
, real
*dvdlambda
,
2415 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2416 int gmx_unused
*global_atom_index
)
2418 return low_angres(nbonds
, forceatoms
, forceparams
, x
, f
, fshift
, pbc
, g
,
2419 lambda
, dvdlambda
, TRUE
);
2422 real
dihres(int nbonds
,
2423 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2424 const rvec x
[], rvec4 f
[], rvec fshift
[],
2425 const t_pbc
*pbc
, const t_graph
*g
,
2426 real lambda
, real
*dvdlambda
,
2427 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2428 int gmx_unused
*global_atom_index
)
2431 int ai
, aj
, ak
, al
, i
, k
, type
, t1
, t2
, t3
;
2432 real phi0A
, phi0B
, dphiA
, dphiB
, kfacA
, kfacB
, phi0
, dphi
, kfac
;
2433 real phi
, ddphi
, ddp
, ddp2
, dp
, d2r
, L1
;
2434 rvec r_ij
, r_kj
, r_kl
, m
, n
;
2441 for (i
= 0; (i
< nbonds
); )
2443 type
= forceatoms
[i
++];
2444 ai
= forceatoms
[i
++];
2445 aj
= forceatoms
[i
++];
2446 ak
= forceatoms
[i
++];
2447 al
= forceatoms
[i
++];
2449 phi0A
= forceparams
[type
].dihres
.phiA
*d2r
;
2450 dphiA
= forceparams
[type
].dihres
.dphiA
*d2r
;
2451 kfacA
= forceparams
[type
].dihres
.kfacA
;
2453 phi0B
= forceparams
[type
].dihres
.phiB
*d2r
;
2454 dphiB
= forceparams
[type
].dihres
.dphiB
*d2r
;
2455 kfacB
= forceparams
[type
].dihres
.kfacB
;
2457 phi0
= L1
*phi0A
+ lambda
*phi0B
;
2458 dphi
= L1
*dphiA
+ lambda
*dphiB
;
2459 kfac
= L1
*kfacA
+ lambda
*kfacB
;
2461 phi
= dih_angle(x
[ai
], x
[aj
], x
[ak
], x
[al
], pbc
, r_ij
, r_kj
, r_kl
, m
, n
,
2467 fprintf(debug
, "dihres[%d]: %d %d %d %d : phi=%f, dphi=%f, kfac=%f\n",
2468 k
++, ai
, aj
, ak
, al
, phi0
, dphi
, kfac
);
2470 /* phi can jump if phi0 is close to Pi/-Pi, which will cause huge
2471 * force changes if we just apply a normal harmonic.
2472 * Instead, we first calculate phi-phi0 and take it modulo (-Pi,Pi).
2473 * This means we will never have the periodicity problem, unless
2474 * the dihedral is Pi away from phiO, which is very unlikely due to
2478 make_dp_periodic(&dp
);
2484 else if (dp
< -dphi
)
2496 vtot
+= 0.5*kfac
*ddp2
;
2499 *dvdlambda
+= 0.5*(kfacB
- kfacA
)*ddp2
;
2500 /* lambda dependence from changing restraint distances */
2503 *dvdlambda
-= kfac
*ddp
*((dphiB
- dphiA
)+(phi0B
- phi0A
));
2507 *dvdlambda
+= kfac
*ddp
*((dphiB
- dphiA
)-(phi0B
- phi0A
));
2509 do_dih_fup(ai
, aj
, ak
, al
, ddphi
, r_ij
, r_kj
, r_kl
, m
, n
,
2510 f
, fshift
, pbc
, g
, x
, t1
, t2
, t3
); /* 112 */
2517 real
unimplemented(int gmx_unused nbonds
,
2518 const t_iatom gmx_unused forceatoms
[], const t_iparams gmx_unused forceparams
[],
2519 const rvec gmx_unused x
[], rvec4 gmx_unused f
[], rvec gmx_unused fshift
[],
2520 const t_pbc gmx_unused
*pbc
, const t_graph gmx_unused
*g
,
2521 real gmx_unused lambda
, real gmx_unused
*dvdlambda
,
2522 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2523 int gmx_unused
*global_atom_index
)
2525 gmx_impl("*** you are using a not implemented function");
2527 return 0.0; /* To make the compiler happy */
2530 real
restrangles(int nbonds
,
2531 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2532 const rvec x
[], rvec4 f
[], rvec fshift
[],
2533 const t_pbc
*pbc
, const t_graph
*g
,
2534 real gmx_unused lambda
, real gmx_unused
*dvdlambda
,
2535 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2536 int gmx_unused
*global_atom_index
)
2538 int i
, d
, ai
, aj
, ak
, type
, m
;
2541 ivec jt
, dt_ij
, dt_kj
;
2543 real prefactor
, ratio_ante
, ratio_post
;
2544 rvec delta_ante
, delta_post
, vec_temp
;
2547 for (i
= 0; (i
< nbonds
); )
2549 type
= forceatoms
[i
++];
2550 ai
= forceatoms
[i
++];
2551 aj
= forceatoms
[i
++];
2552 ak
= forceatoms
[i
++];
2554 t1
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], vec_temp
);
2555 pbc_rvec_sub(pbc
, x
[aj
], x
[ai
], delta_ante
);
2556 t2
= pbc_rvec_sub(pbc
, x
[ak
], x
[aj
], delta_post
);
2559 /* This function computes factors needed for restricted angle potential.
2560 * The restricted angle potential is used in coarse-grained simulations to avoid singularities
2561 * when three particles align and the dihedral angle and dihedral potential
2562 * cannot be calculated. This potential is calculated using the formula:
2563 real restrangles(int nbonds,
2564 const t_iatom forceatoms[],const t_iparams forceparams[],
2565 const rvec x[],rvec4 f[],rvec fshift[],
2566 const t_pbc *pbc,const t_graph *g,
2567 real gmx_unused lambda,real gmx_unused *dvdlambda,
2568 const t_mdatoms gmx_unused *md,t_fcdata gmx_unused *fcd,
2569 int gmx_unused *global_atom_index)
2571 int i, d, ai, aj, ak, type, m;
2575 ivec jt,dt_ij,dt_kj;
2577 real prefactor, ratio_ante, ratio_post;
2578 rvec delta_ante, delta_post, vec_temp;
2581 for(i=0; (i<nbonds); )
2583 type = forceatoms[i++];
2584 ai = forceatoms[i++];
2585 aj = forceatoms[i++];
2586 ak = forceatoms[i++];
2588 * \f[V_{\rm ReB}(\theta_i) = \frac{1}{2} k_{\theta} \frac{(\cos\theta_i - \cos\theta_0)^2}
2589 * {\sin^2\theta_i}\f] ({eq:ReB} and ref \cite{MonicaGoga2013} from the manual).
2590 * For more explanations see comments file "restcbt.h". */
2592 compute_factors_restangles(type
, forceparams
, delta_ante
, delta_post
,
2593 &prefactor
, &ratio_ante
, &ratio_post
, &v
);
2595 /* Forces are computed per component */
2596 for (d
= 0; d
< DIM
; d
++)
2598 f_i
[d
] = prefactor
* (ratio_ante
* delta_ante
[d
] - delta_post
[d
]);
2599 f_j
[d
] = prefactor
* ((ratio_post
+ 1.0) * delta_post
[d
] - (ratio_ante
+ 1.0) * delta_ante
[d
]);
2600 f_k
[d
] = prefactor
* (delta_ante
[d
] - ratio_post
* delta_post
[d
]);
2603 /* Computation of potential energy */
2609 for (m
= 0; (m
< DIM
); m
++)
2618 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
2619 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
2620 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
2621 t1
= IVEC2IS(dt_ij
);
2622 t2
= IVEC2IS(dt_kj
);
2625 rvec_inc(fshift
[t1
], f_i
);
2626 rvec_inc(fshift
[CENTRAL
], f_j
);
2627 rvec_inc(fshift
[t2
], f_k
);
2633 real
restrdihs(int nbonds
,
2634 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2635 const rvec x
[], rvec4 f
[], rvec fshift
[],
2636 const t_pbc
*pbc
, const t_graph
*g
,
2637 real gmx_unused lambda
, real gmx_unused
*dvlambda
,
2638 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2639 int gmx_unused
*global_atom_index
)
2641 int i
, d
, type
, ai
, aj
, ak
, al
;
2642 rvec f_i
, f_j
, f_k
, f_l
;
2644 ivec jt
, dt_ij
, dt_kj
, dt_lj
;
2647 rvec delta_ante
, delta_crnt
, delta_post
, vec_temp
;
2648 real factor_phi_ai_ante
, factor_phi_ai_crnt
, factor_phi_ai_post
;
2649 real factor_phi_aj_ante
, factor_phi_aj_crnt
, factor_phi_aj_post
;
2650 real factor_phi_ak_ante
, factor_phi_ak_crnt
, factor_phi_ak_post
;
2651 real factor_phi_al_ante
, factor_phi_al_crnt
, factor_phi_al_post
;
2656 for (i
= 0; (i
< nbonds
); )
2658 type
= forceatoms
[i
++];
2659 ai
= forceatoms
[i
++];
2660 aj
= forceatoms
[i
++];
2661 ak
= forceatoms
[i
++];
2662 al
= forceatoms
[i
++];
2664 t1
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], vec_temp
);
2665 pbc_rvec_sub(pbc
, x
[aj
], x
[ai
], delta_ante
);
2666 t2
= pbc_rvec_sub(pbc
, x
[ak
], x
[aj
], delta_crnt
);
2667 pbc_rvec_sub(pbc
, x
[ak
], x
[al
], vec_temp
);
2668 pbc_rvec_sub(pbc
, x
[al
], x
[ak
], delta_post
);
2670 /* This function computes factors needed for restricted angle potential.
2671 * The restricted angle potential is used in coarse-grained simulations to avoid singularities
2672 * when three particles align and the dihedral angle and dihedral potential cannot be calculated.
2673 * This potential is calculated using the formula:
2674 * \f[V_{\rm ReB}(\theta_i) = \frac{1}{2} k_{\theta}
2675 * \frac{(\cos\theta_i - \cos\theta_0)^2}{\sin^2\theta_i}\f]
2676 * ({eq:ReB} and ref \cite{MonicaGoga2013} from the manual).
2677 * For more explanations see comments file "restcbt.h" */
2679 compute_factors_restrdihs(type
, forceparams
,
2680 delta_ante
, delta_crnt
, delta_post
,
2681 &factor_phi_ai_ante
, &factor_phi_ai_crnt
, &factor_phi_ai_post
,
2682 &factor_phi_aj_ante
, &factor_phi_aj_crnt
, &factor_phi_aj_post
,
2683 &factor_phi_ak_ante
, &factor_phi_ak_crnt
, &factor_phi_ak_post
,
2684 &factor_phi_al_ante
, &factor_phi_al_crnt
, &factor_phi_al_post
,
2685 &prefactor_phi
, &v
);
2688 /* Computation of forces per component */
2689 for (d
= 0; d
< DIM
; d
++)
2691 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
]);
2692 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
]);
2693 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
]);
2694 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
]);
2696 /* Computation of the energy */
2702 /* Updating the forces */
2704 rvec_inc(f
[ai
], f_i
);
2705 rvec_inc(f
[aj
], f_j
);
2706 rvec_inc(f
[ak
], f_k
);
2707 rvec_inc(f
[al
], f_l
);
2710 /* Updating the fshift forces for the pressure coupling */
2713 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
2714 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
2715 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
2716 ivec_sub(SHIFT_IVEC(g
, al
), jt
, dt_lj
);
2717 t1
= IVEC2IS(dt_ij
);
2718 t2
= IVEC2IS(dt_kj
);
2719 t3
= IVEC2IS(dt_lj
);
2723 t3
= pbc_rvec_sub(pbc
, x
[al
], x
[aj
], dx_jl
);
2730 rvec_inc(fshift
[t1
], f_i
);
2731 rvec_inc(fshift
[CENTRAL
], f_j
);
2732 rvec_inc(fshift
[t2
], f_k
);
2733 rvec_inc(fshift
[t3
], f_l
);
2741 real
cbtdihs(int nbonds
,
2742 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2743 const rvec x
[], rvec4 f
[], rvec fshift
[],
2744 const t_pbc
*pbc
, const t_graph
*g
,
2745 real gmx_unused lambda
, real gmx_unused
*dvdlambda
,
2746 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2747 int gmx_unused
*global_atom_index
)
2749 int type
, ai
, aj
, ak
, al
, i
, d
;
2753 rvec f_i
, f_j
, f_k
, f_l
;
2754 ivec jt
, dt_ij
, dt_kj
, dt_lj
;
2756 rvec delta_ante
, delta_crnt
, delta_post
;
2757 rvec f_phi_ai
, f_phi_aj
, f_phi_ak
, f_phi_al
;
2758 rvec f_theta_ante_ai
, f_theta_ante_aj
, f_theta_ante_ak
;
2759 rvec f_theta_post_aj
, f_theta_post_ak
, f_theta_post_al
;
2765 for (i
= 0; (i
< nbonds
); )
2767 type
= forceatoms
[i
++];
2768 ai
= forceatoms
[i
++];
2769 aj
= forceatoms
[i
++];
2770 ak
= forceatoms
[i
++];
2771 al
= forceatoms
[i
++];
2774 t1
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], vec_temp
);
2775 pbc_rvec_sub(pbc
, x
[aj
], x
[ai
], delta_ante
);
2776 t2
= pbc_rvec_sub(pbc
, x
[ak
], x
[aj
], vec_temp
);
2777 pbc_rvec_sub(pbc
, x
[ak
], x
[aj
], delta_crnt
);
2778 pbc_rvec_sub(pbc
, x
[ak
], x
[al
], vec_temp
);
2779 pbc_rvec_sub(pbc
, x
[al
], x
[ak
], delta_post
);
2781 /* \brief Compute factors for CBT potential
2782 * The combined bending-torsion potential goes to zero in a very smooth manner, eliminating the numerical
2783 * instabilities, when three coarse-grained particles align and the dihedral angle and standard
2784 * dihedral potentials cannot be calculated. The CBT potential is calculated using the formula:
2785 * \f[V_{\rm CBT}(\theta_{i-1}, \theta_i, \phi_i) = k_{\phi} \sin^3\theta_{i-1} \sin^3\theta_{i}
2786 * \sum_{n=0}^4 { a_n \cos^n\phi_i}\f] ({eq:CBT} and ref \cite{MonicaGoga2013} from the manual).
2787 * It contains in its expression not only the dihedral angle \f$\phi\f$
2788 * but also \f[\theta_{i-1}\f] (theta_ante bellow) and \f[\theta_{i}\f] (theta_post bellow)
2789 * --- the adjacent bending angles.
2790 * For more explanations see comments file "restcbt.h". */
2792 compute_factors_cbtdihs(type
, forceparams
, delta_ante
, delta_crnt
, delta_post
,
2793 f_phi_ai
, f_phi_aj
, f_phi_ak
, f_phi_al
,
2794 f_theta_ante_ai
, f_theta_ante_aj
, f_theta_ante_ak
,
2795 f_theta_post_aj
, f_theta_post_ak
, f_theta_post_al
,
2799 /* Acumulate the resuts per beads */
2800 for (d
= 0; d
< DIM
; d
++)
2802 f_i
[d
] = f_phi_ai
[d
] + f_theta_ante_ai
[d
];
2803 f_j
[d
] = f_phi_aj
[d
] + f_theta_ante_aj
[d
] + f_theta_post_aj
[d
];
2804 f_k
[d
] = f_phi_ak
[d
] + f_theta_ante_ak
[d
] + f_theta_post_ak
[d
];
2805 f_l
[d
] = f_phi_al
[d
] + f_theta_post_al
[d
];
2808 /* Compute the potential energy */
2813 /* Updating the forces */
2814 rvec_inc(f
[ai
], f_i
);
2815 rvec_inc(f
[aj
], f_j
);
2816 rvec_inc(f
[ak
], f_k
);
2817 rvec_inc(f
[al
], f_l
);
2820 /* Updating the fshift forces for the pressure coupling */
2823 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
2824 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
2825 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
2826 ivec_sub(SHIFT_IVEC(g
, al
), jt
, dt_lj
);
2827 t1
= IVEC2IS(dt_ij
);
2828 t2
= IVEC2IS(dt_kj
);
2829 t3
= IVEC2IS(dt_lj
);
2833 t3
= pbc_rvec_sub(pbc
, x
[al
], x
[aj
], dx_jl
);
2840 rvec_inc(fshift
[t1
], f_i
);
2841 rvec_inc(fshift
[CENTRAL
], f_j
);
2842 rvec_inc(fshift
[t2
], f_k
);
2843 rvec_inc(fshift
[t3
], f_l
);
2849 real
rbdihs(int nbonds
,
2850 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2851 const rvec x
[], rvec4 f
[], rvec fshift
[],
2852 const t_pbc
*pbc
, const t_graph
*g
,
2853 real lambda
, real
*dvdlambda
,
2854 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
2855 int gmx_unused
*global_atom_index
)
2857 const real c0
= 0.0, c1
= 1.0, c2
= 2.0, c3
= 3.0, c4
= 4.0, c5
= 5.0;
2858 int type
, ai
, aj
, ak
, al
, i
, j
;
2860 rvec r_ij
, r_kj
, r_kl
, m
, n
;
2861 real parmA
[NR_RBDIHS
];
2862 real parmB
[NR_RBDIHS
];
2863 real parm
[NR_RBDIHS
];
2864 real cos_phi
, phi
, rbp
, rbpBA
;
2865 real v
, ddphi
, sin_phi
;
2867 real L1
= 1.0-lambda
;
2871 for (i
= 0; (i
< nbonds
); )
2873 type
= forceatoms
[i
++];
2874 ai
= forceatoms
[i
++];
2875 aj
= forceatoms
[i
++];
2876 ak
= forceatoms
[i
++];
2877 al
= forceatoms
[i
++];
2879 phi
= dih_angle(x
[ai
], x
[aj
], x
[ak
], x
[al
], pbc
, r_ij
, r_kj
, r_kl
, m
, n
,
2880 &t1
, &t2
, &t3
); /* 84 */
2882 /* Change to polymer convention */
2889 phi
-= M_PI
; /* 1 */
2892 cos_phi
= std::cos(phi
);
2893 /* Beware of accuracy loss, cannot use 1-sqrt(cos^2) ! */
2894 sin_phi
= std::sin(phi
);
2896 for (j
= 0; (j
< NR_RBDIHS
); j
++)
2898 parmA
[j
] = forceparams
[type
].rbdihs
.rbcA
[j
];
2899 parmB
[j
] = forceparams
[type
].rbdihs
.rbcB
[j
];
2900 parm
[j
] = L1
*parmA
[j
]+lambda
*parmB
[j
];
2902 /* Calculate cosine powers */
2903 /* Calculate the energy */
2904 /* Calculate the derivative */
2907 dvdl_term
+= (parmB
[0]-parmA
[0]);
2912 rbpBA
= parmB
[1]-parmA
[1];
2913 ddphi
+= rbp
*cosfac
;
2916 dvdl_term
+= cosfac
*rbpBA
;
2918 rbpBA
= parmB
[2]-parmA
[2];
2919 ddphi
+= c2
*rbp
*cosfac
;
2922 dvdl_term
+= cosfac
*rbpBA
;
2924 rbpBA
= parmB
[3]-parmA
[3];
2925 ddphi
+= c3
*rbp
*cosfac
;
2928 dvdl_term
+= cosfac
*rbpBA
;
2930 rbpBA
= parmB
[4]-parmA
[4];
2931 ddphi
+= c4
*rbp
*cosfac
;
2934 dvdl_term
+= cosfac
*rbpBA
;
2936 rbpBA
= parmB
[5]-parmA
[5];
2937 ddphi
+= c5
*rbp
*cosfac
;
2940 dvdl_term
+= cosfac
*rbpBA
;
2942 ddphi
= -ddphi
*sin_phi
; /* 11 */
2944 do_dih_fup(ai
, aj
, ak
, al
, ddphi
, r_ij
, r_kj
, r_kl
, m
, n
,
2945 f
, fshift
, pbc
, g
, x
, t1
, t2
, t3
); /* 112 */
2948 *dvdlambda
+= dvdl_term
;
2955 /*! \brief Mysterious undocumented function */
2957 cmap_setup_grid_index(int ip
, int grid_spacing
, int *ipm1
, int *ipp1
, int *ipp2
)
2963 ip
= ip
+ grid_spacing
- 1;
2965 else if (ip
> grid_spacing
)
2967 ip
= ip
- grid_spacing
- 1;
2976 im1
= grid_spacing
- 1;
2978 else if (ip
== grid_spacing
-2)
2982 else if (ip
== grid_spacing
-1)
2997 cmap_dihs(int nbonds
,
2998 const t_iatom forceatoms
[], const t_iparams forceparams
[],
2999 const gmx_cmap_t
*cmap_grid
,
3000 const rvec x
[], rvec4 f
[], rvec fshift
[],
3001 const struct t_pbc
*pbc
, const struct t_graph
*g
,
3002 real gmx_unused lambda
, real gmx_unused
*dvdlambda
,
3003 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
3004 int gmx_unused
*global_atom_index
)
3007 int ai
, aj
, ak
, al
, am
;
3008 int a1i
, a1j
, a1k
, a1l
, a2i
, a2j
, a2k
, a2l
;
3010 int t11
, t21
, t31
, t12
, t22
, t32
;
3011 int iphi1
, ip1m1
, ip1p1
, ip1p2
;
3012 int iphi2
, ip2m1
, ip2p1
, ip2p2
;
3014 int pos1
, pos2
, pos3
, pos4
;
3016 real ty
[4], ty1
[4], ty2
[4], ty12
[4], tx
[16];
3017 real phi1
, cos_phi1
, sin_phi1
, xphi1
;
3018 real phi2
, cos_phi2
, sin_phi2
, xphi2
;
3019 real dx
, tt
, tu
, e
, df1
, df2
, vtot
;
3020 real ra21
, rb21
, rg21
, rg1
, rgr1
, ra2r1
, rb2r1
, rabr1
;
3021 real ra22
, rb22
, rg22
, rg2
, rgr2
, ra2r2
, rb2r2
, rabr2
;
3022 real fg1
, hg1
, fga1
, hgb1
, gaa1
, gbb1
;
3023 real fg2
, hg2
, fga2
, hgb2
, gaa2
, gbb2
;
3026 rvec r1_ij
, r1_kj
, r1_kl
, m1
, n1
;
3027 rvec r2_ij
, r2_kj
, r2_kl
, m2
, n2
;
3028 rvec f1_i
, f1_j
, f1_k
, f1_l
;
3029 rvec f2_i
, f2_j
, f2_k
, f2_l
;
3030 rvec a1
, b1
, a2
, b2
;
3031 rvec f1
, g1
, h1
, f2
, g2
, h2
;
3032 rvec dtf1
, dtg1
, dth1
, dtf2
, dtg2
, dth2
;
3033 ivec jt1
, dt1_ij
, dt1_kj
, dt1_lj
;
3034 ivec jt2
, dt2_ij
, dt2_kj
, dt2_lj
;
3038 int loop_index
[4][4] = {
3045 /* Total CMAP energy */
3048 for (n
= 0; n
< nbonds
; )
3050 /* Five atoms are involved in the two torsions */
3051 type
= forceatoms
[n
++];
3052 ai
= forceatoms
[n
++];
3053 aj
= forceatoms
[n
++];
3054 ak
= forceatoms
[n
++];
3055 al
= forceatoms
[n
++];
3056 am
= forceatoms
[n
++];
3058 /* Which CMAP type is this */
3059 cmapA
= forceparams
[type
].cmap
.cmapA
;
3060 cmapd
= cmap_grid
->cmapdata
[cmapA
].cmap
;
3068 phi1
= dih_angle(x
[a1i
], x
[a1j
], x
[a1k
], x
[a1l
], pbc
, r1_ij
, r1_kj
, r1_kl
, m1
, n1
,
3069 &t11
, &t21
, &t31
); /* 84 */
3071 cos_phi1
= std::cos(phi1
);
3073 a1
[0] = r1_ij
[1]*r1_kj
[2]-r1_ij
[2]*r1_kj
[1];
3074 a1
[1] = r1_ij
[2]*r1_kj
[0]-r1_ij
[0]*r1_kj
[2];
3075 a1
[2] = r1_ij
[0]*r1_kj
[1]-r1_ij
[1]*r1_kj
[0]; /* 9 */
3077 b1
[0] = r1_kl
[1]*r1_kj
[2]-r1_kl
[2]*r1_kj
[1];
3078 b1
[1] = r1_kl
[2]*r1_kj
[0]-r1_kl
[0]*r1_kj
[2];
3079 b1
[2] = r1_kl
[0]*r1_kj
[1]-r1_kl
[1]*r1_kj
[0]; /* 9 */
3081 pbc_rvec_sub(pbc
, x
[a1l
], x
[a1k
], h1
);
3083 ra21
= iprod(a1
, a1
); /* 5 */
3084 rb21
= iprod(b1
, b1
); /* 5 */
3085 rg21
= iprod(r1_kj
, r1_kj
); /* 5 */
3091 rabr1
= sqrt(ra2r1
*rb2r1
);
3093 sin_phi1
= rg1
* rabr1
* iprod(a1
, h1
) * (-1);
3095 if (cos_phi1
< -0.5 || cos_phi1
> 0.5)
3097 phi1
= std::asin(sin_phi1
);
3107 phi1
= -M_PI
- phi1
;
3113 phi1
= std::acos(cos_phi1
);
3121 xphi1
= phi1
+ M_PI
; /* 1 */
3123 /* Second torsion */
3129 phi2
= dih_angle(x
[a2i
], x
[a2j
], x
[a2k
], x
[a2l
], pbc
, r2_ij
, r2_kj
, r2_kl
, m2
, n2
,
3130 &t12
, &t22
, &t32
); /* 84 */
3132 cos_phi2
= std::cos(phi2
);
3134 a2
[0] = r2_ij
[1]*r2_kj
[2]-r2_ij
[2]*r2_kj
[1];
3135 a2
[1] = r2_ij
[2]*r2_kj
[0]-r2_ij
[0]*r2_kj
[2];
3136 a2
[2] = r2_ij
[0]*r2_kj
[1]-r2_ij
[1]*r2_kj
[0]; /* 9 */
3138 b2
[0] = r2_kl
[1]*r2_kj
[2]-r2_kl
[2]*r2_kj
[1];
3139 b2
[1] = r2_kl
[2]*r2_kj
[0]-r2_kl
[0]*r2_kj
[2];
3140 b2
[2] = r2_kl
[0]*r2_kj
[1]-r2_kl
[1]*r2_kj
[0]; /* 9 */
3142 pbc_rvec_sub(pbc
, x
[a2l
], x
[a2k
], h2
);
3144 ra22
= iprod(a2
, a2
); /* 5 */
3145 rb22
= iprod(b2
, b2
); /* 5 */
3146 rg22
= iprod(r2_kj
, r2_kj
); /* 5 */
3152 rabr2
= sqrt(ra2r2
*rb2r2
);
3154 sin_phi2
= rg2
* rabr2
* iprod(a2
, h2
) * (-1);
3156 if (cos_phi2
< -0.5 || cos_phi2
> 0.5)
3158 phi2
= std::asin(sin_phi2
);
3168 phi2
= -M_PI
- phi2
;
3174 phi2
= std::acos(cos_phi2
);
3182 xphi2
= phi2
+ M_PI
; /* 1 */
3184 /* Range mangling */
3187 xphi1
= xphi1
+ 2*M_PI
;
3189 else if (xphi1
>= 2*M_PI
)
3191 xphi1
= xphi1
- 2*M_PI
;
3196 xphi2
= xphi2
+ 2*M_PI
;
3198 else if (xphi2
>= 2*M_PI
)
3200 xphi2
= xphi2
- 2*M_PI
;
3203 /* Number of grid points */
3204 dx
= 2*M_PI
/ cmap_grid
->grid_spacing
;
3206 /* Where on the grid are we */
3207 iphi1
= static_cast<int>(xphi1
/dx
);
3208 iphi2
= static_cast<int>(xphi2
/dx
);
3210 iphi1
= cmap_setup_grid_index(iphi1
, cmap_grid
->grid_spacing
, &ip1m1
, &ip1p1
, &ip1p2
);
3211 iphi2
= cmap_setup_grid_index(iphi2
, cmap_grid
->grid_spacing
, &ip2m1
, &ip2p1
, &ip2p2
);
3213 pos1
= iphi1
*cmap_grid
->grid_spacing
+iphi2
;
3214 pos2
= ip1p1
*cmap_grid
->grid_spacing
+iphi2
;
3215 pos3
= ip1p1
*cmap_grid
->grid_spacing
+ip2p1
;
3216 pos4
= iphi1
*cmap_grid
->grid_spacing
+ip2p1
;
3218 ty
[0] = cmapd
[pos1
*4];
3219 ty
[1] = cmapd
[pos2
*4];
3220 ty
[2] = cmapd
[pos3
*4];
3221 ty
[3] = cmapd
[pos4
*4];
3223 ty1
[0] = cmapd
[pos1
*4+1];
3224 ty1
[1] = cmapd
[pos2
*4+1];
3225 ty1
[2] = cmapd
[pos3
*4+1];
3226 ty1
[3] = cmapd
[pos4
*4+1];
3228 ty2
[0] = cmapd
[pos1
*4+2];
3229 ty2
[1] = cmapd
[pos2
*4+2];
3230 ty2
[2] = cmapd
[pos3
*4+2];
3231 ty2
[3] = cmapd
[pos4
*4+2];
3233 ty12
[0] = cmapd
[pos1
*4+3];
3234 ty12
[1] = cmapd
[pos2
*4+3];
3235 ty12
[2] = cmapd
[pos3
*4+3];
3236 ty12
[3] = cmapd
[pos4
*4+3];
3238 /* Switch to degrees */
3239 dx
= 360.0 / cmap_grid
->grid_spacing
;
3240 xphi1
= xphi1
* RAD2DEG
;
3241 xphi2
= xphi2
* RAD2DEG
;
3243 for (i
= 0; i
< 4; i
++) /* 16 */
3246 tx
[i
+4] = ty1
[i
]*dx
;
3247 tx
[i
+8] = ty2
[i
]*dx
;
3248 tx
[i
+12] = ty12
[i
]*dx
*dx
;
3252 for (int idx
= 0; idx
< 16; idx
++) /* 1056 */
3254 for (int k
= 0; k
< 16; k
++)
3256 tc
[idx
] += cmap_coeff_matrix
[k
*16+idx
]*tx
[k
];
3260 tt
= (xphi1
-iphi1
*dx
)/dx
;
3261 tu
= (xphi2
-iphi2
*dx
)/dx
;
3267 for (i
= 3; i
>= 0; i
--)
3269 l1
= loop_index
[i
][3];
3270 l2
= loop_index
[i
][2];
3271 l3
= loop_index
[i
][1];
3273 e
= tt
* e
+ ((tc
[i
*4+3]*tu
+tc
[i
*4+2])*tu
+ tc
[i
*4+1])*tu
+tc
[i
*4];
3274 df1
= tu
* df1
+ (3.0*tc
[l1
]*tt
+2.0*tc
[l2
])*tt
+tc
[l3
];
3275 df2
= tt
* df2
+ (3.0*tc
[i
*4+3]*tu
+2.0*tc
[i
*4+2])*tu
+tc
[i
*4+1];
3285 /* Do forces - first torsion */
3286 fg1
= iprod(r1_ij
, r1_kj
);
3287 hg1
= iprod(r1_kl
, r1_kj
);
3288 fga1
= fg1
*ra2r1
*rgr1
;
3289 hgb1
= hg1
*rb2r1
*rgr1
;
3293 for (i
= 0; i
< DIM
; i
++)
3295 dtf1
[i
] = gaa1
* a1
[i
];
3296 dtg1
[i
] = fga1
* a1
[i
] - hgb1
* b1
[i
];
3297 dth1
[i
] = gbb1
* b1
[i
];
3299 f1
[i
] = df1
* dtf1
[i
];
3300 g1
[i
] = df1
* dtg1
[i
];
3301 h1
[i
] = df1
* dth1
[i
];
3304 f1_j
[i
] = -f1
[i
] - g1
[i
];
3305 f1_k
[i
] = h1
[i
] + g1
[i
];
3308 f
[a1i
][i
] = f
[a1i
][i
] + f1_i
[i
];
3309 f
[a1j
][i
] = f
[a1j
][i
] + f1_j
[i
]; /* - f1[i] - g1[i] */
3310 f
[a1k
][i
] = f
[a1k
][i
] + f1_k
[i
]; /* h1[i] + g1[i] */
3311 f
[a1l
][i
] = f
[a1l
][i
] + f1_l
[i
]; /* h1[i] */
3314 /* Do forces - second torsion */
3315 fg2
= iprod(r2_ij
, r2_kj
);
3316 hg2
= iprod(r2_kl
, r2_kj
);
3317 fga2
= fg2
*ra2r2
*rgr2
;
3318 hgb2
= hg2
*rb2r2
*rgr2
;
3322 for (i
= 0; i
< DIM
; i
++)
3324 dtf2
[i
] = gaa2
* a2
[i
];
3325 dtg2
[i
] = fga2
* a2
[i
] - hgb2
* b2
[i
];
3326 dth2
[i
] = gbb2
* b2
[i
];
3328 f2
[i
] = df2
* dtf2
[i
];
3329 g2
[i
] = df2
* dtg2
[i
];
3330 h2
[i
] = df2
* dth2
[i
];
3333 f2_j
[i
] = -f2
[i
] - g2
[i
];
3334 f2_k
[i
] = h2
[i
] + g2
[i
];
3337 f
[a2i
][i
] = f
[a2i
][i
] + f2_i
[i
]; /* f2[i] */
3338 f
[a2j
][i
] = f
[a2j
][i
] + f2_j
[i
]; /* - f2[i] - g2[i] */
3339 f
[a2k
][i
] = f
[a2k
][i
] + f2_k
[i
]; /* h2[i] + g2[i] */
3340 f
[a2l
][i
] = f
[a2l
][i
] + f2_l
[i
]; /* - h2[i] */
3346 copy_ivec(SHIFT_IVEC(g
, a1j
), jt1
);
3347 ivec_sub(SHIFT_IVEC(g
, a1i
), jt1
, dt1_ij
);
3348 ivec_sub(SHIFT_IVEC(g
, a1k
), jt1
, dt1_kj
);
3349 ivec_sub(SHIFT_IVEC(g
, a1l
), jt1
, dt1_lj
);
3350 t11
= IVEC2IS(dt1_ij
);
3351 t21
= IVEC2IS(dt1_kj
);
3352 t31
= IVEC2IS(dt1_lj
);
3354 copy_ivec(SHIFT_IVEC(g
, a2j
), jt2
);
3355 ivec_sub(SHIFT_IVEC(g
, a2i
), jt2
, dt2_ij
);
3356 ivec_sub(SHIFT_IVEC(g
, a2k
), jt2
, dt2_kj
);
3357 ivec_sub(SHIFT_IVEC(g
, a2l
), jt2
, dt2_lj
);
3358 t12
= IVEC2IS(dt2_ij
);
3359 t22
= IVEC2IS(dt2_kj
);
3360 t32
= IVEC2IS(dt2_lj
);
3364 t31
= pbc_rvec_sub(pbc
, x
[a1l
], x
[a1j
], h1
);
3365 t32
= pbc_rvec_sub(pbc
, x
[a2l
], x
[a2j
], h2
);
3373 rvec_inc(fshift
[t11
], f1_i
);
3374 rvec_inc(fshift
[CENTRAL
], f1_j
);
3375 rvec_inc(fshift
[t21
], f1_k
);
3376 rvec_inc(fshift
[t31
], f1_l
);
3378 rvec_inc(fshift
[t21
], f2_i
);
3379 rvec_inc(fshift
[CENTRAL
], f2_j
);
3380 rvec_inc(fshift
[t22
], f2_k
);
3381 rvec_inc(fshift
[t32
], f2_l
);
3388 /***********************************************************
3390 * G R O M O S 9 6 F U N C T I O N S
3392 ***********************************************************/
3393 static real
g96harmonic(real kA
, real kB
, real xA
, real xB
, real x
, real lambda
,
3396 const real half
= 0.5;
3397 real L1
, kk
, x0
, dx
, dx2
;
3398 real v
, f
, dvdlambda
;
3401 kk
= L1
*kA
+lambda
*kB
;
3402 x0
= L1
*xA
+lambda
*xB
;
3409 dvdlambda
= half
*(kB
-kA
)*dx2
+ (xA
-xB
)*kk
*dx
;
3416 /* That was 21 flops */
3419 real
g96bonds(int nbonds
,
3420 const t_iatom forceatoms
[], const t_iparams forceparams
[],
3421 const rvec x
[], rvec4 f
[], rvec fshift
[],
3422 const t_pbc
*pbc
, const t_graph
*g
,
3423 real lambda
, real
*dvdlambda
,
3424 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
3425 int gmx_unused
*global_atom_index
)
3427 int i
, m
, ki
, ai
, aj
, type
;
3428 real dr2
, fbond
, vbond
, fij
, vtot
;
3433 for (i
= 0; (i
< nbonds
); )
3435 type
= forceatoms
[i
++];
3436 ai
= forceatoms
[i
++];
3437 aj
= forceatoms
[i
++];
3439 ki
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], dx
); /* 3 */
3440 dr2
= iprod(dx
, dx
); /* 5 */
3442 *dvdlambda
+= g96harmonic(forceparams
[type
].harmonic
.krA
,
3443 forceparams
[type
].harmonic
.krB
,
3444 forceparams
[type
].harmonic
.rA
,
3445 forceparams
[type
].harmonic
.rB
,
3446 dr2
, lambda
, &vbond
, &fbond
);
3448 vtot
+= 0.5*vbond
; /* 1*/
3452 fprintf(debug
, "G96-BONDS: dr = %10g vbond = %10g fbond = %10g\n",
3453 sqrt(dr2
), vbond
, fbond
);
3459 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, aj
), dt
);
3462 for (m
= 0; (m
< DIM
); m
++) /* 15 */
3467 fshift
[ki
][m
] += fij
;
3468 fshift
[CENTRAL
][m
] -= fij
;
3474 static real
g96bond_angle(const rvec xi
, const rvec xj
, const rvec xk
, const t_pbc
*pbc
,
3475 rvec r_ij
, rvec r_kj
,
3477 /* Return value is the angle between the bonds i-j and j-k */
3481 *t1
= pbc_rvec_sub(pbc
, xi
, xj
, r_ij
); /* 3 */
3482 *t2
= pbc_rvec_sub(pbc
, xk
, xj
, r_kj
); /* 3 */
3484 costh
= cos_angle(r_ij
, r_kj
); /* 25 */
3489 real
g96angles(int nbonds
,
3490 const t_iatom forceatoms
[], const t_iparams forceparams
[],
3491 const rvec x
[], rvec4 f
[], rvec fshift
[],
3492 const t_pbc
*pbc
, const t_graph
*g
,
3493 real lambda
, real
*dvdlambda
,
3494 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
3495 int gmx_unused
*global_atom_index
)
3497 int i
, ai
, aj
, ak
, type
, m
, t1
, t2
;
3499 real cos_theta
, dVdt
, va
, vtot
;
3500 real rij_1
, rij_2
, rkj_1
, rkj_2
, rijrkj_1
;
3502 ivec jt
, dt_ij
, dt_kj
;
3505 for (i
= 0; (i
< nbonds
); )
3507 type
= forceatoms
[i
++];
3508 ai
= forceatoms
[i
++];
3509 aj
= forceatoms
[i
++];
3510 ak
= forceatoms
[i
++];
3512 cos_theta
= g96bond_angle(x
[ai
], x
[aj
], x
[ak
], pbc
, r_ij
, r_kj
, &t1
, &t2
);
3514 *dvdlambda
+= g96harmonic(forceparams
[type
].harmonic
.krA
,
3515 forceparams
[type
].harmonic
.krB
,
3516 forceparams
[type
].harmonic
.rA
,
3517 forceparams
[type
].harmonic
.rB
,
3518 cos_theta
, lambda
, &va
, &dVdt
);
3521 rij_1
= gmx::invsqrt(iprod(r_ij
, r_ij
));
3522 rkj_1
= gmx::invsqrt(iprod(r_kj
, r_kj
));
3523 rij_2
= rij_1
*rij_1
;
3524 rkj_2
= rkj_1
*rkj_1
;
3525 rijrkj_1
= rij_1
*rkj_1
; /* 23 */
3530 fprintf(debug
, "G96ANGLES: costheta = %10g vth = %10g dV/dct = %10g\n",
3531 cos_theta
, va
, dVdt
);
3534 for (m
= 0; (m
< DIM
); m
++) /* 42 */
3536 f_i
[m
] = dVdt
*(r_kj
[m
]*rijrkj_1
- r_ij
[m
]*rij_2
*cos_theta
);
3537 f_k
[m
] = dVdt
*(r_ij
[m
]*rijrkj_1
- r_kj
[m
]*rkj_2
*cos_theta
);
3538 f_j
[m
] = -f_i
[m
]-f_k
[m
];
3546 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
3548 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
3549 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
3550 t1
= IVEC2IS(dt_ij
);
3551 t2
= IVEC2IS(dt_kj
);
3553 rvec_inc(fshift
[t1
], f_i
);
3554 rvec_inc(fshift
[CENTRAL
], f_j
);
3555 rvec_inc(fshift
[t2
], f_k
); /* 9 */
3561 real
cross_bond_bond(int nbonds
,
3562 const t_iatom forceatoms
[], const t_iparams forceparams
[],
3563 const rvec x
[], rvec4 f
[], rvec fshift
[],
3564 const t_pbc
*pbc
, const t_graph
*g
,
3565 real gmx_unused lambda
, real gmx_unused
*dvdlambda
,
3566 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
3567 int gmx_unused
*global_atom_index
)
3569 /* Potential from Lawrence and Skimmer, Chem. Phys. Lett. 372 (2003)
3572 int i
, ai
, aj
, ak
, type
, m
, t1
, t2
;
3574 real vtot
, vrr
, s1
, s2
, r1
, r2
, r1e
, r2e
, krr
;
3576 ivec jt
, dt_ij
, dt_kj
;
3579 for (i
= 0; (i
< nbonds
); )
3581 type
= forceatoms
[i
++];
3582 ai
= forceatoms
[i
++];
3583 aj
= forceatoms
[i
++];
3584 ak
= forceatoms
[i
++];
3585 r1e
= forceparams
[type
].cross_bb
.r1e
;
3586 r2e
= forceparams
[type
].cross_bb
.r2e
;
3587 krr
= forceparams
[type
].cross_bb
.krr
;
3589 /* Compute distance vectors ... */
3590 t1
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], r_ij
);
3591 t2
= pbc_rvec_sub(pbc
, x
[ak
], x
[aj
], r_kj
);
3593 /* ... and their lengths */
3597 /* Deviations from ideality */
3601 /* Energy (can be negative!) */
3606 svmul(-krr
*s2
/r1
, r_ij
, f_i
);
3607 svmul(-krr
*s1
/r2
, r_kj
, f_k
);
3609 for (m
= 0; (m
< DIM
); m
++) /* 12 */
3611 f_j
[m
] = -f_i
[m
] - f_k
[m
];
3620 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
3622 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
3623 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
3624 t1
= IVEC2IS(dt_ij
);
3625 t2
= IVEC2IS(dt_kj
);
3627 rvec_inc(fshift
[t1
], f_i
);
3628 rvec_inc(fshift
[CENTRAL
], f_j
);
3629 rvec_inc(fshift
[t2
], f_k
); /* 9 */
3635 real
cross_bond_angle(int nbonds
,
3636 const t_iatom forceatoms
[], const t_iparams forceparams
[],
3637 const rvec x
[], rvec4 f
[], rvec fshift
[],
3638 const t_pbc
*pbc
, const t_graph
*g
,
3639 real gmx_unused lambda
, real gmx_unused
*dvdlambda
,
3640 const t_mdatoms gmx_unused
*md
, t_fcdata gmx_unused
*fcd
,
3641 int gmx_unused
*global_atom_index
)
3643 /* Potential from Lawrence and Skimmer, Chem. Phys. Lett. 372 (2003)
3646 int i
, ai
, aj
, ak
, type
, m
, t1
, t2
;
3647 rvec r_ij
, r_kj
, r_ik
;
3648 real vtot
, vrt
, s1
, s2
, s3
, r1
, r2
, r3
, r1e
, r2e
, r3e
, krt
, k1
, k2
, k3
;
3650 ivec jt
, dt_ij
, dt_kj
;
3653 for (i
= 0; (i
< nbonds
); )
3655 type
= forceatoms
[i
++];
3656 ai
= forceatoms
[i
++];
3657 aj
= forceatoms
[i
++];
3658 ak
= forceatoms
[i
++];
3659 r1e
= forceparams
[type
].cross_ba
.r1e
;
3660 r2e
= forceparams
[type
].cross_ba
.r2e
;
3661 r3e
= forceparams
[type
].cross_ba
.r3e
;
3662 krt
= forceparams
[type
].cross_ba
.krt
;
3664 /* Compute distance vectors ... */
3665 t1
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], r_ij
);
3666 t2
= pbc_rvec_sub(pbc
, x
[ak
], x
[aj
], r_kj
);
3667 pbc_rvec_sub(pbc
, x
[ai
], x
[ak
], r_ik
);
3669 /* ... and their lengths */
3674 /* Deviations from ideality */
3679 /* Energy (can be negative!) */
3680 vrt
= krt
*s3
*(s1
+s2
);
3686 k3
= -krt
*(s1
+s2
)/r3
;
3687 for (m
= 0; (m
< DIM
); m
++)
3689 f_i
[m
] = k1
*r_ij
[m
] + k3
*r_ik
[m
];
3690 f_k
[m
] = k2
*r_kj
[m
] - k3
*r_ik
[m
];
3691 f_j
[m
] = -f_i
[m
] - f_k
[m
];
3694 for (m
= 0; (m
< DIM
); m
++) /* 12 */
3704 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
3706 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
3707 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
3708 t1
= IVEC2IS(dt_ij
);
3709 t2
= IVEC2IS(dt_kj
);
3711 rvec_inc(fshift
[t1
], f_i
);
3712 rvec_inc(fshift
[CENTRAL
], f_j
);
3713 rvec_inc(fshift
[t2
], f_k
); /* 9 */
3719 static real
bonded_tab(const char *type
, int table_nr
,
3720 const bondedtable_t
*table
, real kA
, real kB
, real r
,
3721 real lambda
, real
*V
, real
*F
)
3723 real k
, tabscale
, *VFtab
, rt
, eps
, eps2
, Yt
, Ft
, Geps
, Heps2
, Fp
, VV
, FF
;
3727 k
= (1.0 - lambda
)*kA
+ lambda
*kB
;
3729 tabscale
= table
->scale
;
3730 VFtab
= table
->data
;
3733 n0
= static_cast<int>(rt
);
3736 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",
3737 type
, table_nr
, r
, n0
, n0
+1, table
->n
);
3744 Geps
= VFtab
[nnn
+2]*eps
;
3745 Heps2
= VFtab
[nnn
+3]*eps2
;
3746 Fp
= Ft
+ Geps
+ Heps2
;
3748 FF
= Fp
+ Geps
+ 2.0*Heps2
;
3750 *F
= -k
*FF
*tabscale
;
3752 dvdlambda
= (kB
- kA
)*VV
;
3756 /* That was 22 flops */
3759 real
tab_bonds(int nbonds
,
3760 const t_iatom forceatoms
[], const t_iparams forceparams
[],
3761 const rvec x
[], rvec4 f
[], rvec fshift
[],
3762 const t_pbc
*pbc
, const t_graph
*g
,
3763 real lambda
, real
*dvdlambda
,
3764 const t_mdatoms gmx_unused
*md
, t_fcdata
*fcd
,
3765 int gmx_unused
*global_atom_index
)
3767 int i
, m
, ki
, ai
, aj
, type
, table
;
3768 real dr
, dr2
, fbond
, vbond
, fij
, vtot
;
3773 for (i
= 0; (i
< nbonds
); )
3775 type
= forceatoms
[i
++];
3776 ai
= forceatoms
[i
++];
3777 aj
= forceatoms
[i
++];
3779 ki
= pbc_rvec_sub(pbc
, x
[ai
], x
[aj
], dx
); /* 3 */
3780 dr2
= iprod(dx
, dx
); /* 5 */
3781 dr
= dr2
*gmx::invsqrt(dr2
); /* 10 */
3783 table
= forceparams
[type
].tab
.table
;
3785 *dvdlambda
+= bonded_tab("bond", table
,
3786 &fcd
->bondtab
[table
],
3787 forceparams
[type
].tab
.kA
,
3788 forceparams
[type
].tab
.kB
,
3789 dr
, lambda
, &vbond
, &fbond
); /* 22 */
3797 vtot
+= vbond
; /* 1*/
3798 fbond
*= gmx::invsqrt(dr2
); /* 6 */
3802 fprintf(debug
, "TABBONDS: dr = %10g vbond = %10g fbond = %10g\n",
3808 ivec_sub(SHIFT_IVEC(g
, ai
), SHIFT_IVEC(g
, aj
), dt
);
3811 for (m
= 0; (m
< DIM
); m
++) /* 15 */
3816 fshift
[ki
][m
] += fij
;
3817 fshift
[CENTRAL
][m
] -= fij
;
3823 real
tab_angles(int nbonds
,
3824 const t_iatom forceatoms
[], const t_iparams forceparams
[],
3825 const rvec x
[], rvec4 f
[], rvec fshift
[],
3826 const t_pbc
*pbc
, const t_graph
*g
,
3827 real lambda
, real
*dvdlambda
,
3828 const t_mdatoms gmx_unused
*md
, t_fcdata
*fcd
,
3829 int gmx_unused
*global_atom_index
)
3831 int i
, ai
, aj
, ak
, t1
, t2
, type
, table
;
3833 real cos_theta
, cos_theta2
, theta
, dVdt
, va
, vtot
;
3834 ivec jt
, dt_ij
, dt_kj
;
3837 for (i
= 0; (i
< nbonds
); )
3839 type
= forceatoms
[i
++];
3840 ai
= forceatoms
[i
++];
3841 aj
= forceatoms
[i
++];
3842 ak
= forceatoms
[i
++];
3844 theta
= bond_angle(x
[ai
], x
[aj
], x
[ak
], pbc
,
3845 r_ij
, r_kj
, &cos_theta
, &t1
, &t2
); /* 41 */
3847 table
= forceparams
[type
].tab
.table
;
3849 *dvdlambda
+= bonded_tab("angle", table
,
3850 &fcd
->angletab
[table
],
3851 forceparams
[type
].tab
.kA
,
3852 forceparams
[type
].tab
.kB
,
3853 theta
, lambda
, &va
, &dVdt
); /* 22 */
3856 cos_theta2
= gmx::square(cos_theta
); /* 1 */
3865 st
= dVdt
*gmx::invsqrt(1 - cos_theta2
); /* 12 */
3866 sth
= st
*cos_theta
; /* 1 */
3870 fprintf(debug
, "ANGLES: theta = %10g vth = %10g dV/dtheta = %10g\n",
3871 theta
*RAD2DEG
, va
, dVdt
);
3874 nrkj2
= iprod(r_kj
, r_kj
); /* 5 */
3875 nrij2
= iprod(r_ij
, r_ij
);
3877 cik
= st
*gmx::invsqrt(nrkj2
*nrij2
); /* 12 */
3878 cii
= sth
/nrij2
; /* 10 */
3879 ckk
= sth
/nrkj2
; /* 10 */
3881 for (m
= 0; (m
< DIM
); m
++) /* 39 */
3883 f_i
[m
] = -(cik
*r_kj
[m
]-cii
*r_ij
[m
]);
3884 f_k
[m
] = -(cik
*r_ij
[m
]-ckk
*r_kj
[m
]);
3885 f_j
[m
] = -f_i
[m
]-f_k
[m
];
3892 copy_ivec(SHIFT_IVEC(g
, aj
), jt
);
3894 ivec_sub(SHIFT_IVEC(g
, ai
), jt
, dt_ij
);
3895 ivec_sub(SHIFT_IVEC(g
, ak
), jt
, dt_kj
);
3896 t1
= IVEC2IS(dt_ij
);
3897 t2
= IVEC2IS(dt_kj
);
3899 rvec_inc(fshift
[t1
], f_i
);
3900 rvec_inc(fshift
[CENTRAL
], f_j
);
3901 rvec_inc(fshift
[t2
], f_k
);
3907 real
tab_dihs(int nbonds
,
3908 const t_iatom forceatoms
[], const t_iparams forceparams
[],
3909 const rvec x
[], rvec4 f
[], rvec fshift
[],
3910 const t_pbc
*pbc
, const t_graph
*g
,
3911 real lambda
, real
*dvdlambda
,
3912 const t_mdatoms gmx_unused
*md
, t_fcdata
*fcd
,
3913 int gmx_unused
*global_atom_index
)
3915 int i
, type
, ai
, aj
, ak
, al
, table
;
3917 rvec r_ij
, r_kj
, r_kl
, m
, n
;
3918 real phi
, ddphi
, vpd
, vtot
;
3921 for (i
= 0; (i
< nbonds
); )
3923 type
= forceatoms
[i
++];
3924 ai
= forceatoms
[i
++];
3925 aj
= forceatoms
[i
++];
3926 ak
= forceatoms
[i
++];
3927 al
= forceatoms
[i
++];
3929 phi
= dih_angle(x
[ai
], x
[aj
], x
[ak
], x
[al
], pbc
, r_ij
, r_kj
, r_kl
, m
, n
,
3930 &t1
, &t2
, &t3
); /* 84 */
3932 table
= forceparams
[type
].tab
.table
;
3934 /* Hopefully phi+M_PI never results in values < 0 */
3935 *dvdlambda
+= bonded_tab("dihedral", table
,
3936 &fcd
->dihtab
[table
],
3937 forceparams
[type
].tab
.kA
,
3938 forceparams
[type
].tab
.kB
,
3939 phi
+M_PI
, lambda
, &vpd
, &ddphi
);
3942 do_dih_fup(ai
, aj
, ak
, al
, -ddphi
, r_ij
, r_kj
, r_kl
, m
, n
,
3943 f
, fshift
, pbc
, g
, x
, t1
, t2
, t3
); /* 112 */
3946 fprintf(debug
, "pdih: (%d,%d,%d,%d) phi=%g\n",
3947 ai
, aj
, ak
, al
, phi
);