1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
34 * GROningen Mixture of Alchemy and Childrens' Stories
51 #include "gmx_fatal.h"
57 #include "nonbonded.h"
60 /* Find a better place for this? */
61 const int cmap_coeff_matrix[] = {
62 1, 0, -3, 2, 0, 0, 0, 0, -3, 0, 9, -6, 2, 0, -6, 4 ,
63 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, -9, 6, -2, 0, 6, -4,
64 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, -6, 0, 0, -6, 4 ,
65 0, 0, 3, -2, 0, 0, 0, 0, 0, 0, -9, 6, 0, 0, 6, -4,
66 0, 0, 0, 0, 1, 0, -3, 2, -2, 0, 6, -4, 1, 0, -3, 2 ,
67 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 3, -2, 1, 0, -3, 2 ,
68 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 2, 0, 0, 3, -2,
69 0, 0, 0, 0, 0, 0, 3, -2, 0, 0, -6, 4, 0, 0, 3, -2,
70 0, 1, -2, 1, 0, 0, 0, 0, 0, -3, 6, -3, 0, 2, -4, 2 ,
71 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -6, 3, 0, -2, 4, -2,
72 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, 2, -2,
73 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 3, -3, 0, 0, -2, 2 ,
74 0, 0, 0, 0, 0, 1, -2, 1, 0, -2, 4, -2, 0, 1, -2, 1,
75 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 2, -1, 0, 1, -2, 1,
76 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, -1, 1,
77 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 2, -2, 0, 0, -1, 1
82 int glatnr(int *global_atom_index,int i)
86 if (global_atom_index == NULL) {
89 atnr = global_atom_index[i] + 1;
95 static int pbc_rvec_sub(const t_pbc *pbc,const rvec xi,const rvec xj,rvec dx)
98 return pbc_dx_aiuc(pbc,xi,xj,dx);
107 * Morse potential bond by Frank Everdij
109 * Three parameters needed:
111 * b0 = equilibrium distance in nm
112 * be = beta in nm^-1 (actually, it's nu_e*Sqrt(2*pi*pi*mu/D_e))
113 * cb = well depth in kJ/mol
115 * Note: the potential is referenced to be +cb at infinite separation
116 * and zero at the equilibrium distance!
119 real morse_bonds(int nbonds,
120 const t_iatom forceatoms[],const t_iparams forceparams[],
121 const rvec x[],rvec f[],rvec fshift[],
122 const t_pbc *pbc,const t_graph *g,
123 real lambda,real *dvdl,
124 const t_mdatoms *md,t_fcdata *fcd,
125 int *global_atom_index)
129 real dr,dr2,temp,omtemp,cbomtemp,fbond,vbond,fij,b0,be,cb,vtot;
131 int i,m,ki,type,ai,aj;
135 for(i=0; (i<nbonds); ) {
136 type = forceatoms[i++];
137 ai = forceatoms[i++];
138 aj = forceatoms[i++];
140 b0 = forceparams[type].morse.b0;
141 be = forceparams[type].morse.beta;
142 cb = forceparams[type].morse.cb;
144 ki = pbc_rvec_sub(pbc,x[ai],x[aj],dx); /* 3 */
145 dr2 = iprod(dx,dx); /* 5 */
146 dr = dr2*gmx_invsqrt(dr2); /* 10 */
147 temp = exp(-be*(dr-b0)); /* 12 */
152 omtemp = one-temp; /* 1 */
153 cbomtemp = cb*omtemp; /* 1 */
154 vbond = cbomtemp*omtemp; /* 1 */
155 fbond = -two*be*temp*cbomtemp*gmx_invsqrt(dr2); /* 9 */
156 vtot += vbond; /* 1 */
159 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
163 for (m=0; (m<DIM); m++) { /* 15 */
168 fshift[CENTRAL][m]-=fij;
174 real cubic_bonds(int nbonds,
175 const t_iatom forceatoms[],const t_iparams forceparams[],
176 const rvec x[],rvec f[],rvec fshift[],
177 const t_pbc *pbc,const t_graph *g,
178 real lambda,real *dvdl,
179 const t_mdatoms *md,t_fcdata *fcd,
180 int *global_atom_index)
182 const real three = 3.0;
183 const real two = 2.0;
185 real dr,dr2,dist,kdist,kdist2,fbond,vbond,fij,vtot;
187 int i,m,ki,type,ai,aj;
191 for(i=0; (i<nbonds); ) {
192 type = forceatoms[i++];
193 ai = forceatoms[i++];
194 aj = forceatoms[i++];
196 b0 = forceparams[type].cubic.b0;
197 kb = forceparams[type].cubic.kb;
198 kcub = forceparams[type].cubic.kcub;
200 ki = pbc_rvec_sub(pbc,x[ai],x[aj],dx); /* 3 */
201 dr2 = iprod(dx,dx); /* 5 */
206 dr = dr2*gmx_invsqrt(dr2); /* 10 */
211 vbond = kdist2 + kcub*kdist2*dist;
212 fbond = -(two*kdist + three*kdist2*kcub)/dr;
214 vtot += vbond; /* 21 */
217 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
220 for (m=0; (m<DIM); m++) { /* 15 */
225 fshift[CENTRAL][m]-=fij;
231 real FENE_bonds(int nbonds,
232 const t_iatom forceatoms[],const t_iparams forceparams[],
233 const rvec x[],rvec f[],rvec fshift[],
234 const t_pbc *pbc,const t_graph *g,
235 real lambda,real *dvdl,
236 const t_mdatoms *md,t_fcdata *fcd,
237 int *global_atom_index)
242 real dr,dr2,bm2,omdr2obm2,fbond,vbond,fij,vtot;
244 int i,m,ki,type,ai,aj;
248 for(i=0; (i<nbonds); ) {
249 type = forceatoms[i++];
250 ai = forceatoms[i++];
251 aj = forceatoms[i++];
253 bm = forceparams[type].fene.bm;
254 kb = forceparams[type].fene.kb;
256 ki = pbc_rvec_sub(pbc,x[ai],x[aj],dx); /* 3 */
257 dr2 = iprod(dx,dx); /* 5 */
266 "r^2 (%f) >= bm^2 (%f) in FENE bond between atoms %d and %d",
268 glatnr(global_atom_index,ai),
269 glatnr(global_atom_index,aj));
271 omdr2obm2 = one - dr2/bm2;
273 vbond = -half*kb*bm2*log(omdr2obm2);
274 fbond = -kb/omdr2obm2;
276 vtot += vbond; /* 35 */
279 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
282 for (m=0; (m<DIM); m++) { /* 15 */
287 fshift[CENTRAL][m]-=fij;
293 real harmonic(real kA,real kB,real xA,real xB,real x,real lambda,
297 real L1,kk,x0,dx,dx2;
301 kk = L1*kA+lambda*kB;
302 x0 = L1*xA+lambda*xB;
309 dvdl = half*(kB-kA)*dx2 + (xA-xB)*kk*dx;
316 /* That was 19 flops */
320 real bonds(int nbonds,
321 const t_iatom forceatoms[],const t_iparams forceparams[],
322 const rvec x[],rvec f[],rvec fshift[],
323 const t_pbc *pbc,const t_graph *g,
324 real lambda,real *dvdlambda,
325 const t_mdatoms *md,t_fcdata *fcd,
326 int *global_atom_index)
328 int i,m,ki,ai,aj,type;
329 real dr,dr2,fbond,vbond,fij,vtot;
334 for(i=0; (i<nbonds); ) {
335 type = forceatoms[i++];
336 ai = forceatoms[i++];
337 aj = forceatoms[i++];
339 ki = pbc_rvec_sub(pbc,x[ai],x[aj],dx); /* 3 */
340 dr2 = iprod(dx,dx); /* 5 */
341 dr = dr2*gmx_invsqrt(dr2); /* 10 */
343 *dvdlambda += harmonic(forceparams[type].harmonic.krA,
344 forceparams[type].harmonic.krB,
345 forceparams[type].harmonic.rA,
346 forceparams[type].harmonic.rB,
347 dr,lambda,&vbond,&fbond); /* 19 */
354 fbond *= gmx_invsqrt(dr2); /* 6 */
357 fprintf(debug,"BONDS: dr = %10g vbond = %10g fbond = %10g\n",
361 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
364 for (m=0; (m<DIM); m++) { /* 15 */
369 fshift[CENTRAL][m]-=fij;
375 real restraint_bonds(int nbonds,
376 const t_iatom forceatoms[],const t_iparams forceparams[],
377 const rvec x[],rvec f[],rvec fshift[],
378 const t_pbc *pbc,const t_graph *g,
379 real lambda,real *dvdlambda,
380 const t_mdatoms *md,t_fcdata *fcd,
381 int *global_atom_index)
383 int i,m,ki,ai,aj,type;
384 real dr,dr2,fbond,vbond,fij,vtot;
386 real low,dlow,up1,dup1,up2,dup2,k,dk;
394 for(i=0; (i<nbonds); )
396 type = forceatoms[i++];
397 ai = forceatoms[i++];
398 aj = forceatoms[i++];
400 ki = pbc_rvec_sub(pbc,x[ai],x[aj],dx); /* 3 */
401 dr2 = iprod(dx,dx); /* 5 */
402 dr = dr2*gmx_invsqrt(dr2); /* 10 */
404 low = L1*forceparams[type].restraint.lowA + lambda*forceparams[type].restraint.lowB;
405 dlow = -forceparams[type].restraint.lowA + forceparams[type].restraint.lowB;
406 up1 = L1*forceparams[type].restraint.up1A + lambda*forceparams[type].restraint.up1B;
407 dup1 = -forceparams[type].restraint.up1A + forceparams[type].restraint.up1B;
408 up2 = L1*forceparams[type].restraint.up2A + lambda*forceparams[type].restraint.up2B;
409 dup2 = -forceparams[type].restraint.up2A + forceparams[type].restraint.up2B;
410 k = L1*forceparams[type].restraint.kA + lambda*forceparams[type].restraint.kB;
411 dk = -forceparams[type].restraint.kA + forceparams[type].restraint.kB;
420 *dvdlambda += 0.5*dk*drh2 - k*dlow*drh;
433 *dvdlambda += 0.5*dk*drh2 - k*dup1*drh;
438 vbond = k*(up2 - up1)*(0.5*(up2 - up1) + drh);
439 fbond = -k*(up2 - up1);
440 *dvdlambda += dk*(up2 - up1)*(0.5*(up2 - up1) + drh)
441 + k*(dup2 - dup1)*(up2 - up1 + drh)
442 - k*(up2 - up1)*dup2;
449 fbond *= gmx_invsqrt(dr2); /* 6 */
452 fprintf(debug,"BONDS: dr = %10g vbond = %10g fbond = %10g\n",
456 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
459 for (m=0; (m<DIM); m++) { /* 15 */
464 fshift[CENTRAL][m]-=fij;
471 real polarize(int nbonds,
472 const t_iatom forceatoms[],const t_iparams forceparams[],
473 const rvec x[],rvec f[],rvec fshift[],
474 const t_pbc *pbc,const t_graph *g,
475 real lambda,real *dvdlambda,
476 const t_mdatoms *md,t_fcdata *fcd,
477 int *global_atom_index)
479 int i,m,ki,ai,aj,type;
480 real dr,dr2,fbond,vbond,fij,vtot,ksh;
485 for(i=0; (i<nbonds); ) {
486 type = forceatoms[i++];
487 ai = forceatoms[i++];
488 aj = forceatoms[i++];
489 ksh = sqr(md->chargeA[aj])*ONE_4PI_EPS0/forceparams[type].polarize.alpha;
491 fprintf(debug,"POL: local ai = %d aj = %d ksh = %.3f\n",ai,aj,ksh);
493 ki = pbc_rvec_sub(pbc,x[ai],x[aj],dx); /* 3 */
494 dr2 = iprod(dx,dx); /* 5 */
495 dr = dr2*gmx_invsqrt(dr2); /* 10 */
497 *dvdlambda += harmonic(ksh,ksh,0,0,dr,lambda,&vbond,&fbond); /* 19 */
503 fbond *= gmx_invsqrt(dr2); /* 6 */
506 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
509 for (m=0; (m<DIM); m++) { /* 15 */
514 fshift[CENTRAL][m]-=fij;
520 real anharm_polarize(int nbonds,
521 const t_iatom forceatoms[],const t_iparams forceparams[],
522 const rvec x[],rvec f[],rvec fshift[],
523 const t_pbc *pbc,const t_graph *g,
524 real lambda,real *dvdlambda,
525 const t_mdatoms *md,t_fcdata *fcd,
526 int *global_atom_index)
528 int i,m,ki,ai,aj,type;
529 real dr,dr2,fbond,vbond,fij,vtot,ksh,khyp,drcut,ddr,ddr3;
534 for(i=0; (i<nbonds); ) {
535 type = forceatoms[i++];
536 ai = forceatoms[i++];
537 aj = forceatoms[i++];
538 ksh = sqr(md->chargeA[aj])*ONE_4PI_EPS0/forceparams[type].anharm_polarize.alpha; /* 7*/
539 khyp = forceparams[type].anharm_polarize.khyp;
540 drcut = forceparams[type].anharm_polarize.drcut;
542 fprintf(debug,"POL: local ai = %d aj = %d ksh = %.3f\n",ai,aj,ksh);
544 ki = pbc_rvec_sub(pbc,x[ai],x[aj],dx); /* 3 */
545 dr2 = iprod(dx,dx); /* 5 */
546 dr = dr2*gmx_invsqrt(dr2); /* 10 */
548 *dvdlambda += harmonic(ksh,ksh,0,0,dr,lambda,&vbond,&fbond); /* 19 */
556 vbond += khyp*ddr*ddr3;
557 fbond -= 4*khyp*ddr3;
559 fbond *= gmx_invsqrt(dr2); /* 6 */
563 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
566 for (m=0; (m<DIM); m++) { /* 15 */
571 fshift[CENTRAL][m]-=fij;
577 real water_pol(int nbonds,
578 const t_iatom forceatoms[],const t_iparams forceparams[],
579 const rvec x[],rvec f[],rvec fshift[],
580 const t_pbc *pbc,const t_graph *g,
581 real lambda,real *dvdlambda,
582 const t_mdatoms *md,t_fcdata *fcd,
583 int *global_atom_index)
585 /* This routine implements anisotropic polarizibility for water, through
586 * a shell connected to a dummy with spring constant that differ in the
587 * three spatial dimensions in the molecular frame.
589 int i,m,aO,aH1,aH2,aD,aS,type,type0;
590 rvec dOH1,dOH2,dHH,dOD,dDS,nW,kk,dx,kdx,proj;
594 real vtot,fij,r_HH,r_OD,r_nW,tx,ty,tz,qS;
598 type0 = forceatoms[0];
600 qS = md->chargeA[aS];
601 kk[XX] = sqr(qS)*ONE_4PI_EPS0/forceparams[type0].wpol.al_x;
602 kk[YY] = sqr(qS)*ONE_4PI_EPS0/forceparams[type0].wpol.al_y;
603 kk[ZZ] = sqr(qS)*ONE_4PI_EPS0/forceparams[type0].wpol.al_z;
604 r_HH = 1.0/forceparams[type0].wpol.rHH;
605 r_OD = 1.0/forceparams[type0].wpol.rOD;
607 fprintf(debug,"WPOL: qS = %10.5f aS = %5d\n",qS,aS);
608 fprintf(debug,"WPOL: kk = %10.3f %10.3f %10.3f\n",
609 kk[XX],kk[YY],kk[ZZ]);
610 fprintf(debug,"WPOL: rOH = %10.3f rHH = %10.3f rOD = %10.3f\n",
611 forceparams[type0].wpol.rOH,
612 forceparams[type0].wpol.rHH,
613 forceparams[type0].wpol.rOD);
615 for(i=0; (i<nbonds); i+=6) {
616 type = forceatoms[i];
618 gmx_fatal(FARGS,"Sorry, type = %d, type0 = %d, file = %s, line = %d",
619 type,type0,__FILE__,__LINE__);
620 aO = forceatoms[i+1];
621 aH1 = forceatoms[i+2];
622 aH2 = forceatoms[i+3];
623 aD = forceatoms[i+4];
624 aS = forceatoms[i+5];
626 /* Compute vectors describing the water frame */
627 rvec_sub(x[aH1],x[aO], dOH1);
628 rvec_sub(x[aH2],x[aO], dOH2);
629 rvec_sub(x[aH2],x[aH1],dHH);
630 rvec_sub(x[aD], x[aO], dOD);
631 rvec_sub(x[aS], x[aD], dDS);
634 /* Compute inverse length of normal vector
635 * (this one could be precomputed, but I'm too lazy now)
637 r_nW = gmx_invsqrt(iprod(nW,nW));
638 /* This is for precision, but does not make a big difference,
641 r_OD = gmx_invsqrt(iprod(dOD,dOD));
643 /* Normalize the vectors in the water frame */
648 /* Compute displacement of shell along components of the vector */
649 dx[ZZ] = iprod(dDS,dOD);
650 /* Compute projection on the XY plane: dDS - dx[ZZ]*dOD */
651 for(m=0; (m<DIM); m++)
652 proj[m] = dDS[m]-dx[ZZ]*dOD[m];
654 /*dx[XX] = iprod(dDS,nW);
655 dx[YY] = iprod(dDS,dHH);*/
656 dx[XX] = iprod(proj,nW);
657 for(m=0; (m<DIM); m++)
658 proj[m] -= dx[XX]*nW[m];
659 dx[YY] = iprod(proj,dHH);
663 fprintf(debug,"WPOL: dx2=%10g dy2=%10g dz2=%10g sum=%10g dDS^2=%10g\n",
664 sqr(dx[XX]),sqr(dx[YY]),sqr(dx[ZZ]),iprod(dx,dx),iprod(dDS,dDS));
665 fprintf(debug,"WPOL: dHH=(%10g,%10g,%10g)\n",dHH[XX],dHH[YY],dHH[ZZ]);
666 fprintf(debug,"WPOL: dOD=(%10g,%10g,%10g), 1/r_OD = %10g\n",
667 dOD[XX],dOD[YY],dOD[ZZ],1/r_OD);
668 fprintf(debug,"WPOL: nW =(%10g,%10g,%10g), 1/r_nW = %10g\n",
669 nW[XX],nW[YY],nW[ZZ],1/r_nW);
670 fprintf(debug,"WPOL: dx =%10g, dy =%10g, dz =%10g\n",
671 dx[XX],dx[YY],dx[ZZ]);
672 fprintf(debug,"WPOL: dDSx=%10g, dDSy=%10g, dDSz=%10g\n",
673 dDS[XX],dDS[YY],dDS[ZZ]);
676 /* Now compute the forces and energy */
677 kdx[XX] = kk[XX]*dx[XX];
678 kdx[YY] = kk[YY]*dx[YY];
679 kdx[ZZ] = kk[ZZ]*dx[ZZ];
680 vtot += iprod(dx,kdx);
681 for(m=0; (m<DIM); m++) {
682 /* This is a tensor operation but written out for speed */
695 fprintf(debug,"WPOL: vwpol=%g\n",0.5*iprod(dx,kdx));
696 fprintf(debug,"WPOL: df = (%10g, %10g, %10g)\n",df[XX],df[YY],df[ZZ]);
704 static real do_1_thole(const rvec xi,const rvec xj,rvec fi,rvec fj,
705 const t_pbc *pbc,real qq,
706 rvec fshift[],real afac)
709 real r12sq,r12_1,r12n,r12bar,v0,v1,fscal,ebar,fff;
712 t = pbc_rvec_sub(pbc,xi,xj,r12); /* 3 */
714 r12sq = iprod(r12,r12); /* 5 */
715 r12_1 = gmx_invsqrt(r12sq); /* 5 */
716 r12bar = afac/r12_1; /* 5 */
717 v0 = qq*ONE_4PI_EPS0*r12_1; /* 2 */
718 ebar = exp(-r12bar); /* 5 */
719 v1 = (1-(1+0.5*r12bar)*ebar); /* 4 */
720 fscal = ((v0*r12_1)*v1 - v0*0.5*afac*ebar*(r12bar+1))*r12_1; /* 9 */
722 fprintf(debug,"THOLE: v0 = %.3f v1 = %.3f r12= % .3f r12bar = %.3f fscal = %.3f ebar = %.3f\n",v0,v1,1/r12_1,r12bar,fscal,ebar);
724 for(m=0; (m<DIM); m++) {
729 fshift[CENTRAL][m] -= fff;
732 return v0*v1; /* 1 */
736 real thole_pol(int nbonds,
737 const t_iatom forceatoms[],const t_iparams forceparams[],
738 const rvec x[],rvec f[],rvec fshift[],
739 const t_pbc *pbc,const t_graph *g,
740 real lambda,real *dvdlambda,
741 const t_mdatoms *md,t_fcdata *fcd,
742 int *global_atom_index)
744 /* Interaction between two pairs of particles with opposite charge */
745 int i,type,a1,da1,a2,da2;
746 real q1,q2,qq,a,al1,al2,afac;
749 for(i=0; (i<nbonds); ) {
750 type = forceatoms[i++];
751 a1 = forceatoms[i++];
752 da1 = forceatoms[i++];
753 a2 = forceatoms[i++];
754 da2 = forceatoms[i++];
755 q1 = md->chargeA[da1];
756 q2 = md->chargeA[da2];
757 a = forceparams[type].thole.a;
758 al1 = forceparams[type].thole.alpha1;
759 al2 = forceparams[type].thole.alpha2;
761 afac = a*pow(al1*al2,-1.0/6.0);
762 V += do_1_thole(x[a1], x[a2], f[a1], f[a2], pbc, qq,fshift,afac);
763 V += do_1_thole(x[da1],x[a2], f[da1],f[a2], pbc,-qq,fshift,afac);
764 V += do_1_thole(x[a1], x[da2],f[a1], f[da2],pbc,-qq,fshift,afac);
765 V += do_1_thole(x[da1],x[da2],f[da1],f[da2],pbc, qq,fshift,afac);
771 real bond_angle(const rvec xi,const rvec xj,const rvec xk,const t_pbc *pbc,
772 rvec r_ij,rvec r_kj,real *costh,
774 /* Return value is the angle between the bonds i-j and j-k */
779 *t1 = pbc_rvec_sub(pbc,xi,xj,r_ij); /* 3 */
780 *t2 = pbc_rvec_sub(pbc,xk,xj,r_kj); /* 3 */
782 *costh=cos_angle(r_ij,r_kj); /* 25 */
783 th=acos(*costh); /* 10 */
788 real angles(int nbonds,
789 const t_iatom forceatoms[],const t_iparams forceparams[],
790 const rvec x[],rvec f[],rvec fshift[],
791 const t_pbc *pbc,const t_graph *g,
792 real lambda,real *dvdlambda,
793 const t_mdatoms *md,t_fcdata *fcd,
794 int *global_atom_index)
796 int i,ai,aj,ak,t1,t2,type;
798 real cos_theta,cos_theta2,theta,dVdt,va,vtot;
802 for(i=0; (i<nbonds); ) {
803 type = forceatoms[i++];
804 ai = forceatoms[i++];
805 aj = forceatoms[i++];
806 ak = forceatoms[i++];
808 theta = bond_angle(x[ai],x[aj],x[ak],pbc,
809 r_ij,r_kj,&cos_theta,&t1,&t2); /* 41 */
811 *dvdlambda += harmonic(forceparams[type].harmonic.krA,
812 forceparams[type].harmonic.krB,
813 forceparams[type].harmonic.rA*DEG2RAD,
814 forceparams[type].harmonic.rB*DEG2RAD,
815 theta,lambda,&va,&dVdt); /* 21 */
818 cos_theta2 = sqr(cos_theta);
819 if (cos_theta2 < 1) {
826 st = dVdt*gmx_invsqrt(1 - cos_theta2); /* 12 */
827 sth = st*cos_theta; /* 1 */
830 fprintf(debug,"ANGLES: theta = %10g vth = %10g dV/dtheta = %10g\n",
831 theta*RAD2DEG,va,dVdt);
833 nrkj2=iprod(r_kj,r_kj); /* 5 */
834 nrij2=iprod(r_ij,r_ij);
836 cik=st*gmx_invsqrt(nrkj2*nrij2); /* 12 */
837 cii=sth/nrij2; /* 10 */
838 ckk=sth/nrkj2; /* 10 */
840 for (m=0; (m<DIM); m++) { /* 39 */
841 f_i[m]=-(cik*r_kj[m]-cii*r_ij[m]);
842 f_k[m]=-(cik*r_ij[m]-ckk*r_kj[m]);
843 f_j[m]=-f_i[m]-f_k[m];
849 copy_ivec(SHIFT_IVEC(g,aj),jt);
851 ivec_sub(SHIFT_IVEC(g,ai),jt,dt_ij);
852 ivec_sub(SHIFT_IVEC(g,ak),jt,dt_kj);
856 rvec_inc(fshift[t1],f_i);
857 rvec_inc(fshift[CENTRAL],f_j);
858 rvec_inc(fshift[t2],f_k);
864 real linear_angles(int nbonds,
865 const t_iatom forceatoms[],const t_iparams forceparams[],
866 const rvec x[],rvec f[],rvec fshift[],
867 const t_pbc *pbc,const t_graph *g,
868 real lambda,real *dvdlambda,
869 const t_mdatoms *md,t_fcdata *fcd,
870 int *global_atom_index)
872 int i,m,ai,aj,ak,t1,t2,type;
874 real L1,kA,kB,aA,aB,dr,dr2,va,vtot,a,b,klin,dvdl;
876 rvec r_ij,r_kj,r_ik,dx;
881 for(i=0; (i<nbonds); ) {
882 type = forceatoms[i++];
883 ai = forceatoms[i++];
884 aj = forceatoms[i++];
885 ak = forceatoms[i++];
887 kA = forceparams[type].linangle.klinA;
888 kB = forceparams[type].linangle.klinB;
889 klin = L1*kA + lambda*kB;
891 aA = forceparams[type].linangle.aA;
892 aB = forceparams[type].linangle.aB;
896 t1 = pbc_rvec_sub(pbc,x[ai],x[aj],r_ij);
897 t2 = pbc_rvec_sub(pbc,x[ak],x[aj],r_kj);
898 rvec_sub(r_ij,r_kj,r_ik);
901 for(m=0; (m<DIM); m++)
903 dr = - a * r_ij[m] - b * r_kj[m];
908 f_j[m] = -(f_i[m]+f_k[m]);
914 dvdl += 0.5*(kB-kA)*dr2 + klin*(aB-aA)*iprod(dx,r_ik);
919 copy_ivec(SHIFT_IVEC(g,aj),jt);
921 ivec_sub(SHIFT_IVEC(g,ai),jt,dt_ij);
922 ivec_sub(SHIFT_IVEC(g,ak),jt,dt_kj);
926 rvec_inc(fshift[t1],f_i);
927 rvec_inc(fshift[CENTRAL],f_j);
928 rvec_inc(fshift[t2],f_k);
934 real urey_bradley(int nbonds,
935 const t_iatom forceatoms[],const t_iparams forceparams[],
936 const rvec x[],rvec f[],rvec fshift[],
937 const t_pbc *pbc,const t_graph *g,
938 real lambda,real *dvdlambda,
939 const t_mdatoms *md,t_fcdata *fcd,
940 int *global_atom_index)
942 int i,m,ai,aj,ak,t1,t2,type,ki;
944 real cos_theta,cos_theta2,theta;
945 real dVdt,va,vtot,kth,th0,kUB,r13,dr,dr2,vbond,fbond,fik;
946 ivec jt,dt_ij,dt_kj,dt_ik;
949 for(i=0; (i<nbonds); ) {
950 type = forceatoms[i++];
951 ai = forceatoms[i++];
952 aj = forceatoms[i++];
953 ak = forceatoms[i++];
954 th0 = forceparams[type].u_b.theta*DEG2RAD;
955 kth = forceparams[type].u_b.ktheta;
956 r13 = forceparams[type].u_b.r13;
957 kUB = forceparams[type].u_b.kUB;
959 theta = bond_angle(x[ai],x[aj],x[ak],pbc,
960 r_ij,r_kj,&cos_theta,&t1,&t2); /* 41 */
962 *dvdlambda += harmonic(kth,kth,th0,th0,theta,lambda,&va,&dVdt); /* 21 */
965 ki = pbc_rvec_sub(pbc,x[ai],x[ak],r_ik); /* 3 */
966 dr2 = iprod(r_ik,r_ik); /* 5 */
967 dr = dr2*gmx_invsqrt(dr2); /* 10 */
969 *dvdlambda += harmonic(kUB,kUB,r13,r13,dr,lambda,&vbond,&fbond); /* 19 */
971 cos_theta2 = sqr(cos_theta); /* 1 */
972 if (cos_theta2 < 1) {
978 st = dVdt*gmx_invsqrt(1 - cos_theta2); /* 12 */
979 sth = st*cos_theta; /* 1 */
982 fprintf(debug,"ANGLES: theta = %10g vth = %10g dV/dtheta = %10g\n",
983 theta*RAD2DEG,va,dVdt);
985 nrkj2=iprod(r_kj,r_kj); /* 5 */
986 nrij2=iprod(r_ij,r_ij);
988 cik=st*gmx_invsqrt(nrkj2*nrij2); /* 12 */
989 cii=sth/nrij2; /* 10 */
990 ckk=sth/nrkj2; /* 10 */
992 for (m=0; (m<DIM); m++) { /* 39 */
993 f_i[m]=-(cik*r_kj[m]-cii*r_ij[m]);
994 f_k[m]=-(cik*r_ij[m]-ckk*r_kj[m]);
995 f_j[m]=-f_i[m]-f_k[m];
1001 copy_ivec(SHIFT_IVEC(g,aj),jt);
1003 ivec_sub(SHIFT_IVEC(g,ai),jt,dt_ij);
1004 ivec_sub(SHIFT_IVEC(g,ak),jt,dt_kj);
1008 rvec_inc(fshift[t1],f_i);
1009 rvec_inc(fshift[CENTRAL],f_j);
1010 rvec_inc(fshift[t2],f_k);
1012 /* Time for the bond calculations */
1016 vtot += vbond; /* 1*/
1017 fbond *= gmx_invsqrt(dr2); /* 6 */
1020 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,ak),dt_ik);
1023 for (m=0; (m<DIM); m++) { /* 15 */
1028 fshift[CENTRAL][m]-=fik;
1034 real quartic_angles(int nbonds,
1035 const t_iatom forceatoms[],const t_iparams forceparams[],
1036 const rvec x[],rvec f[],rvec fshift[],
1037 const t_pbc *pbc,const t_graph *g,
1038 real lambda,real *dvdlambda,
1039 const t_mdatoms *md,t_fcdata *fcd,
1040 int *global_atom_index)
1042 int i,j,ai,aj,ak,t1,t2,type;
1044 real cos_theta,cos_theta2,theta,dt,dVdt,va,dtp,c,vtot;
1045 ivec jt,dt_ij,dt_kj;
1048 for(i=0; (i<nbonds); ) {
1049 type = forceatoms[i++];
1050 ai = forceatoms[i++];
1051 aj = forceatoms[i++];
1052 ak = forceatoms[i++];
1054 theta = bond_angle(x[ai],x[aj],x[ak],pbc,
1055 r_ij,r_kj,&cos_theta,&t1,&t2); /* 41 */
1057 dt = theta - forceparams[type].qangle.theta*DEG2RAD; /* 2 */
1060 va = forceparams[type].qangle.c[0];
1062 for(j=1; j<=4; j++) {
1063 c = forceparams[type].qangle.c[j];
1072 cos_theta2 = sqr(cos_theta); /* 1 */
1073 if (cos_theta2 < 1) {
1080 st = dVdt*gmx_invsqrt(1 - cos_theta2); /* 12 */
1081 sth = st*cos_theta; /* 1 */
1084 fprintf(debug,"ANGLES: theta = %10g vth = %10g dV/dtheta = %10g\n",
1085 theta*RAD2DEG,va,dVdt);
1087 nrkj2=iprod(r_kj,r_kj); /* 5 */
1088 nrij2=iprod(r_ij,r_ij);
1090 cik=st*gmx_invsqrt(nrkj2*nrij2); /* 12 */
1091 cii=sth/nrij2; /* 10 */
1092 ckk=sth/nrkj2; /* 10 */
1094 for (m=0; (m<DIM); m++) { /* 39 */
1095 f_i[m]=-(cik*r_kj[m]-cii*r_ij[m]);
1096 f_k[m]=-(cik*r_ij[m]-ckk*r_kj[m]);
1097 f_j[m]=-f_i[m]-f_k[m];
1103 copy_ivec(SHIFT_IVEC(g,aj),jt);
1105 ivec_sub(SHIFT_IVEC(g,ai),jt,dt_ij);
1106 ivec_sub(SHIFT_IVEC(g,ak),jt,dt_kj);
1110 rvec_inc(fshift[t1],f_i);
1111 rvec_inc(fshift[CENTRAL],f_j);
1112 rvec_inc(fshift[t2],f_k);
1118 real dih_angle(const rvec xi,const rvec xj,const rvec xk,const rvec xl,
1120 rvec r_ij,rvec r_kj,rvec r_kl,rvec m,rvec n,
1121 real *sign,int *t1,int *t2,int *t3)
1125 *t1 = pbc_rvec_sub(pbc,xi,xj,r_ij); /* 3 */
1126 *t2 = pbc_rvec_sub(pbc,xk,xj,r_kj); /* 3 */
1127 *t3 = pbc_rvec_sub(pbc,xk,xl,r_kl); /* 3 */
1129 cprod(r_ij,r_kj,m); /* 9 */
1130 cprod(r_kj,r_kl,n); /* 9 */
1131 phi=gmx_angle(m,n); /* 49 (assuming 25 for atan2) */
1132 ipr=iprod(r_ij,n); /* 5 */
1133 (*sign)=(ipr<0.0)?-1.0:1.0;
1134 phi=(*sign)*phi; /* 1 */
1141 void do_dih_fup(int i,int j,int k,int l,real ddphi,
1142 rvec r_ij,rvec r_kj,rvec r_kl,
1143 rvec m,rvec n,rvec f[],rvec fshift[],
1144 const t_pbc *pbc,const t_graph *g,
1145 const rvec x[],int t1,int t2,int t3)
1148 rvec f_i,f_j,f_k,f_l;
1149 rvec uvec,vvec,svec,dx_jl;
1150 real iprm,iprn,nrkj,nrkj2;
1152 ivec jt,dt_ij,dt_kj,dt_lj;
1154 iprm = iprod(m,m); /* 5 */
1155 iprn = iprod(n,n); /* 5 */
1156 nrkj2 = iprod(r_kj,r_kj); /* 5 */
1157 toler = nrkj2*GMX_REAL_EPS;
1158 if ((iprm > toler) && (iprn > toler)) {
1159 nrkj = nrkj2*gmx_invsqrt(nrkj2); /* 10 */
1160 a = -ddphi*nrkj/iprm; /* 11 */
1161 svmul(a,m,f_i); /* 3 */
1162 a = ddphi*nrkj/iprn; /* 11 */
1163 svmul(a,n,f_l); /* 3 */
1164 p = iprod(r_ij,r_kj); /* 5 */
1165 p /= nrkj2; /* 10 */
1166 q = iprod(r_kl,r_kj); /* 5 */
1167 q /= nrkj2; /* 10 */
1168 svmul(p,f_i,uvec); /* 3 */
1169 svmul(q,f_l,vvec); /* 3 */
1170 rvec_sub(uvec,vvec,svec); /* 3 */
1171 rvec_sub(f_i,svec,f_j); /* 3 */
1172 rvec_add(f_l,svec,f_k); /* 3 */
1173 rvec_inc(f[i],f_i); /* 3 */
1174 rvec_dec(f[j],f_j); /* 3 */
1175 rvec_dec(f[k],f_k); /* 3 */
1176 rvec_inc(f[l],f_l); /* 3 */
1179 copy_ivec(SHIFT_IVEC(g,j),jt);
1180 ivec_sub(SHIFT_IVEC(g,i),jt,dt_ij);
1181 ivec_sub(SHIFT_IVEC(g,k),jt,dt_kj);
1182 ivec_sub(SHIFT_IVEC(g,l),jt,dt_lj);
1187 t3 = pbc_rvec_sub(pbc,x[l],x[j],dx_jl);
1192 rvec_inc(fshift[t1],f_i);
1193 rvec_dec(fshift[CENTRAL],f_j);
1194 rvec_dec(fshift[t2],f_k);
1195 rvec_inc(fshift[t3],f_l);
1201 real dopdihs(real cpA,real cpB,real phiA,real phiB,int mult,
1202 real phi,real lambda,real *V,real *F)
1204 real v,dvdl,mdphi,v1,sdphi,ddphi;
1205 real L1 = 1.0 - lambda;
1206 real ph0 = (L1*phiA + lambda*phiB)*DEG2RAD;
1207 real dph0 = (phiB - phiA)*DEG2RAD;
1208 real cp = L1*cpA + lambda*cpB;
1210 mdphi = mult*phi - ph0;
1212 ddphi = -cp*mult*sdphi;
1213 v1 = 1.0 + cos(mdphi);
1216 dvdl = (cpB - cpA)*v1 + cp*dph0*sdphi;
1223 /* That was 40 flops */
1226 static real dopdihs_min(real cpA,real cpB,real phiA,real phiB,int mult,
1227 real phi,real lambda,real *V,real *F)
1228 /* similar to dopdihs, except for a minus sign *
1229 * and a different treatment of mult/phi0 */
1231 real v,dvdl,mdphi,v1,sdphi,ddphi;
1232 real L1 = 1.0 - lambda;
1233 real ph0 = (L1*phiA + lambda*phiB)*DEG2RAD;
1234 real dph0 = (phiB - phiA)*DEG2RAD;
1235 real cp = L1*cpA + lambda*cpB;
1237 mdphi = mult*(phi-ph0);
1239 ddphi = cp*mult*sdphi;
1240 v1 = 1.0-cos(mdphi);
1243 dvdl = (cpB-cpA)*v1 + cp*dph0*sdphi;
1250 /* That was 40 flops */
1253 real pdihs(int nbonds,
1254 const t_iatom forceatoms[],const t_iparams forceparams[],
1255 const rvec x[],rvec f[],rvec fshift[],
1256 const t_pbc *pbc,const t_graph *g,
1257 real lambda,real *dvdlambda,
1258 const t_mdatoms *md,t_fcdata *fcd,
1259 int *global_atom_index)
1261 int i,type,ai,aj,ak,al;
1263 rvec r_ij,r_kj,r_kl,m,n;
1264 real phi,sign,ddphi,vpd,vtot;
1268 for(i=0; (i<nbonds); ) {
1269 type = forceatoms[i++];
1270 ai = forceatoms[i++];
1271 aj = forceatoms[i++];
1272 ak = forceatoms[i++];
1273 al = forceatoms[i++];
1275 phi=dih_angle(x[ai],x[aj],x[ak],x[al],pbc,r_ij,r_kj,r_kl,m,n,
1276 &sign,&t1,&t2,&t3); /* 84 */
1278 *dvdlambda += dopdihs(forceparams[type].pdihs.cpA,
1279 forceparams[type].pdihs.cpB,
1280 forceparams[type].pdihs.phiA,
1281 forceparams[type].pdihs.phiB,
1282 forceparams[type].pdihs.mult,
1283 phi,lambda,&vpd,&ddphi);
1286 do_dih_fup(ai,aj,ak,al,ddphi,r_ij,r_kj,r_kl,m,n,
1287 f,fshift,pbc,g,x,t1,t2,t3); /* 112 */
1290 fprintf(debug,"pdih: (%d,%d,%d,%d) phi=%g\n",
1300 real idihs(int nbonds,
1301 const t_iatom forceatoms[],const t_iparams forceparams[],
1302 const rvec x[],rvec f[],rvec fshift[],
1303 const t_pbc *pbc,const t_graph *g,
1304 real lambda,real *dvdlambda,
1305 const t_mdatoms *md,t_fcdata *fcd,
1306 int *global_atom_index)
1308 int i,type,ai,aj,ak,al;
1310 real phi,phi0,dphi0,ddphi,sign,vtot;
1311 rvec r_ij,r_kj,r_kl,m,n;
1312 real L1,kk,dp,dp2,kA,kB,pA,pB,dvdl;
1318 for(i=0; (i<nbonds); ) {
1319 type = forceatoms[i++];
1320 ai = forceatoms[i++];
1321 aj = forceatoms[i++];
1322 ak = forceatoms[i++];
1323 al = forceatoms[i++];
1325 phi=dih_angle(x[ai],x[aj],x[ak],x[al],pbc,r_ij,r_kj,r_kl,m,n,
1326 &sign,&t1,&t2,&t3); /* 84 */
1328 /* phi can jump if phi0 is close to Pi/-Pi, which will cause huge
1329 * force changes if we just apply a normal harmonic.
1330 * Instead, we first calculate phi-phi0 and take it modulo (-Pi,Pi).
1331 * This means we will never have the periodicity problem, unless
1332 * the dihedral is Pi away from phiO, which is very unlikely due to
1335 kA = forceparams[type].harmonic.krA;
1336 kB = forceparams[type].harmonic.krB;
1337 pA = forceparams[type].harmonic.rA;
1338 pB = forceparams[type].harmonic.rB;
1340 kk = L1*kA + lambda*kB;
1341 phi0 = (L1*pA + lambda*pB)*DEG2RAD;
1342 dphi0 = (pB - pA)*DEG2RAD;
1344 /* dp = (phi-phi0), modulo (-pi,pi) */
1346 /* dp cannot be outside (-2*pi,2*pi) */
1357 dvdl += 0.5*(kB - kA)*dp2 - kk*dphi0*dp;
1359 do_dih_fup(ai,aj,ak,al,(real)(-ddphi),r_ij,r_kj,r_kl,m,n,
1360 f,fshift,pbc,g,x,t1,t2,t3); /* 112 */
1364 fprintf(debug,"idih: (%d,%d,%d,%d) phi=%g\n",
1374 real posres(int nbonds,
1375 const t_iatom forceatoms[],const t_iparams forceparams[],
1376 const rvec x[],rvec f[],rvec vir_diag,
1378 real lambda,real *dvdlambda,
1379 int refcoord_scaling,int ePBC,rvec comA,rvec comB)
1381 int i,ai,m,d,type,ki,npbcdim=0;
1382 const t_iparams *pr;
1385 real posA,posB,ref=0;
1386 rvec comA_sc,comB_sc,rdist,dpdl,pos,dx;
1388 npbcdim = ePBC2npbcdim(ePBC);
1390 if (refcoord_scaling == erscCOM)
1392 clear_rvec(comA_sc);
1393 clear_rvec(comB_sc);
1394 for(m=0; m<npbcdim; m++)
1396 for(d=m; d<npbcdim; d++)
1398 comA_sc[m] += comA[d]*pbc->box[d][m];
1399 comB_sc[m] += comB[d]*pbc->box[d][m];
1407 for(i=0; (i<nbonds); )
1409 type = forceatoms[i++];
1410 ai = forceatoms[i++];
1411 pr = &forceparams[type];
1413 for(m=0; m<DIM; m++)
1415 posA = forceparams[type].posres.pos0A[m];
1416 posB = forceparams[type].posres.pos0B[m];
1419 switch (refcoord_scaling)
1423 rdist[m] = L1*posA + lambda*posB;
1424 dpdl[m] = posB - posA;
1427 /* Box relative coordinates are stored for dimensions with pbc */
1428 posA *= pbc->box[m][m];
1429 posB *= pbc->box[m][m];
1430 for(d=m+1; d<npbcdim; d++)
1432 posA += forceparams[type].posres.pos0A[d]*pbc->box[d][m];
1433 posB += forceparams[type].posres.pos0B[d]*pbc->box[d][m];
1435 ref = L1*posA + lambda*posB;
1437 dpdl[m] = posB - posA;
1440 ref = L1*comA_sc[m] + lambda*comB_sc[m];
1441 rdist[m] = L1*posA + lambda*posB;
1442 dpdl[m] = comB_sc[m] - comA_sc[m] + posB - posA;
1448 ref = L1*posA + lambda*posB;
1450 dpdl[m] = posB - posA;
1453 /* We do pbc_dx with ref+rdist,
1454 * since with only ref we can be up to half a box vector wrong.
1456 pos[m] = ref + rdist[m];
1461 pbc_dx(pbc,x[ai],pos,dx);
1465 rvec_sub(x[ai],pos,dx);
1468 for (m=0; (m<DIM); m++)
1470 kk = L1*pr->posres.fcA[m] + lambda*pr->posres.fcB[m];
1473 vtot += 0.5*kk*dx[m]*dx[m];
1475 0.5*(pr->posres.fcB[m] - pr->posres.fcA[m])*dx[m]*dx[m]
1478 /* Here we correct for the pbc_dx which included rdist */
1479 vir_diag[m] -= 0.5*(dx[m] + rdist[m])*fm;
1486 static real low_angres(int nbonds,
1487 const t_iatom forceatoms[],const t_iparams forceparams[],
1488 const rvec x[],rvec f[],rvec fshift[],
1489 const t_pbc *pbc,const t_graph *g,
1490 real lambda,real *dvdlambda,
1493 int i,m,type,ai,aj,ak,al;
1495 real phi,cos_phi,cos_phi2,vid,vtot,dVdphi;
1496 rvec r_ij,r_kl,f_i,f_k={0,0,0};
1497 real st,sth,nrij2,nrkl2,c,cij,ckl;
1500 t2 = 0; /* avoid warning with gcc-3.3. It is never used uninitialized */
1503 ak=al=0; /* to avoid warnings */
1504 for(i=0; i<nbonds; ) {
1505 type = forceatoms[i++];
1506 ai = forceatoms[i++];
1507 aj = forceatoms[i++];
1508 t1 = pbc_rvec_sub(pbc,x[aj],x[ai],r_ij); /* 3 */
1510 ak = forceatoms[i++];
1511 al = forceatoms[i++];
1512 t2 = pbc_rvec_sub(pbc,x[al],x[ak],r_kl); /* 3 */
1519 cos_phi = cos_angle(r_ij,r_kl); /* 25 */
1520 phi = acos(cos_phi); /* 10 */
1522 *dvdlambda += dopdihs_min(forceparams[type].pdihs.cpA,
1523 forceparams[type].pdihs.cpB,
1524 forceparams[type].pdihs.phiA,
1525 forceparams[type].pdihs.phiB,
1526 forceparams[type].pdihs.mult,
1527 phi,lambda,&vid,&dVdphi); /* 40 */
1531 cos_phi2 = sqr(cos_phi); /* 1 */
1533 st = -dVdphi*gmx_invsqrt(1 - cos_phi2); /* 12 */
1534 sth = st*cos_phi; /* 1 */
1535 nrij2 = iprod(r_ij,r_ij); /* 5 */
1536 nrkl2 = iprod(r_kl,r_kl); /* 5 */
1538 c = st*gmx_invsqrt(nrij2*nrkl2); /* 11 */
1539 cij = sth/nrij2; /* 10 */
1540 ckl = sth/nrkl2; /* 10 */
1542 for (m=0; m<DIM; m++) { /* 18+18 */
1543 f_i[m] = (c*r_kl[m]-cij*r_ij[m]);
1547 f_k[m] = (c*r_ij[m]-ckl*r_kl[m]);
1554 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
1557 rvec_inc(fshift[t1],f_i);
1558 rvec_dec(fshift[CENTRAL],f_i);
1561 ivec_sub(SHIFT_IVEC(g,ak),SHIFT_IVEC(g,al),dt);
1564 rvec_inc(fshift[t2],f_k);
1565 rvec_dec(fshift[CENTRAL],f_k);
1570 return vtot; /* 184 / 157 (bZAxis) total */
1573 real angres(int nbonds,
1574 const t_iatom forceatoms[],const t_iparams forceparams[],
1575 const rvec x[],rvec f[],rvec fshift[],
1576 const t_pbc *pbc,const t_graph *g,
1577 real lambda,real *dvdlambda,
1578 const t_mdatoms *md,t_fcdata *fcd,
1579 int *global_atom_index)
1581 return low_angres(nbonds,forceatoms,forceparams,x,f,fshift,pbc,g,
1582 lambda,dvdlambda,FALSE);
1585 real angresz(int nbonds,
1586 const t_iatom forceatoms[],const t_iparams forceparams[],
1587 const rvec x[],rvec f[],rvec fshift[],
1588 const t_pbc *pbc,const t_graph *g,
1589 real lambda,real *dvdlambda,
1590 const t_mdatoms *md,t_fcdata *fcd,
1591 int *global_atom_index)
1593 return low_angres(nbonds,forceatoms,forceparams,x,f,fshift,pbc,g,
1594 lambda,dvdlambda,TRUE);
1598 real unimplemented(int nbonds,
1599 const t_iatom forceatoms[],const t_iparams forceparams[],
1600 const rvec x[],rvec f[],rvec fshift[],
1601 const t_pbc *pbc,const t_graph *g,
1602 real lambda,real *dvdlambda,
1603 const t_mdatoms *md,t_fcdata *fcd,
1604 int *global_atom_index)
1606 gmx_impl("*** you are using a not implemented function");
1608 return 0.0; /* To make the compiler happy */
1611 real rbdihs(int nbonds,
1612 const t_iatom forceatoms[],const t_iparams forceparams[],
1613 const rvec x[],rvec f[],rvec fshift[],
1614 const t_pbc *pbc,const t_graph *g,
1615 real lambda,real *dvdlambda,
1616 const t_mdatoms *md,t_fcdata *fcd,
1617 int *global_atom_index)
1619 const real c0=0.0,c1=1.0,c2=2.0,c3=3.0,c4=4.0,c5=5.0;
1620 int type,ai,aj,ak,al,i,j;
1622 rvec r_ij,r_kj,r_kl,m,n;
1623 real parmA[NR_RBDIHS];
1624 real parmB[NR_RBDIHS];
1625 real parm[NR_RBDIHS];
1626 real cos_phi,phi,rbp,rbpBA;
1627 real v,sign,ddphi,sin_phi;
1629 real L1 = 1.0-lambda;
1633 for(i=0; (i<nbonds); ) {
1634 type = forceatoms[i++];
1635 ai = forceatoms[i++];
1636 aj = forceatoms[i++];
1637 ak = forceatoms[i++];
1638 al = forceatoms[i++];
1640 phi=dih_angle(x[ai],x[aj],x[ak],x[al],pbc,r_ij,r_kj,r_kl,m,n,
1641 &sign,&t1,&t2,&t3); /* 84 */
1643 /* Change to polymer convention */
1647 phi -= M_PI; /* 1 */
1650 /* Beware of accuracy loss, cannot use 1-sqrt(cos^2) ! */
1653 for(j=0; (j<NR_RBDIHS); j++) {
1654 parmA[j] = forceparams[type].rbdihs.rbcA[j];
1655 parmB[j] = forceparams[type].rbdihs.rbcB[j];
1656 parm[j] = L1*parmA[j]+lambda*parmB[j];
1658 /* Calculate cosine powers */
1659 /* Calculate the energy */
1660 /* Calculate the derivative */
1663 dvdl += (parmB[0]-parmA[0]);
1668 rbpBA = parmB[1]-parmA[1];
1669 ddphi += rbp*cosfac;
1672 dvdl += cosfac*rbpBA;
1674 rbpBA = parmB[2]-parmA[2];
1675 ddphi += c2*rbp*cosfac;
1678 dvdl += cosfac*rbpBA;
1680 rbpBA = parmB[3]-parmA[3];
1681 ddphi += c3*rbp*cosfac;
1684 dvdl += cosfac*rbpBA;
1686 rbpBA = parmB[4]-parmA[4];
1687 ddphi += c4*rbp*cosfac;
1690 dvdl += cosfac*rbpBA;
1692 rbpBA = parmB[5]-parmA[5];
1693 ddphi += c5*rbp*cosfac;
1696 dvdl += cosfac*rbpBA;
1698 ddphi = -ddphi*sin_phi; /* 11 */
1700 do_dih_fup(ai,aj,ak,al,ddphi,r_ij,r_kj,r_kl,m,n,
1701 f,fshift,pbc,g,x,t1,t2,t3); /* 112 */
1709 int cmap_setup_grid_index(int ip, int grid_spacing, int *ipm1, int *ipp1, int *ipp2)
1715 ip = ip + grid_spacing - 1;
1717 else if(ip > grid_spacing)
1719 ip = ip - grid_spacing - 1;
1728 im1 = grid_spacing - 1;
1730 else if(ip == grid_spacing-2)
1734 else if(ip == grid_spacing-1)
1748 real cmap_dihs(int nbonds,
1749 const t_iatom forceatoms[],const t_iparams forceparams[],
1750 const gmx_cmap_t *cmap_grid,
1751 const rvec x[],rvec f[],rvec fshift[],
1752 const t_pbc *pbc,const t_graph *g,
1753 real lambda,real *dvdlambda,
1754 const t_mdatoms *md,t_fcdata *fcd,
1755 int *global_atom_index)
1759 int a1i,a1j,a1k,a1l,a2i,a2j,a2k,a2l;
1761 int t11,t21,t31,t12,t22,t32;
1762 int iphi1,ip1m1,ip1p1,ip1p2;
1763 int iphi2,ip2m1,ip2p1,ip2p2;
1765 int pos1,pos2,pos3,pos4,tmp;
1767 real ty[4],ty1[4],ty2[4],ty12[4],tc[16],tx[16];
1768 real phi1,psi1,cos_phi1,sin_phi1,sign1,xphi1;
1769 real phi2,psi2,cos_phi2,sin_phi2,sign2,xphi2;
1770 real dx,xx,tt,tu,e,df1,df2,ddf1,ddf2,ddf12,vtot;
1771 real ra21,rb21,rg21,rg1,rgr1,ra2r1,rb2r1,rabr1;
1772 real ra22,rb22,rg22,rg2,rgr2,ra2r2,rb2r2,rabr2;
1773 real fg1,hg1,fga1,hgb1,gaa1,gbb1;
1774 real fg2,hg2,fga2,hgb2,gaa2,gbb2;
1777 rvec r1_ij, r1_kj, r1_kl,m1,n1;
1778 rvec r2_ij, r2_kj, r2_kl,m2,n2;
1779 rvec f1_i,f1_j,f1_k,f1_l;
1780 rvec f2_i,f2_j,f2_k,f2_l;
1782 rvec f1,g1,h1,f2,g2,h2;
1783 rvec dtf1,dtg1,dth1,dtf2,dtg2,dth2;
1784 ivec jt1,dt1_ij,dt1_kj,dt1_lj;
1785 ivec jt2,dt2_ij,dt2_kj,dt2_lj;
1789 int loop_index[4][4] = {
1796 /* Total CMAP energy */
1801 /* Five atoms are involved in the two torsions */
1802 type = forceatoms[n++];
1803 ai = forceatoms[n++];
1804 aj = forceatoms[n++];
1805 ak = forceatoms[n++];
1806 al = forceatoms[n++];
1807 am = forceatoms[n++];
1809 /* Which CMAP type is this */
1810 cmapA = forceparams[type].cmap.cmapA;
1811 cmapd = cmap_grid->cmapdata[cmapA].cmap;
1819 phi1 = dih_angle(x[a1i], x[a1j], x[a1k], x[a1l], pbc, r1_ij, r1_kj, r1_kl, m1, n1,
1820 &sign1, &t11, &t21, &t31); /* 84 */
1822 cos_phi1 = cos(phi1);
1824 a1[0] = r1_ij[1]*r1_kj[2]-r1_ij[2]*r1_kj[1];
1825 a1[1] = r1_ij[2]*r1_kj[0]-r1_ij[0]*r1_kj[2];
1826 a1[2] = r1_ij[0]*r1_kj[1]-r1_ij[1]*r1_kj[0]; /* 9 */
1828 b1[0] = r1_kl[1]*r1_kj[2]-r1_kl[2]*r1_kj[1];
1829 b1[1] = r1_kl[2]*r1_kj[0]-r1_kl[0]*r1_kj[2];
1830 b1[2] = r1_kl[0]*r1_kj[1]-r1_kl[1]*r1_kj[0]; /* 9 */
1832 tmp = pbc_rvec_sub(pbc,x[a1l],x[a1k],h1);
1834 ra21 = iprod(a1,a1); /* 5 */
1835 rb21 = iprod(b1,b1); /* 5 */
1836 rg21 = iprod(r1_kj,r1_kj); /* 5 */
1842 rabr1 = sqrt(ra2r1*rb2r1);
1844 sin_phi1 = rg1 * rabr1 * iprod(a1,h1) * (-1);
1846 if(cos_phi1 < -0.5 || cos_phi1 > 0.5)
1848 phi1 = asin(sin_phi1);
1858 phi1 = -M_PI - phi1;
1864 phi1 = acos(cos_phi1);
1872 xphi1 = phi1 + M_PI; /* 1 */
1874 /* Second torsion */
1880 phi2 = dih_angle(x[a2i], x[a2j], x[a2k], x[a2l], pbc, r2_ij, r2_kj, r2_kl, m2, n2,
1881 &sign2, &t12, &t22, &t32); /* 84 */
1883 cos_phi2 = cos(phi2);
1885 a2[0] = r2_ij[1]*r2_kj[2]-r2_ij[2]*r2_kj[1];
1886 a2[1] = r2_ij[2]*r2_kj[0]-r2_ij[0]*r2_kj[2];
1887 a2[2] = r2_ij[0]*r2_kj[1]-r2_ij[1]*r2_kj[0]; /* 9 */
1889 b2[0] = r2_kl[1]*r2_kj[2]-r2_kl[2]*r2_kj[1];
1890 b2[1] = r2_kl[2]*r2_kj[0]-r2_kl[0]*r2_kj[2];
1891 b2[2] = r2_kl[0]*r2_kj[1]-r2_kl[1]*r2_kj[0]; /* 9 */
1893 tmp = pbc_rvec_sub(pbc,x[a2l],x[a2k],h2);
1895 ra22 = iprod(a2,a2); /* 5 */
1896 rb22 = iprod(b2,b2); /* 5 */
1897 rg22 = iprod(r2_kj,r2_kj); /* 5 */
1903 rabr2 = sqrt(ra2r2*rb2r2);
1905 sin_phi2 = rg2 * rabr2 * iprod(a2,h2) * (-1);
1907 if(cos_phi2 < -0.5 || cos_phi2 > 0.5)
1909 phi2 = asin(sin_phi2);
1919 phi2 = -M_PI - phi2;
1925 phi2 = acos(cos_phi2);
1933 xphi2 = phi2 + M_PI; /* 1 */
1935 /* Range mangling */
1938 xphi1 = xphi1 + 2*M_PI;
1940 else if(xphi1>=2*M_PI)
1942 xphi1 = xphi1 - 2*M_PI;
1947 xphi2 = xphi2 + 2*M_PI;
1949 else if(xphi2>=2*M_PI)
1951 xphi2 = xphi2 - 2*M_PI;
1954 /* Number of grid points */
1955 dx = 2*M_PI / cmap_grid->grid_spacing;
1957 /* Where on the grid are we */
1958 iphi1 = (int)(xphi1/dx);
1959 iphi2 = (int)(xphi2/dx);
1961 iphi1 = cmap_setup_grid_index(iphi1, cmap_grid->grid_spacing, &ip1m1,&ip1p1,&ip1p2);
1962 iphi2 = cmap_setup_grid_index(iphi2, cmap_grid->grid_spacing, &ip2m1,&ip2p1,&ip2p2);
1964 pos1 = iphi1*cmap_grid->grid_spacing+iphi2;
1965 pos2 = ip1p1*cmap_grid->grid_spacing+iphi2;
1966 pos3 = ip1p1*cmap_grid->grid_spacing+ip2p1;
1967 pos4 = iphi1*cmap_grid->grid_spacing+ip2p1;
1969 ty[0] = cmapd[pos1*4];
1970 ty[1] = cmapd[pos2*4];
1971 ty[2] = cmapd[pos3*4];
1972 ty[3] = cmapd[pos4*4];
1974 ty1[0] = cmapd[pos1*4+1];
1975 ty1[1] = cmapd[pos2*4+1];
1976 ty1[2] = cmapd[pos3*4+1];
1977 ty1[3] = cmapd[pos4*4+1];
1979 ty2[0] = cmapd[pos1*4+2];
1980 ty2[1] = cmapd[pos2*4+2];
1981 ty2[2] = cmapd[pos3*4+2];
1982 ty2[3] = cmapd[pos4*4+2];
1984 ty12[0] = cmapd[pos1*4+3];
1985 ty12[1] = cmapd[pos2*4+3];
1986 ty12[2] = cmapd[pos3*4+3];
1987 ty12[3] = cmapd[pos4*4+3];
1989 /* Switch to degrees */
1990 dx = 360.0 / cmap_grid->grid_spacing;
1991 xphi1 = xphi1 * RAD2DEG;
1992 xphi2 = xphi2 * RAD2DEG;
1994 for(i=0;i<4;i++) /* 16 */
1997 tx[i+4] = ty1[i]*dx;
1998 tx[i+8] = ty2[i]*dx;
1999 tx[i+12] = ty12[i]*dx*dx;
2003 for(i=0;i<4;i++) /* 1056 */
2010 xx = xx + cmap_coeff_matrix[k*16+idx]*tx[k];
2018 tt = (xphi1-iphi1*dx)/dx;
2019 tu = (xphi2-iphi2*dx)/dx;
2030 l1 = loop_index[i][3];
2031 l2 = loop_index[i][2];
2032 l3 = loop_index[i][1];
2034 e = tt * e + ((tc[i*4+3]*tu+tc[i*4+2])*tu + tc[i*4+1])*tu+tc[i*4];
2035 df1 = tu * df1 + (3.0*tc[l1]*tt+2.0*tc[l2])*tt+tc[l3];
2036 df2 = tt * df2 + (3.0*tc[i*4+3]*tu+2.0*tc[i*4+2])*tu+tc[i*4+1];
2037 ddf1 = tu * ddf1 + 2.0*3.0*tc[l1]*tt+2.0*tc[l2];
2038 ddf2 = tt * ddf2 + 2.0*3.0*tc[4*i+3]*tu+2.0*tc[4*i+2];
2041 ddf12 = tc[5] + 2.0*tc[9]*tt + 3.0*tc[13]*tt*tt + 2.0*tu*(tc[6]+2.0*tc[10]*tt+3.0*tc[14]*tt*tt) +
2042 3.0*tu*tu*(tc[7]+2.0*tc[11]*tt+3.0*tc[15]*tt*tt);
2047 ddf1 = ddf1 * fac * fac;
2048 ddf2 = ddf2 * fac * fac;
2049 ddf12 = ddf12 * fac * fac;
2054 /* Do forces - first torsion */
2055 fg1 = iprod(r1_ij,r1_kj);
2056 hg1 = iprod(r1_kl,r1_kj);
2057 fga1 = fg1*ra2r1*rgr1;
2058 hgb1 = hg1*rb2r1*rgr1;
2064 dtf1[i] = gaa1 * a1[i];
2065 dtg1[i] = fga1 * a1[i] - hgb1 * b1[i];
2066 dth1[i] = gbb1 * b1[i];
2068 f1[i] = df1 * dtf1[i];
2069 g1[i] = df1 * dtg1[i];
2070 h1[i] = df1 * dth1[i];
2073 f1_j[i] = -f1[i] - g1[i];
2074 f1_k[i] = h1[i] + g1[i];
2077 f[a1i][i] = f[a1i][i] + f1_i[i];
2078 f[a1j][i] = f[a1j][i] + f1_j[i]; /* - f1[i] - g1[i] */
2079 f[a1k][i] = f[a1k][i] + f1_k[i]; /* h1[i] + g1[i] */
2080 f[a1l][i] = f[a1l][i] + f1_l[i]; /* h1[i] */
2083 /* Do forces - second torsion */
2084 fg2 = iprod(r2_ij,r2_kj);
2085 hg2 = iprod(r2_kl,r2_kj);
2086 fga2 = fg2*ra2r2*rgr2;
2087 hgb2 = hg2*rb2r2*rgr2;
2093 dtf2[i] = gaa2 * a2[i];
2094 dtg2[i] = fga2 * a2[i] - hgb2 * b2[i];
2095 dth2[i] = gbb2 * b2[i];
2097 f2[i] = df2 * dtf2[i];
2098 g2[i] = df2 * dtg2[i];
2099 h2[i] = df2 * dth2[i];
2102 f2_j[i] = -f2[i] - g2[i];
2103 f2_k[i] = h2[i] + g2[i];
2106 f[a2i][i] = f[a2i][i] + f2_i[i]; /* f2[i] */
2107 f[a2j][i] = f[a2j][i] + f2_j[i]; /* - f2[i] - g2[i] */
2108 f[a2k][i] = f[a2k][i] + f2_k[i]; /* h2[i] + g2[i] */
2109 f[a2l][i] = f[a2l][i] + f2_l[i]; /* - h2[i] */
2115 copy_ivec(SHIFT_IVEC(g,a1j), jt1);
2116 ivec_sub(SHIFT_IVEC(g,a1i), jt1,dt1_ij);
2117 ivec_sub(SHIFT_IVEC(g,a1k), jt1,dt1_kj);
2118 ivec_sub(SHIFT_IVEC(g,a1l), jt1,dt1_lj);
2119 t11 = IVEC2IS(dt1_ij);
2120 t21 = IVEC2IS(dt1_kj);
2121 t31 = IVEC2IS(dt1_lj);
2123 copy_ivec(SHIFT_IVEC(g,a2j), jt2);
2124 ivec_sub(SHIFT_IVEC(g,a2i), jt2,dt2_ij);
2125 ivec_sub(SHIFT_IVEC(g,a2k), jt2,dt2_kj);
2126 ivec_sub(SHIFT_IVEC(g,a2l), jt2,dt2_lj);
2127 t12 = IVEC2IS(dt2_ij);
2128 t22 = IVEC2IS(dt2_kj);
2129 t32 = IVEC2IS(dt2_lj);
2133 t31 = pbc_rvec_sub(pbc,x[a1l],x[a1j],h1);
2134 t32 = pbc_rvec_sub(pbc,x[a2l],x[a2j],h2);
2142 rvec_inc(fshift[t11],f1_i);
2143 rvec_inc(fshift[CENTRAL],f1_j);
2144 rvec_inc(fshift[t21],f1_k);
2145 rvec_inc(fshift[t31],f1_l);
2147 rvec_inc(fshift[t21],f2_i);
2148 rvec_inc(fshift[CENTRAL],f2_j);
2149 rvec_inc(fshift[t22],f2_k);
2150 rvec_inc(fshift[t32],f2_l);
2157 /***********************************************************
2159 * G R O M O S 9 6 F U N C T I O N S
2161 ***********************************************************/
2162 real g96harmonic(real kA,real kB,real xA,real xB,real x,real lambda,
2165 const real half=0.5;
2166 real L1,kk,x0,dx,dx2;
2170 kk = L1*kA+lambda*kB;
2171 x0 = L1*xA+lambda*xB;
2178 dvdl = half*(kB-kA)*dx2 + (xA-xB)*kk*dx;
2185 /* That was 21 flops */
2188 real g96bonds(int nbonds,
2189 const t_iatom forceatoms[],const t_iparams forceparams[],
2190 const rvec x[],rvec f[],rvec fshift[],
2191 const t_pbc *pbc,const t_graph *g,
2192 real lambda,real *dvdlambda,
2193 const t_mdatoms *md,t_fcdata *fcd,
2194 int *global_atom_index)
2196 int i,m,ki,ai,aj,type;
2197 real dr2,fbond,vbond,fij,vtot;
2202 for(i=0; (i<nbonds); ) {
2203 type = forceatoms[i++];
2204 ai = forceatoms[i++];
2205 aj = forceatoms[i++];
2207 ki = pbc_rvec_sub(pbc,x[ai],x[aj],dx); /* 3 */
2208 dr2 = iprod(dx,dx); /* 5 */
2210 *dvdlambda += g96harmonic(forceparams[type].harmonic.krA,
2211 forceparams[type].harmonic.krB,
2212 forceparams[type].harmonic.rA,
2213 forceparams[type].harmonic.rB,
2214 dr2,lambda,&vbond,&fbond);
2216 vtot += 0.5*vbond; /* 1*/
2219 fprintf(debug,"G96-BONDS: dr = %10g vbond = %10g fbond = %10g\n",
2220 sqrt(dr2),vbond,fbond);
2224 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
2227 for (m=0; (m<DIM); m++) { /* 15 */
2232 fshift[CENTRAL][m]-=fij;
2238 real g96bond_angle(const rvec xi,const rvec xj,const rvec xk,const t_pbc *pbc,
2239 rvec r_ij,rvec r_kj,
2241 /* Return value is the angle between the bonds i-j and j-k */
2245 *t1 = pbc_rvec_sub(pbc,xi,xj,r_ij); /* 3 */
2246 *t2 = pbc_rvec_sub(pbc,xk,xj,r_kj); /* 3 */
2248 costh=cos_angle(r_ij,r_kj); /* 25 */
2253 real g96angles(int nbonds,
2254 const t_iatom forceatoms[],const t_iparams forceparams[],
2255 const rvec x[],rvec f[],rvec fshift[],
2256 const t_pbc *pbc,const t_graph *g,
2257 real lambda,real *dvdlambda,
2258 const t_mdatoms *md,t_fcdata *fcd,
2259 int *global_atom_index)
2261 int i,ai,aj,ak,type,m,t1,t2;
2263 real cos_theta,dVdt,va,vtot;
2264 real rij_1,rij_2,rkj_1,rkj_2,rijrkj_1;
2266 ivec jt,dt_ij,dt_kj;
2269 for(i=0; (i<nbonds); ) {
2270 type = forceatoms[i++];
2271 ai = forceatoms[i++];
2272 aj = forceatoms[i++];
2273 ak = forceatoms[i++];
2275 cos_theta = g96bond_angle(x[ai],x[aj],x[ak],pbc,r_ij,r_kj,&t1,&t2);
2277 *dvdlambda += g96harmonic(forceparams[type].harmonic.krA,
2278 forceparams[type].harmonic.krB,
2279 forceparams[type].harmonic.rA,
2280 forceparams[type].harmonic.rB,
2281 cos_theta,lambda,&va,&dVdt);
2284 rij_1 = gmx_invsqrt(iprod(r_ij,r_ij));
2285 rkj_1 = gmx_invsqrt(iprod(r_kj,r_kj));
2286 rij_2 = rij_1*rij_1;
2287 rkj_2 = rkj_1*rkj_1;
2288 rijrkj_1 = rij_1*rkj_1; /* 23 */
2292 fprintf(debug,"G96ANGLES: costheta = %10g vth = %10g dV/dct = %10g\n",
2295 for (m=0; (m<DIM); m++) { /* 42 */
2296 f_i[m]=dVdt*(r_kj[m]*rijrkj_1 - r_ij[m]*rij_2*cos_theta);
2297 f_k[m]=dVdt*(r_ij[m]*rijrkj_1 - r_kj[m]*rkj_2*cos_theta);
2298 f_j[m]=-f_i[m]-f_k[m];
2305 copy_ivec(SHIFT_IVEC(g,aj),jt);
2307 ivec_sub(SHIFT_IVEC(g,ai),jt,dt_ij);
2308 ivec_sub(SHIFT_IVEC(g,ak),jt,dt_kj);
2312 rvec_inc(fshift[t1],f_i);
2313 rvec_inc(fshift[CENTRAL],f_j);
2314 rvec_inc(fshift[t2],f_k); /* 9 */
2320 real cross_bond_bond(int nbonds,
2321 const t_iatom forceatoms[],const t_iparams forceparams[],
2322 const rvec x[],rvec f[],rvec fshift[],
2323 const t_pbc *pbc,const t_graph *g,
2324 real lambda,real *dvdlambda,
2325 const t_mdatoms *md,t_fcdata *fcd,
2326 int *global_atom_index)
2328 /* Potential from Lawrence and Skimmer, Chem. Phys. Lett. 372 (2003)
2331 int i,ai,aj,ak,type,m,t1,t2;
2333 real vtot,vrr,s1,s2,r1,r2,r1e,r2e,krr;
2335 ivec jt,dt_ij,dt_kj;
2338 for(i=0; (i<nbonds); ) {
2339 type = forceatoms[i++];
2340 ai = forceatoms[i++];
2341 aj = forceatoms[i++];
2342 ak = forceatoms[i++];
2343 r1e = forceparams[type].cross_bb.r1e;
2344 r2e = forceparams[type].cross_bb.r2e;
2345 krr = forceparams[type].cross_bb.krr;
2347 /* Compute distance vectors ... */
2348 t1 = pbc_rvec_sub(pbc,x[ai],x[aj],r_ij);
2349 t2 = pbc_rvec_sub(pbc,x[ak],x[aj],r_kj);
2351 /* ... and their lengths */
2355 /* Deviations from ideality */
2359 /* Energy (can be negative!) */
2364 svmul(-krr*s2/r1,r_ij,f_i);
2365 svmul(-krr*s1/r2,r_kj,f_k);
2367 for (m=0; (m<DIM); m++) { /* 12 */
2368 f_j[m] = -f_i[m] - f_k[m];
2376 copy_ivec(SHIFT_IVEC(g,aj),jt);
2378 ivec_sub(SHIFT_IVEC(g,ai),jt,dt_ij);
2379 ivec_sub(SHIFT_IVEC(g,ak),jt,dt_kj);
2383 rvec_inc(fshift[t1],f_i);
2384 rvec_inc(fshift[CENTRAL],f_j);
2385 rvec_inc(fshift[t2],f_k); /* 9 */
2391 real cross_bond_angle(int nbonds,
2392 const t_iatom forceatoms[],const t_iparams forceparams[],
2393 const rvec x[],rvec f[],rvec fshift[],
2394 const t_pbc *pbc,const t_graph *g,
2395 real lambda,real *dvdlambda,
2396 const t_mdatoms *md,t_fcdata *fcd,
2397 int *global_atom_index)
2399 /* Potential from Lawrence and Skimmer, Chem. Phys. Lett. 372 (2003)
2402 int i,ai,aj,ak,type,m,t1,t2,t3;
2403 rvec r_ij,r_kj,r_ik;
2404 real vtot,vrt,s1,s2,s3,r1,r2,r3,r1e,r2e,r3e,krt,k1,k2,k3;
2406 ivec jt,dt_ij,dt_kj;
2409 for(i=0; (i<nbonds); ) {
2410 type = forceatoms[i++];
2411 ai = forceatoms[i++];
2412 aj = forceatoms[i++];
2413 ak = forceatoms[i++];
2414 r1e = forceparams[type].cross_ba.r1e;
2415 r2e = forceparams[type].cross_ba.r2e;
2416 r3e = forceparams[type].cross_ba.r3e;
2417 krt = forceparams[type].cross_ba.krt;
2419 /* Compute distance vectors ... */
2420 t1 = pbc_rvec_sub(pbc,x[ai],x[aj],r_ij);
2421 t2 = pbc_rvec_sub(pbc,x[ak],x[aj],r_kj);
2422 t3 = pbc_rvec_sub(pbc,x[ai],x[ak],r_ik);
2424 /* ... and their lengths */
2429 /* Deviations from ideality */
2434 /* Energy (can be negative!) */
2435 vrt = krt*s3*(s1+s2);
2441 k3 = -krt*(s1+s2)/r3;
2442 for(m=0; (m<DIM); m++) {
2443 f_i[m] = k1*r_ij[m] + k3*r_ik[m];
2444 f_k[m] = k2*r_kj[m] - k3*r_ik[m];
2445 f_j[m] = -f_i[m] - f_k[m];
2448 for (m=0; (m<DIM); m++) { /* 12 */
2456 copy_ivec(SHIFT_IVEC(g,aj),jt);
2458 ivec_sub(SHIFT_IVEC(g,ai),jt,dt_ij);
2459 ivec_sub(SHIFT_IVEC(g,ak),jt,dt_kj);
2463 rvec_inc(fshift[t1],f_i);
2464 rvec_inc(fshift[CENTRAL],f_j);
2465 rvec_inc(fshift[t2],f_k); /* 9 */
2471 static real bonded_tab(const char *type,int table_nr,
2472 const bondedtable_t *table,real kA,real kB,real r,
2473 real lambda,real *V,real *F)
2475 real k,tabscale,*VFtab,rt,eps,eps2,Yt,Ft,Geps,Heps2,Fp,VV,FF;
2479 k = (1.0 - lambda)*kA + lambda*kB;
2481 tabscale = table->scale;
2486 if (n0 >= table->n) {
2487 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",
2488 type,table_nr,r,n0,n0+1,table->n);
2495 Geps = VFtab[nnn+2]*eps;
2496 Heps2 = VFtab[nnn+3]*eps2;
2497 Fp = Ft + Geps + Heps2;
2499 FF = Fp + Geps + 2.0*Heps2;
2501 *F = -k*FF*tabscale;
2503 dvdl = (kB - kA)*VV;
2507 /* That was 22 flops */
2510 real tab_bonds(int nbonds,
2511 const t_iatom forceatoms[],const t_iparams forceparams[],
2512 const rvec x[],rvec f[],rvec fshift[],
2513 const t_pbc *pbc,const t_graph *g,
2514 real lambda,real *dvdlambda,
2515 const t_mdatoms *md,t_fcdata *fcd,
2516 int *global_atom_index)
2518 int i,m,ki,ai,aj,type,table;
2519 real dr,dr2,fbond,vbond,fij,vtot;
2524 for(i=0; (i<nbonds); ) {
2525 type = forceatoms[i++];
2526 ai = forceatoms[i++];
2527 aj = forceatoms[i++];
2529 ki = pbc_rvec_sub(pbc,x[ai],x[aj],dx); /* 3 */
2530 dr2 = iprod(dx,dx); /* 5 */
2531 dr = dr2*gmx_invsqrt(dr2); /* 10 */
2533 table = forceparams[type].tab.table;
2535 *dvdlambda += bonded_tab("bond",table,
2536 &fcd->bondtab[table],
2537 forceparams[type].tab.kA,
2538 forceparams[type].tab.kB,
2539 dr,lambda,&vbond,&fbond); /* 22 */
2545 vtot += vbond;/* 1*/
2546 fbond *= gmx_invsqrt(dr2); /* 6 */
2549 fprintf(debug,"TABBONDS: dr = %10g vbond = %10g fbond = %10g\n",
2553 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
2556 for (m=0; (m<DIM); m++) { /* 15 */
2561 fshift[CENTRAL][m]-=fij;
2567 real tab_angles(int nbonds,
2568 const t_iatom forceatoms[],const t_iparams forceparams[],
2569 const rvec x[],rvec f[],rvec fshift[],
2570 const t_pbc *pbc,const t_graph *g,
2571 real lambda,real *dvdlambda,
2572 const t_mdatoms *md,t_fcdata *fcd,
2573 int *global_atom_index)
2575 int i,ai,aj,ak,t1,t2,type,table;
2577 real cos_theta,cos_theta2,theta,dVdt,va,vtot;
2578 ivec jt,dt_ij,dt_kj;
2581 for(i=0; (i<nbonds); ) {
2582 type = forceatoms[i++];
2583 ai = forceatoms[i++];
2584 aj = forceatoms[i++];
2585 ak = forceatoms[i++];
2587 theta = bond_angle(x[ai],x[aj],x[ak],pbc,
2588 r_ij,r_kj,&cos_theta,&t1,&t2); /* 41 */
2590 table = forceparams[type].tab.table;
2592 *dvdlambda += bonded_tab("angle",table,
2593 &fcd->angletab[table],
2594 forceparams[type].tab.kA,
2595 forceparams[type].tab.kB,
2596 theta,lambda,&va,&dVdt); /* 22 */
2599 cos_theta2 = sqr(cos_theta); /* 1 */
2600 if (cos_theta2 < 1) {
2607 st = dVdt*gmx_invsqrt(1 - cos_theta2); /* 12 */
2608 sth = st*cos_theta; /* 1 */
2611 fprintf(debug,"ANGLES: theta = %10g vth = %10g dV/dtheta = %10g\n",
2612 theta*RAD2DEG,va,dVdt);
2614 nrkj2=iprod(r_kj,r_kj); /* 5 */
2615 nrij2=iprod(r_ij,r_ij);
2617 cik=st*gmx_invsqrt(nrkj2*nrij2); /* 12 */
2618 cii=sth/nrij2; /* 10 */
2619 ckk=sth/nrkj2; /* 10 */
2621 for (m=0; (m<DIM); m++) { /* 39 */
2622 f_i[m]=-(cik*r_kj[m]-cii*r_ij[m]);
2623 f_k[m]=-(cik*r_ij[m]-ckk*r_kj[m]);
2624 f_j[m]=-f_i[m]-f_k[m];
2630 copy_ivec(SHIFT_IVEC(g,aj),jt);
2632 ivec_sub(SHIFT_IVEC(g,ai),jt,dt_ij);
2633 ivec_sub(SHIFT_IVEC(g,ak),jt,dt_kj);
2637 rvec_inc(fshift[t1],f_i);
2638 rvec_inc(fshift[CENTRAL],f_j);
2639 rvec_inc(fshift[t2],f_k);
2645 real tab_dihs(int nbonds,
2646 const t_iatom forceatoms[],const t_iparams forceparams[],
2647 const rvec x[],rvec f[],rvec fshift[],
2648 const t_pbc *pbc,const t_graph *g,
2649 real lambda,real *dvdlambda,
2650 const t_mdatoms *md,t_fcdata *fcd,
2651 int *global_atom_index)
2653 int i,type,ai,aj,ak,al,table;
2655 rvec r_ij,r_kj,r_kl,m,n;
2656 real phi,sign,ddphi,vpd,vtot;
2659 for(i=0; (i<nbonds); ) {
2660 type = forceatoms[i++];
2661 ai = forceatoms[i++];
2662 aj = forceatoms[i++];
2663 ak = forceatoms[i++];
2664 al = forceatoms[i++];
2666 phi=dih_angle(x[ai],x[aj],x[ak],x[al],pbc,r_ij,r_kj,r_kl,m,n,
2667 &sign,&t1,&t2,&t3); /* 84 */
2669 table = forceparams[type].tab.table;
2671 /* Hopefully phi+M_PI never results in values < 0 */
2672 *dvdlambda += bonded_tab("dihedral",table,
2673 &fcd->dihtab[table],
2674 forceparams[type].tab.kA,
2675 forceparams[type].tab.kB,
2676 phi+M_PI,lambda,&vpd,&ddphi);
2679 do_dih_fup(ai,aj,ak,al,-ddphi,r_ij,r_kj,r_kl,m,n,
2680 f,fshift,pbc,g,x,t1,t2,t3); /* 112 */
2683 fprintf(debug,"pdih: (%d,%d,%d,%d) phi=%g\n",
2691 void calc_bonds(FILE *fplog,const gmx_multisim_t *ms,
2693 rvec x[],history_t *hist,
2694 rvec f[],t_forcerec *fr,
2695 const t_pbc *pbc,const t_graph *g,
2696 gmx_enerdata_t *enerd,t_nrnb *nrnb,
2698 const t_mdatoms *md,
2699 t_fcdata *fcd,int *global_atom_index,
2700 t_atomtypes *atype, gmx_genborn_t *born,
2701 gmx_bool bPrintSepPot,gmx_large_int_t step)
2703 int ftype,nbonds,ind,nat1;
2705 const t_pbc *pbc_null;
2714 fprintf(fplog,"Step %s: bonded V and dVdl for this node\n",
2715 gmx_step_str(step,buf));
2719 p_graph(debug,"Bondage is fun",g);
2724 /* Do pre force calculation stuff which might require communication */
2725 if (idef->il[F_ORIRES].nr) {
2726 epot[F_ORIRESDEV] = calc_orires_dev(ms,idef->il[F_ORIRES].nr,
2727 idef->il[F_ORIRES].iatoms,
2728 idef->iparams,md,(const rvec*)x,
2731 if (idef->il[F_DISRES].nr) {
2732 calc_disres_R_6(ms,idef->il[F_DISRES].nr,
2733 idef->il[F_DISRES].iatoms,
2734 idef->iparams,(const rvec*)x,pbc_null,
2738 /* Loop over all bonded force types to calculate the bonded forces */
2739 for(ftype=0; (ftype<F_NRE); ftype++) {
2740 if(ftype<F_GB12 || ftype>F_GB14) {
2741 if ((interaction_function[ftype].flags & IF_BOND) &&
2742 !(ftype == F_CONNBONDS || ftype == F_POSRES)) {
2743 nbonds=idef->il[ftype].nr;
2745 ind = interaction_function[ftype].nrnb_ind;
2746 nat1 = interaction_function[ftype].nratoms + 1;
2748 if (ftype < F_LJ14 || ftype > F_LJC_PAIRS_NB) {
2751 v = cmap_dihs(nbonds,idef->il[ftype].iatoms,
2752 idef->iparams,&idef->cmap_grid,
2753 (const rvec*)x,f,fr->fshift,
2754 pbc_null,g,lambda,&dvdl,md,fcd,
2760 interaction_function[ftype].ifunc(nbonds,idef->il[ftype].iatoms,
2762 (const rvec*)x,f,fr->fshift,
2763 pbc_null,g,lambda,&dvdl,md,fcd,
2768 fprintf(fplog," %-23s #%4d V %12.5e dVdl %12.5e\n",
2769 interaction_function[ftype].longname,nbonds/nat1,v,dvdl);
2772 v = do_listed_vdw_q(ftype,nbonds,idef->il[ftype].iatoms,
2774 (const rvec*)x,f,fr->fshift,
2777 md,fr,&enerd->grpp,global_atom_index);
2779 fprintf(fplog," %-5s + %-15s #%4d dVdl %12.5e\n",
2780 interaction_function[ftype].longname,
2781 interaction_function[F_COUL14].longname,nbonds/nat1,dvdl);
2785 inc_nrnb(nrnb,ind,nbonds/nat1);
2787 enerd->dvdl_nonlin += dvdl;
2792 /* Copy the sum of violations for the distance restraints from fcd */
2794 epot[F_DISRESVIOL] = fcd->disres.sumviol;
2797 void calc_bonds_lambda(FILE *fplog,
2801 const t_pbc *pbc,const t_graph *g,
2802 gmx_enerdata_t *enerd,t_nrnb *nrnb,
2804 const t_mdatoms *md,
2805 t_fcdata *fcd,int *global_atom_index)
2807 int ftype,nbonds_np,nbonds,ind, nat1;
2809 rvec *f,*fshift_orig;
2810 const t_pbc *pbc_null;
2820 snew(f,fr->natoms_force);
2821 /* We want to preserve the fshift array in forcerec */
2822 fshift_orig = fr->fshift;
2823 snew(fr->fshift,SHIFTS);
2825 /* Loop over all bonded force types to calculate the bonded forces */
2826 for(ftype=0; (ftype<F_NRE); ftype++) {
2827 if(ftype<F_GB12 || ftype>F_GB14) {
2829 if ((interaction_function[ftype].flags & IF_BOND) &&
2830 !(ftype == F_CONNBONDS || ftype == F_POSRES))
2832 nbonds_np = idef->il[ftype].nr_nonperturbed;
2833 nbonds = idef->il[ftype].nr - nbonds_np;
2834 nat1 = interaction_function[ftype].nratoms + 1;
2836 ind = interaction_function[ftype].nrnb_ind;
2837 iatom_fe = idef->il[ftype].iatoms + nbonds_np;
2839 if (ftype < F_LJ14 || ftype > F_LJC_PAIRS_NB) {
2841 interaction_function[ftype].ifunc(nbonds,iatom_fe,
2843 (const rvec*)x,f,fr->fshift,
2844 pbc_null,g,lambda,&dvdl,md,fcd,
2847 v = do_listed_vdw_q(ftype,nbonds,iatom_fe,
2849 (const rvec*)x,f,fr->fshift,
2852 md,fr,&enerd->grpp,global_atom_index);
2855 inc_nrnb(nrnb,ind,nbonds/nat1);
2863 fr->fshift = fshift_orig;