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 *dvdlambda,
124 const t_mdatoms *md,t_fcdata *fcd,
125 int *global_atom_index)
129 real dr,dr2,temp,omtemp,cbomtemp,fbond,vbond,fij,vtot;
130 real b0,be,cb,b0A,beA,cbA,b0B,beB,cbB,L1;
132 int i,m,ki,type,ai,aj;
136 for(i=0; (i<nbonds); ) {
137 type = forceatoms[i++];
138 ai = forceatoms[i++];
139 aj = forceatoms[i++];
141 b0A = forceparams[type].morse.b0A;
142 beA = forceparams[type].morse.betaA;
143 cbA = forceparams[type].morse.cbA;
145 b0B = forceparams[type].morse.b0B;
146 beB = forceparams[type].morse.betaB;
147 cbB = forceparams[type].morse.cbB;
149 L1 = one-lambda; /* 1 */
150 b0 = L1*b0A + lambda*b0B; /* 3 */
151 be = L1*beA + lambda*beB; /* 3 */
152 cb = L1*cbA + lambda*cbB; /* 3 */
154 ki = pbc_rvec_sub(pbc,x[ai],x[aj],dx); /* 3 */
155 dr2 = iprod(dx,dx); /* 5 */
156 dr = dr2*gmx_invsqrt(dr2); /* 10 */
157 temp = exp(-be*(dr-b0)); /* 12 */
161 /* bonds are constrainted. This may _not_ include bond constraints if they are lambda dependent */
162 *dvdlambda = cbB-cbA;
166 omtemp = one-temp; /* 1 */
167 cbomtemp = cb*omtemp; /* 1 */
168 vbond = cbomtemp*omtemp; /* 1 */
169 fbond = -two*be*temp*cbomtemp*gmx_invsqrt(dr2); /* 9 */
170 vtot += vbond; /* 1 */
172 *dvdlambda += (cbB - cbA) * omtemp * omtemp - (2-2*omtemp)*omtemp * cb * ((b0B-b0A)*be - (beB-beA)*(dr-b0)); /* 15 */
175 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
179 for (m=0; (m<DIM); m++) { /* 15 */
184 fshift[CENTRAL][m]-=fij;
190 real cubic_bonds(int nbonds,
191 const t_iatom forceatoms[],const t_iparams forceparams[],
192 const rvec x[],rvec f[],rvec fshift[],
193 const t_pbc *pbc,const t_graph *g,
194 real lambda,real *dvdlambda,
195 const t_mdatoms *md,t_fcdata *fcd,
196 int *global_atom_index)
198 const real three = 3.0;
199 const real two = 2.0;
201 real dr,dr2,dist,kdist,kdist2,fbond,vbond,fij,vtot;
203 int i,m,ki,type,ai,aj;
207 for(i=0; (i<nbonds); ) {
208 type = forceatoms[i++];
209 ai = forceatoms[i++];
210 aj = forceatoms[i++];
212 b0 = forceparams[type].cubic.b0;
213 kb = forceparams[type].cubic.kb;
214 kcub = forceparams[type].cubic.kcub;
216 ki = pbc_rvec_sub(pbc,x[ai],x[aj],dx); /* 3 */
217 dr2 = iprod(dx,dx); /* 5 */
222 dr = dr2*gmx_invsqrt(dr2); /* 10 */
227 vbond = kdist2 + kcub*kdist2*dist;
228 fbond = -(two*kdist + three*kdist2*kcub)/dr;
230 vtot += vbond; /* 21 */
233 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
236 for (m=0; (m<DIM); m++) { /* 15 */
241 fshift[CENTRAL][m]-=fij;
247 real FENE_bonds(int nbonds,
248 const t_iatom forceatoms[],const t_iparams forceparams[],
249 const rvec x[],rvec f[],rvec fshift[],
250 const t_pbc *pbc,const t_graph *g,
251 real lambda,real *dvdlambda,
252 const t_mdatoms *md,t_fcdata *fcd,
253 int *global_atom_index)
258 real dr,dr2,bm2,omdr2obm2,fbond,vbond,fij,vtot;
260 int i,m,ki,type,ai,aj;
264 for(i=0; (i<nbonds); ) {
265 type = forceatoms[i++];
266 ai = forceatoms[i++];
267 aj = forceatoms[i++];
269 bm = forceparams[type].fene.bm;
270 kb = forceparams[type].fene.kb;
272 ki = pbc_rvec_sub(pbc,x[ai],x[aj],dx); /* 3 */
273 dr2 = iprod(dx,dx); /* 5 */
282 "r^2 (%f) >= bm^2 (%f) in FENE bond between atoms %d and %d",
284 glatnr(global_atom_index,ai),
285 glatnr(global_atom_index,aj));
287 omdr2obm2 = one - dr2/bm2;
289 vbond = -half*kb*bm2*log(omdr2obm2);
290 fbond = -kb/omdr2obm2;
292 vtot += vbond; /* 35 */
295 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
298 for (m=0; (m<DIM); m++) { /* 15 */
303 fshift[CENTRAL][m]-=fij;
309 real harmonic(real kA,real kB,real xA,real xB,real x,real lambda,
313 real L1,kk,x0,dx,dx2;
317 kk = L1*kA+lambda*kB;
318 x0 = L1*xA+lambda*xB;
325 dvdlambda = half*(kB-kA)*dx2 + (xA-xB)*kk*dx;
332 /* That was 19 flops */
336 real bonds(int nbonds,
337 const t_iatom forceatoms[],const t_iparams forceparams[],
338 const rvec x[],rvec f[],rvec fshift[],
339 const t_pbc *pbc,const t_graph *g,
340 real lambda,real *dvdlambda,
341 const t_mdatoms *md,t_fcdata *fcd,
342 int *global_atom_index)
344 int i,m,ki,ai,aj,type;
345 real dr,dr2,fbond,vbond,fij,vtot;
350 for(i=0; (i<nbonds); ) {
351 type = forceatoms[i++];
352 ai = forceatoms[i++];
353 aj = forceatoms[i++];
355 ki = pbc_rvec_sub(pbc,x[ai],x[aj],dx); /* 3 */
356 dr2 = iprod(dx,dx); /* 5 */
357 dr = dr2*gmx_invsqrt(dr2); /* 10 */
359 *dvdlambda += harmonic(forceparams[type].harmonic.krA,
360 forceparams[type].harmonic.krB,
361 forceparams[type].harmonic.rA,
362 forceparams[type].harmonic.rB,
363 dr,lambda,&vbond,&fbond); /* 19 */
370 fbond *= gmx_invsqrt(dr2); /* 6 */
373 fprintf(debug,"BONDS: dr = %10g vbond = %10g fbond = %10g\n",
377 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
380 for (m=0; (m<DIM); m++) { /* 15 */
385 fshift[CENTRAL][m]-=fij;
391 real restraint_bonds(int nbonds,
392 const t_iatom forceatoms[],const t_iparams forceparams[],
393 const rvec x[],rvec f[],rvec fshift[],
394 const t_pbc *pbc,const t_graph *g,
395 real lambda,real *dvdlambda,
396 const t_mdatoms *md,t_fcdata *fcd,
397 int *global_atom_index)
399 int i,m,ki,ai,aj,type;
400 real dr,dr2,fbond,vbond,fij,vtot;
402 real low,dlow,up1,dup1,up2,dup2,k,dk;
410 for(i=0; (i<nbonds); )
412 type = forceatoms[i++];
413 ai = forceatoms[i++];
414 aj = forceatoms[i++];
416 ki = pbc_rvec_sub(pbc,x[ai],x[aj],dx); /* 3 */
417 dr2 = iprod(dx,dx); /* 5 */
418 dr = dr2*gmx_invsqrt(dr2); /* 10 */
420 low = L1*forceparams[type].restraint.lowA + lambda*forceparams[type].restraint.lowB;
421 dlow = -forceparams[type].restraint.lowA + forceparams[type].restraint.lowB;
422 up1 = L1*forceparams[type].restraint.up1A + lambda*forceparams[type].restraint.up1B;
423 dup1 = -forceparams[type].restraint.up1A + forceparams[type].restraint.up1B;
424 up2 = L1*forceparams[type].restraint.up2A + lambda*forceparams[type].restraint.up2B;
425 dup2 = -forceparams[type].restraint.up2A + forceparams[type].restraint.up2B;
426 k = L1*forceparams[type].restraint.kA + lambda*forceparams[type].restraint.kB;
427 dk = -forceparams[type].restraint.kA + forceparams[type].restraint.kB;
436 *dvdlambda += 0.5*dk*drh2 - k*dlow*drh;
449 *dvdlambda += 0.5*dk*drh2 - k*dup1*drh;
454 vbond = k*(up2 - up1)*(0.5*(up2 - up1) + drh);
455 fbond = -k*(up2 - up1);
456 *dvdlambda += dk*(up2 - up1)*(0.5*(up2 - up1) + drh)
457 + k*(dup2 - dup1)*(up2 - up1 + drh)
458 - k*(up2 - up1)*dup2;
465 fbond *= gmx_invsqrt(dr2); /* 6 */
468 fprintf(debug,"BONDS: dr = %10g vbond = %10g fbond = %10g\n",
472 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
475 for (m=0; (m<DIM); m++) { /* 15 */
480 fshift[CENTRAL][m]-=fij;
487 real polarize(int nbonds,
488 const t_iatom forceatoms[],const t_iparams forceparams[],
489 const rvec x[],rvec f[],rvec fshift[],
490 const t_pbc *pbc,const t_graph *g,
491 real lambda,real *dvdlambda,
492 const t_mdatoms *md,t_fcdata *fcd,
493 int *global_atom_index)
495 int i,m,ki,ai,aj,type;
496 real dr,dr2,fbond,vbond,fij,vtot,ksh;
501 for(i=0; (i<nbonds); ) {
502 type = forceatoms[i++];
503 ai = forceatoms[i++];
504 aj = forceatoms[i++];
505 ksh = sqr(md->chargeA[aj])*ONE_4PI_EPS0/forceparams[type].polarize.alpha;
507 fprintf(debug,"POL: local ai = %d aj = %d ksh = %.3f\n",ai,aj,ksh);
509 ki = pbc_rvec_sub(pbc,x[ai],x[aj],dx); /* 3 */
510 dr2 = iprod(dx,dx); /* 5 */
511 dr = dr2*gmx_invsqrt(dr2); /* 10 */
513 *dvdlambda += harmonic(ksh,ksh,0,0,dr,lambda,&vbond,&fbond); /* 19 */
519 fbond *= gmx_invsqrt(dr2); /* 6 */
522 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
525 for (m=0; (m<DIM); m++) { /* 15 */
530 fshift[CENTRAL][m]-=fij;
536 real anharm_polarize(int nbonds,
537 const t_iatom forceatoms[],const t_iparams forceparams[],
538 const rvec x[],rvec f[],rvec fshift[],
539 const t_pbc *pbc,const t_graph *g,
540 real lambda,real *dvdlambda,
541 const t_mdatoms *md,t_fcdata *fcd,
542 int *global_atom_index)
544 int i,m,ki,ai,aj,type;
545 real dr,dr2,fbond,vbond,fij,vtot,ksh,khyp,drcut,ddr,ddr3;
550 for(i=0; (i<nbonds); ) {
551 type = forceatoms[i++];
552 ai = forceatoms[i++];
553 aj = forceatoms[i++];
554 ksh = sqr(md->chargeA[aj])*ONE_4PI_EPS0/forceparams[type].anharm_polarize.alpha; /* 7*/
555 khyp = forceparams[type].anharm_polarize.khyp;
556 drcut = forceparams[type].anharm_polarize.drcut;
558 fprintf(debug,"POL: local ai = %d aj = %d ksh = %.3f\n",ai,aj,ksh);
560 ki = pbc_rvec_sub(pbc,x[ai],x[aj],dx); /* 3 */
561 dr2 = iprod(dx,dx); /* 5 */
562 dr = dr2*gmx_invsqrt(dr2); /* 10 */
564 *dvdlambda += harmonic(ksh,ksh,0,0,dr,lambda,&vbond,&fbond); /* 19 */
572 vbond += khyp*ddr*ddr3;
573 fbond -= 4*khyp*ddr3;
575 fbond *= gmx_invsqrt(dr2); /* 6 */
579 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
582 for (m=0; (m<DIM); m++) { /* 15 */
587 fshift[CENTRAL][m]-=fij;
593 real water_pol(int nbonds,
594 const t_iatom forceatoms[],const t_iparams forceparams[],
595 const rvec x[],rvec f[],rvec fshift[],
596 const t_pbc *pbc,const t_graph *g,
597 real lambda,real *dvdlambda,
598 const t_mdatoms *md,t_fcdata *fcd,
599 int *global_atom_index)
601 /* This routine implements anisotropic polarizibility for water, through
602 * a shell connected to a dummy with spring constant that differ in the
603 * three spatial dimensions in the molecular frame.
605 int i,m,aO,aH1,aH2,aD,aS,type,type0;
606 rvec dOH1,dOH2,dHH,dOD,dDS,nW,kk,dx,kdx,proj;
610 real vtot,fij,r_HH,r_OD,r_nW,tx,ty,tz,qS;
614 type0 = forceatoms[0];
616 qS = md->chargeA[aS];
617 kk[XX] = sqr(qS)*ONE_4PI_EPS0/forceparams[type0].wpol.al_x;
618 kk[YY] = sqr(qS)*ONE_4PI_EPS0/forceparams[type0].wpol.al_y;
619 kk[ZZ] = sqr(qS)*ONE_4PI_EPS0/forceparams[type0].wpol.al_z;
620 r_HH = 1.0/forceparams[type0].wpol.rHH;
621 r_OD = 1.0/forceparams[type0].wpol.rOD;
623 fprintf(debug,"WPOL: qS = %10.5f aS = %5d\n",qS,aS);
624 fprintf(debug,"WPOL: kk = %10.3f %10.3f %10.3f\n",
625 kk[XX],kk[YY],kk[ZZ]);
626 fprintf(debug,"WPOL: rOH = %10.3f rHH = %10.3f rOD = %10.3f\n",
627 forceparams[type0].wpol.rOH,
628 forceparams[type0].wpol.rHH,
629 forceparams[type0].wpol.rOD);
631 for(i=0; (i<nbonds); i+=6) {
632 type = forceatoms[i];
634 gmx_fatal(FARGS,"Sorry, type = %d, type0 = %d, file = %s, line = %d",
635 type,type0,__FILE__,__LINE__);
636 aO = forceatoms[i+1];
637 aH1 = forceatoms[i+2];
638 aH2 = forceatoms[i+3];
639 aD = forceatoms[i+4];
640 aS = forceatoms[i+5];
642 /* Compute vectors describing the water frame */
643 rvec_sub(x[aH1],x[aO], dOH1);
644 rvec_sub(x[aH2],x[aO], dOH2);
645 rvec_sub(x[aH2],x[aH1],dHH);
646 rvec_sub(x[aD], x[aO], dOD);
647 rvec_sub(x[aS], x[aD], dDS);
650 /* Compute inverse length of normal vector
651 * (this one could be precomputed, but I'm too lazy now)
653 r_nW = gmx_invsqrt(iprod(nW,nW));
654 /* This is for precision, but does not make a big difference,
657 r_OD = gmx_invsqrt(iprod(dOD,dOD));
659 /* Normalize the vectors in the water frame */
664 /* Compute displacement of shell along components of the vector */
665 dx[ZZ] = iprod(dDS,dOD);
666 /* Compute projection on the XY plane: dDS - dx[ZZ]*dOD */
667 for(m=0; (m<DIM); m++)
668 proj[m] = dDS[m]-dx[ZZ]*dOD[m];
670 /*dx[XX] = iprod(dDS,nW);
671 dx[YY] = iprod(dDS,dHH);*/
672 dx[XX] = iprod(proj,nW);
673 for(m=0; (m<DIM); m++)
674 proj[m] -= dx[XX]*nW[m];
675 dx[YY] = iprod(proj,dHH);
679 fprintf(debug,"WPOL: dx2=%10g dy2=%10g dz2=%10g sum=%10g dDS^2=%10g\n",
680 sqr(dx[XX]),sqr(dx[YY]),sqr(dx[ZZ]),iprod(dx,dx),iprod(dDS,dDS));
681 fprintf(debug,"WPOL: dHH=(%10g,%10g,%10g)\n",dHH[XX],dHH[YY],dHH[ZZ]);
682 fprintf(debug,"WPOL: dOD=(%10g,%10g,%10g), 1/r_OD = %10g\n",
683 dOD[XX],dOD[YY],dOD[ZZ],1/r_OD);
684 fprintf(debug,"WPOL: nW =(%10g,%10g,%10g), 1/r_nW = %10g\n",
685 nW[XX],nW[YY],nW[ZZ],1/r_nW);
686 fprintf(debug,"WPOL: dx =%10g, dy =%10g, dz =%10g\n",
687 dx[XX],dx[YY],dx[ZZ]);
688 fprintf(debug,"WPOL: dDSx=%10g, dDSy=%10g, dDSz=%10g\n",
689 dDS[XX],dDS[YY],dDS[ZZ]);
692 /* Now compute the forces and energy */
693 kdx[XX] = kk[XX]*dx[XX];
694 kdx[YY] = kk[YY]*dx[YY];
695 kdx[ZZ] = kk[ZZ]*dx[ZZ];
696 vtot += iprod(dx,kdx);
697 for(m=0; (m<DIM); m++) {
698 /* This is a tensor operation but written out for speed */
711 fprintf(debug,"WPOL: vwpol=%g\n",0.5*iprod(dx,kdx));
712 fprintf(debug,"WPOL: df = (%10g, %10g, %10g)\n",df[XX],df[YY],df[ZZ]);
720 static real do_1_thole(const rvec xi,const rvec xj,rvec fi,rvec fj,
721 const t_pbc *pbc,real qq,
722 rvec fshift[],real afac)
725 real r12sq,r12_1,r12n,r12bar,v0,v1,fscal,ebar,fff;
728 t = pbc_rvec_sub(pbc,xi,xj,r12); /* 3 */
730 r12sq = iprod(r12,r12); /* 5 */
731 r12_1 = gmx_invsqrt(r12sq); /* 5 */
732 r12bar = afac/r12_1; /* 5 */
733 v0 = qq*ONE_4PI_EPS0*r12_1; /* 2 */
734 ebar = exp(-r12bar); /* 5 */
735 v1 = (1-(1+0.5*r12bar)*ebar); /* 4 */
736 fscal = ((v0*r12_1)*v1 - v0*0.5*afac*ebar*(r12bar+1))*r12_1; /* 9 */
738 fprintf(debug,"THOLE: v0 = %.3f v1 = %.3f r12= % .3f r12bar = %.3f fscal = %.3f ebar = %.3f\n",v0,v1,1/r12_1,r12bar,fscal,ebar);
740 for(m=0; (m<DIM); m++) {
745 fshift[CENTRAL][m] -= fff;
748 return v0*v1; /* 1 */
752 real thole_pol(int nbonds,
753 const t_iatom forceatoms[],const t_iparams forceparams[],
754 const rvec x[],rvec f[],rvec fshift[],
755 const t_pbc *pbc,const t_graph *g,
756 real lambda,real *dvdlambda,
757 const t_mdatoms *md,t_fcdata *fcd,
758 int *global_atom_index)
760 /* Interaction between two pairs of particles with opposite charge */
761 int i,type,a1,da1,a2,da2;
762 real q1,q2,qq,a,al1,al2,afac;
765 for(i=0; (i<nbonds); ) {
766 type = forceatoms[i++];
767 a1 = forceatoms[i++];
768 da1 = forceatoms[i++];
769 a2 = forceatoms[i++];
770 da2 = forceatoms[i++];
771 q1 = md->chargeA[da1];
772 q2 = md->chargeA[da2];
773 a = forceparams[type].thole.a;
774 al1 = forceparams[type].thole.alpha1;
775 al2 = forceparams[type].thole.alpha2;
777 afac = a*pow(al1*al2,-1.0/6.0);
778 V += do_1_thole(x[a1], x[a2], f[a1], f[a2], pbc, qq,fshift,afac);
779 V += do_1_thole(x[da1],x[a2], f[da1],f[a2], pbc,-qq,fshift,afac);
780 V += do_1_thole(x[a1], x[da2],f[a1], f[da2],pbc,-qq,fshift,afac);
781 V += do_1_thole(x[da1],x[da2],f[da1],f[da2],pbc, qq,fshift,afac);
787 real bond_angle(const rvec xi,const rvec xj,const rvec xk,const t_pbc *pbc,
788 rvec r_ij,rvec r_kj,real *costh,
790 /* Return value is the angle between the bonds i-j and j-k */
795 *t1 = pbc_rvec_sub(pbc,xi,xj,r_ij); /* 3 */
796 *t2 = pbc_rvec_sub(pbc,xk,xj,r_kj); /* 3 */
798 *costh=cos_angle(r_ij,r_kj); /* 25 */
799 th=acos(*costh); /* 10 */
804 real angles(int nbonds,
805 const t_iatom forceatoms[],const t_iparams forceparams[],
806 const rvec x[],rvec f[],rvec fshift[],
807 const t_pbc *pbc,const t_graph *g,
808 real lambda,real *dvdlambda,
809 const t_mdatoms *md,t_fcdata *fcd,
810 int *global_atom_index)
812 int i,ai,aj,ak,t1,t2,type;
814 real cos_theta,cos_theta2,theta,dVdt,va,vtot;
818 for(i=0; (i<nbonds); ) {
819 type = forceatoms[i++];
820 ai = forceatoms[i++];
821 aj = forceatoms[i++];
822 ak = forceatoms[i++];
824 theta = bond_angle(x[ai],x[aj],x[ak],pbc,
825 r_ij,r_kj,&cos_theta,&t1,&t2); /* 41 */
827 *dvdlambda += harmonic(forceparams[type].harmonic.krA,
828 forceparams[type].harmonic.krB,
829 forceparams[type].harmonic.rA*DEG2RAD,
830 forceparams[type].harmonic.rB*DEG2RAD,
831 theta,lambda,&va,&dVdt); /* 21 */
834 cos_theta2 = sqr(cos_theta);
835 if (cos_theta2 < 1) {
842 st = dVdt*gmx_invsqrt(1 - cos_theta2); /* 12 */
843 sth = st*cos_theta; /* 1 */
846 fprintf(debug,"ANGLES: theta = %10g vth = %10g dV/dtheta = %10g\n",
847 theta*RAD2DEG,va,dVdt);
849 nrkj2=iprod(r_kj,r_kj); /* 5 */
850 nrij2=iprod(r_ij,r_ij);
852 cik=st*gmx_invsqrt(nrkj2*nrij2); /* 12 */
853 cii=sth/nrij2; /* 10 */
854 ckk=sth/nrkj2; /* 10 */
856 for (m=0; (m<DIM); m++) { /* 39 */
857 f_i[m]=-(cik*r_kj[m]-cii*r_ij[m]);
858 f_k[m]=-(cik*r_ij[m]-ckk*r_kj[m]);
859 f_j[m]=-f_i[m]-f_k[m];
865 copy_ivec(SHIFT_IVEC(g,aj),jt);
867 ivec_sub(SHIFT_IVEC(g,ai),jt,dt_ij);
868 ivec_sub(SHIFT_IVEC(g,ak),jt,dt_kj);
872 rvec_inc(fshift[t1],f_i);
873 rvec_inc(fshift[CENTRAL],f_j);
874 rvec_inc(fshift[t2],f_k);
880 real linear_angles(int nbonds,
881 const t_iatom forceatoms[],const t_iparams forceparams[],
882 const rvec x[],rvec f[],rvec fshift[],
883 const t_pbc *pbc,const t_graph *g,
884 real lambda,real *dvdlambda,
885 const t_mdatoms *md,t_fcdata *fcd,
886 int *global_atom_index)
888 int i,m,ai,aj,ak,t1,t2,type;
890 real L1,kA,kB,aA,aB,dr,dr2,va,vtot,a,b,klin;
892 rvec r_ij,r_kj,r_ik,dx;
896 for(i=0; (i<nbonds); ) {
897 type = forceatoms[i++];
898 ai = forceatoms[i++];
899 aj = forceatoms[i++];
900 ak = forceatoms[i++];
902 kA = forceparams[type].linangle.klinA;
903 kB = forceparams[type].linangle.klinB;
904 klin = L1*kA + lambda*kB;
906 aA = forceparams[type].linangle.aA;
907 aB = forceparams[type].linangle.aB;
911 t1 = pbc_rvec_sub(pbc,x[ai],x[aj],r_ij);
912 t2 = pbc_rvec_sub(pbc,x[ak],x[aj],r_kj);
913 rvec_sub(r_ij,r_kj,r_ik);
916 for(m=0; (m<DIM); m++)
918 dr = - a * r_ij[m] - b * r_kj[m];
923 f_j[m] = -(f_i[m]+f_k[m]);
929 *dvdlambda += 0.5*(kB-kA)*dr2 + klin*(aB-aA)*iprod(dx,r_ik);
934 copy_ivec(SHIFT_IVEC(g,aj),jt);
936 ivec_sub(SHIFT_IVEC(g,ai),jt,dt_ij);
937 ivec_sub(SHIFT_IVEC(g,ak),jt,dt_kj);
941 rvec_inc(fshift[t1],f_i);
942 rvec_inc(fshift[CENTRAL],f_j);
943 rvec_inc(fshift[t2],f_k);
948 real urey_bradley(int nbonds,
949 const t_iatom forceatoms[],const t_iparams forceparams[],
950 const rvec x[],rvec f[],rvec fshift[],
951 const t_pbc *pbc,const t_graph *g,
952 real lambda,real *dvdlambda,
953 const t_mdatoms *md,t_fcdata *fcd,
954 int *global_atom_index)
956 int i,m,ai,aj,ak,t1,t2,type,ki;
958 real cos_theta,cos_theta2,theta;
959 real dVdt,va,vtot,dr,dr2,vbond,fbond,fik;
960 real kthA,th0A,kUBA,r13A,kthB,th0B,kUBB,r13B;
961 ivec jt,dt_ij,dt_kj,dt_ik;
964 for(i=0; (i<nbonds); ) {
965 type = forceatoms[i++];
966 ai = forceatoms[i++];
967 aj = forceatoms[i++];
968 ak = forceatoms[i++];
969 th0A = forceparams[type].u_b.thetaA*DEG2RAD;
970 kthA = forceparams[type].u_b.kthetaA;
971 r13A = forceparams[type].u_b.r13A;
972 kUBA = forceparams[type].u_b.kUBA;
973 th0B = forceparams[type].u_b.thetaB*DEG2RAD;
974 kthB = forceparams[type].u_b.kthetaB;
975 r13B = forceparams[type].u_b.r13B;
976 kUBB = forceparams[type].u_b.kUBB;
978 theta = bond_angle(x[ai],x[aj],x[ak],pbc,
979 r_ij,r_kj,&cos_theta,&t1,&t2); /* 41 */
981 *dvdlambda += harmonic(kthA,kthB,th0A,th0B,theta,lambda,&va,&dVdt); /* 21 */
984 ki = pbc_rvec_sub(pbc,x[ai],x[ak],r_ik); /* 3 */
985 dr2 = iprod(r_ik,r_ik); /* 5 */
986 dr = dr2*gmx_invsqrt(dr2); /* 10 */
988 *dvdlambda += harmonic(kUBA,kUBB,r13A,r13B,dr,lambda,&vbond,&fbond); /* 19 */
990 cos_theta2 = sqr(cos_theta); /* 1 */
991 if (cos_theta2 < 1) {
997 st = dVdt*gmx_invsqrt(1 - cos_theta2); /* 12 */
998 sth = st*cos_theta; /* 1 */
1001 fprintf(debug,"ANGLES: theta = %10g vth = %10g dV/dtheta = %10g\n",
1002 theta*RAD2DEG,va,dVdt);
1004 nrkj2=iprod(r_kj,r_kj); /* 5 */
1005 nrij2=iprod(r_ij,r_ij);
1007 cik=st*gmx_invsqrt(nrkj2*nrij2); /* 12 */
1008 cii=sth/nrij2; /* 10 */
1009 ckk=sth/nrkj2; /* 10 */
1011 for (m=0; (m<DIM); m++) { /* 39 */
1012 f_i[m]=-(cik*r_kj[m]-cii*r_ij[m]);
1013 f_k[m]=-(cik*r_ij[m]-ckk*r_kj[m]);
1014 f_j[m]=-f_i[m]-f_k[m];
1020 copy_ivec(SHIFT_IVEC(g,aj),jt);
1022 ivec_sub(SHIFT_IVEC(g,ai),jt,dt_ij);
1023 ivec_sub(SHIFT_IVEC(g,ak),jt,dt_kj);
1027 rvec_inc(fshift[t1],f_i);
1028 rvec_inc(fshift[CENTRAL],f_j);
1029 rvec_inc(fshift[t2],f_k);
1031 /* Time for the bond calculations */
1035 vtot += vbond; /* 1*/
1036 fbond *= gmx_invsqrt(dr2); /* 6 */
1039 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,ak),dt_ik);
1042 for (m=0; (m<DIM); m++) { /* 15 */
1047 fshift[CENTRAL][m]-=fik;
1053 real quartic_angles(int nbonds,
1054 const t_iatom forceatoms[],const t_iparams forceparams[],
1055 const rvec x[],rvec f[],rvec fshift[],
1056 const t_pbc *pbc,const t_graph *g,
1057 real lambda,real *dvdlambda,
1058 const t_mdatoms *md,t_fcdata *fcd,
1059 int *global_atom_index)
1061 int i,j,ai,aj,ak,t1,t2,type;
1063 real cos_theta,cos_theta2,theta,dt,dVdt,va,dtp,c,vtot;
1064 ivec jt,dt_ij,dt_kj;
1067 for(i=0; (i<nbonds); ) {
1068 type = forceatoms[i++];
1069 ai = forceatoms[i++];
1070 aj = forceatoms[i++];
1071 ak = forceatoms[i++];
1073 theta = bond_angle(x[ai],x[aj],x[ak],pbc,
1074 r_ij,r_kj,&cos_theta,&t1,&t2); /* 41 */
1076 dt = theta - forceparams[type].qangle.theta*DEG2RAD; /* 2 */
1079 va = forceparams[type].qangle.c[0];
1081 for(j=1; j<=4; j++) {
1082 c = forceparams[type].qangle.c[j];
1091 cos_theta2 = sqr(cos_theta); /* 1 */
1092 if (cos_theta2 < 1) {
1099 st = dVdt*gmx_invsqrt(1 - cos_theta2); /* 12 */
1100 sth = st*cos_theta; /* 1 */
1103 fprintf(debug,"ANGLES: theta = %10g vth = %10g dV/dtheta = %10g\n",
1104 theta*RAD2DEG,va,dVdt);
1106 nrkj2=iprod(r_kj,r_kj); /* 5 */
1107 nrij2=iprod(r_ij,r_ij);
1109 cik=st*gmx_invsqrt(nrkj2*nrij2); /* 12 */
1110 cii=sth/nrij2; /* 10 */
1111 ckk=sth/nrkj2; /* 10 */
1113 for (m=0; (m<DIM); m++) { /* 39 */
1114 f_i[m]=-(cik*r_kj[m]-cii*r_ij[m]);
1115 f_k[m]=-(cik*r_ij[m]-ckk*r_kj[m]);
1116 f_j[m]=-f_i[m]-f_k[m];
1122 copy_ivec(SHIFT_IVEC(g,aj),jt);
1124 ivec_sub(SHIFT_IVEC(g,ai),jt,dt_ij);
1125 ivec_sub(SHIFT_IVEC(g,ak),jt,dt_kj);
1129 rvec_inc(fshift[t1],f_i);
1130 rvec_inc(fshift[CENTRAL],f_j);
1131 rvec_inc(fshift[t2],f_k);
1137 real dih_angle(const rvec xi,const rvec xj,const rvec xk,const rvec xl,
1139 rvec r_ij,rvec r_kj,rvec r_kl,rvec m,rvec n,
1140 real *sign,int *t1,int *t2,int *t3)
1144 *t1 = pbc_rvec_sub(pbc,xi,xj,r_ij); /* 3 */
1145 *t2 = pbc_rvec_sub(pbc,xk,xj,r_kj); /* 3 */
1146 *t3 = pbc_rvec_sub(pbc,xk,xl,r_kl); /* 3 */
1148 cprod(r_ij,r_kj,m); /* 9 */
1149 cprod(r_kj,r_kl,n); /* 9 */
1150 phi=gmx_angle(m,n); /* 49 (assuming 25 for atan2) */
1151 ipr=iprod(r_ij,n); /* 5 */
1152 (*sign)=(ipr<0.0)?-1.0:1.0;
1153 phi=(*sign)*phi; /* 1 */
1160 void do_dih_fup(int i,int j,int k,int l,real ddphi,
1161 rvec r_ij,rvec r_kj,rvec r_kl,
1162 rvec m,rvec n,rvec f[],rvec fshift[],
1163 const t_pbc *pbc,const t_graph *g,
1164 const rvec x[],int t1,int t2,int t3)
1167 rvec f_i,f_j,f_k,f_l;
1168 rvec uvec,vvec,svec,dx_jl;
1169 real iprm,iprn,nrkj,nrkj2;
1171 ivec jt,dt_ij,dt_kj,dt_lj;
1173 iprm = iprod(m,m); /* 5 */
1174 iprn = iprod(n,n); /* 5 */
1175 nrkj2 = iprod(r_kj,r_kj); /* 5 */
1176 toler = nrkj2*GMX_REAL_EPS;
1177 if ((iprm > toler) && (iprn > toler)) {
1178 nrkj = nrkj2*gmx_invsqrt(nrkj2); /* 10 */
1179 a = -ddphi*nrkj/iprm; /* 11 */
1180 svmul(a,m,f_i); /* 3 */
1181 a = ddphi*nrkj/iprn; /* 11 */
1182 svmul(a,n,f_l); /* 3 */
1183 p = iprod(r_ij,r_kj); /* 5 */
1184 p /= nrkj2; /* 10 */
1185 q = iprod(r_kl,r_kj); /* 5 */
1186 q /= nrkj2; /* 10 */
1187 svmul(p,f_i,uvec); /* 3 */
1188 svmul(q,f_l,vvec); /* 3 */
1189 rvec_sub(uvec,vvec,svec); /* 3 */
1190 rvec_sub(f_i,svec,f_j); /* 3 */
1191 rvec_add(f_l,svec,f_k); /* 3 */
1192 rvec_inc(f[i],f_i); /* 3 */
1193 rvec_dec(f[j],f_j); /* 3 */
1194 rvec_dec(f[k],f_k); /* 3 */
1195 rvec_inc(f[l],f_l); /* 3 */
1198 copy_ivec(SHIFT_IVEC(g,j),jt);
1199 ivec_sub(SHIFT_IVEC(g,i),jt,dt_ij);
1200 ivec_sub(SHIFT_IVEC(g,k),jt,dt_kj);
1201 ivec_sub(SHIFT_IVEC(g,l),jt,dt_lj);
1206 t3 = pbc_rvec_sub(pbc,x[l],x[j],dx_jl);
1211 rvec_inc(fshift[t1],f_i);
1212 rvec_dec(fshift[CENTRAL],f_j);
1213 rvec_dec(fshift[t2],f_k);
1214 rvec_inc(fshift[t3],f_l);
1220 real dopdihs(real cpA,real cpB,real phiA,real phiB,int mult,
1221 real phi,real lambda,real *V,real *F)
1223 real v,dvdlambda,mdphi,v1,sdphi,ddphi;
1224 real L1 = 1.0 - lambda;
1225 real ph0 = (L1*phiA + lambda*phiB)*DEG2RAD;
1226 real dph0 = (phiB - phiA)*DEG2RAD;
1227 real cp = L1*cpA + lambda*cpB;
1229 mdphi = mult*phi - ph0;
1231 ddphi = -cp*mult*sdphi;
1232 v1 = 1.0 + cos(mdphi);
1235 dvdlambda = (cpB - cpA)*v1 + cp*dph0*sdphi;
1242 /* That was 40 flops */
1245 static real dopdihs_min(real cpA,real cpB,real phiA,real phiB,int mult,
1246 real phi,real lambda,real *V,real *F)
1247 /* similar to dopdihs, except for a minus sign *
1248 * and a different treatment of mult/phi0 */
1250 real v,dvdlambda,mdphi,v1,sdphi,ddphi;
1251 real L1 = 1.0 - lambda;
1252 real ph0 = (L1*phiA + lambda*phiB)*DEG2RAD;
1253 real dph0 = (phiB - phiA)*DEG2RAD;
1254 real cp = L1*cpA + lambda*cpB;
1256 mdphi = mult*(phi-ph0);
1258 ddphi = cp*mult*sdphi;
1259 v1 = 1.0-cos(mdphi);
1262 dvdlambda = (cpB-cpA)*v1 + cp*dph0*sdphi;
1269 /* That was 40 flops */
1272 real pdihs(int nbonds,
1273 const t_iatom forceatoms[],const t_iparams forceparams[],
1274 const rvec x[],rvec f[],rvec fshift[],
1275 const t_pbc *pbc,const t_graph *g,
1276 real lambda,real *dvdlambda,
1277 const t_mdatoms *md,t_fcdata *fcd,
1278 int *global_atom_index)
1280 int i,type,ai,aj,ak,al;
1282 rvec r_ij,r_kj,r_kl,m,n;
1283 real phi,sign,ddphi,vpd,vtot;
1287 for(i=0; (i<nbonds); ) {
1288 type = forceatoms[i++];
1289 ai = forceatoms[i++];
1290 aj = forceatoms[i++];
1291 ak = forceatoms[i++];
1292 al = forceatoms[i++];
1294 phi=dih_angle(x[ai],x[aj],x[ak],x[al],pbc,r_ij,r_kj,r_kl,m,n,
1295 &sign,&t1,&t2,&t3); /* 84 */
1296 *dvdlambda += dopdihs(forceparams[type].pdihs.cpA,
1297 forceparams[type].pdihs.cpB,
1298 forceparams[type].pdihs.phiA,
1299 forceparams[type].pdihs.phiB,
1300 forceparams[type].pdihs.mult,
1301 phi,lambda,&vpd,&ddphi);
1304 do_dih_fup(ai,aj,ak,al,ddphi,r_ij,r_kj,r_kl,m,n,
1305 f,fshift,pbc,g,x,t1,t2,t3); /* 112 */
1308 fprintf(debug,"pdih: (%d,%d,%d,%d) phi=%g\n",
1316 void make_dp_periodic(real *dp) /* 1 flop? */
1318 /* dp cannot be outside (-pi,pi) */
1323 else if (*dp < -M_PI)
1331 real idihs(int nbonds,
1332 const t_iatom forceatoms[],const t_iparams forceparams[],
1333 const rvec x[],rvec f[],rvec fshift[],
1334 const t_pbc *pbc,const t_graph *g,
1335 real lambda,real *dvdlambda,
1336 const t_mdatoms *md,t_fcdata *fcd,
1337 int *global_atom_index)
1339 int i,type,ai,aj,ak,al;
1341 real phi,phi0,dphi0,ddphi,sign,vtot;
1342 rvec r_ij,r_kj,r_kl,m,n;
1343 real L1,kk,dp,dp2,kA,kB,pA,pB,dvdl_term;
1348 for(i=0; (i<nbonds); ) {
1349 type = forceatoms[i++];
1350 ai = forceatoms[i++];
1351 aj = forceatoms[i++];
1352 ak = forceatoms[i++];
1353 al = forceatoms[i++];
1355 phi=dih_angle(x[ai],x[aj],x[ak],x[al],pbc,r_ij,r_kj,r_kl,m,n,
1356 &sign,&t1,&t2,&t3); /* 84 */
1358 /* phi can jump if phi0 is close to Pi/-Pi, which will cause huge
1359 * force changes if we just apply a normal harmonic.
1360 * Instead, we first calculate phi-phi0 and take it modulo (-Pi,Pi).
1361 * This means we will never have the periodicity problem, unless
1362 * the dihedral is Pi away from phiO, which is very unlikely due to
1365 kA = forceparams[type].harmonic.krA;
1366 kB = forceparams[type].harmonic.krB;
1367 pA = forceparams[type].harmonic.rA;
1368 pB = forceparams[type].harmonic.rB;
1370 kk = L1*kA + lambda*kB;
1371 phi0 = (L1*pA + lambda*pB)*DEG2RAD;
1372 dphi0 = (pB - pA)*DEG2RAD;
1376 make_dp_periodic(&dp);
1383 dvdl_term += 0.5*(kB - kA)*dp2 - kk*dphi0*dp;
1385 do_dih_fup(ai,aj,ak,al,(real)(-ddphi),r_ij,r_kj,r_kl,m,n,
1386 f,fshift,pbc,g,x,t1,t2,t3); /* 112 */
1390 fprintf(debug,"idih: (%d,%d,%d,%d) phi=%g\n",
1395 *dvdlambda += dvdl_term;
1400 real posres(int nbonds,
1401 const t_iatom forceatoms[],const t_iparams forceparams[],
1402 const rvec x[],rvec f[],rvec vir_diag,
1404 real lambda,real *dvdlambda,
1405 int refcoord_scaling,int ePBC,rvec comA,rvec comB)
1407 int i,ai,m,d,type,ki,npbcdim=0;
1408 const t_iparams *pr;
1411 real posA,posB,ref=0;
1412 rvec comA_sc,comB_sc,rdist,dpdl,pos,dx;
1413 gmx_bool bForceValid = TRUE;
1415 if ((f==NULL) || (vir_diag==NULL)) { /* should both be null together! */
1416 bForceValid = FALSE;
1419 npbcdim = ePBC2npbcdim(ePBC);
1421 if (refcoord_scaling == erscCOM)
1423 clear_rvec(comA_sc);
1424 clear_rvec(comB_sc);
1425 for(m=0; m<npbcdim; m++)
1427 for(d=m; d<npbcdim; d++)
1429 comA_sc[m] += comA[d]*pbc->box[d][m];
1430 comB_sc[m] += comB[d]*pbc->box[d][m];
1438 for(i=0; (i<nbonds); )
1440 type = forceatoms[i++];
1441 ai = forceatoms[i++];
1442 pr = &forceparams[type];
1444 for(m=0; m<DIM; m++)
1446 posA = forceparams[type].posres.pos0A[m];
1447 posB = forceparams[type].posres.pos0B[m];
1450 switch (refcoord_scaling)
1454 rdist[m] = L1*posA + lambda*posB;
1455 dpdl[m] = posB - posA;
1458 /* Box relative coordinates are stored for dimensions with pbc */
1459 posA *= pbc->box[m][m];
1460 posB *= pbc->box[m][m];
1461 for(d=m+1; d<npbcdim; d++)
1463 posA += forceparams[type].posres.pos0A[d]*pbc->box[d][m];
1464 posB += forceparams[type].posres.pos0B[d]*pbc->box[d][m];
1466 ref = L1*posA + lambda*posB;
1468 dpdl[m] = posB - posA;
1471 ref = L1*comA_sc[m] + lambda*comB_sc[m];
1472 rdist[m] = L1*posA + lambda*posB;
1473 dpdl[m] = comB_sc[m] - comA_sc[m] + posB - posA;
1476 gmx_fatal(FARGS, "No such scaling method implemented");
1481 ref = L1*posA + lambda*posB;
1483 dpdl[m] = posB - posA;
1486 /* We do pbc_dx with ref+rdist,
1487 * since with only ref we can be up to half a box vector wrong.
1489 pos[m] = ref + rdist[m];
1494 pbc_dx(pbc,x[ai],pos,dx);
1498 rvec_sub(x[ai],pos,dx);
1501 for (m=0; (m<DIM); m++)
1503 kk = L1*pr->posres.fcA[m] + lambda*pr->posres.fcB[m];
1505 vtot += 0.5*kk*dx[m]*dx[m];
1507 0.5*(pr->posres.fcB[m] - pr->posres.fcA[m])*dx[m]*dx[m]
1510 /* Here we correct for the pbc_dx which included rdist */
1513 vir_diag[m] -= 0.5*(dx[m] + rdist[m])*fm;
1521 static real low_angres(int nbonds,
1522 const t_iatom forceatoms[],const t_iparams forceparams[],
1523 const rvec x[],rvec f[],rvec fshift[],
1524 const t_pbc *pbc,const t_graph *g,
1525 real lambda,real *dvdlambda,
1528 int i,m,type,ai,aj,ak,al;
1530 real phi,cos_phi,cos_phi2,vid,vtot,dVdphi;
1531 rvec r_ij,r_kl,f_i,f_k={0,0,0};
1532 real st,sth,nrij2,nrkl2,c,cij,ckl;
1535 t2 = 0; /* avoid warning with gcc-3.3. It is never used uninitialized */
1538 ak=al=0; /* to avoid warnings */
1539 for(i=0; i<nbonds; ) {
1540 type = forceatoms[i++];
1541 ai = forceatoms[i++];
1542 aj = forceatoms[i++];
1543 t1 = pbc_rvec_sub(pbc,x[aj],x[ai],r_ij); /* 3 */
1545 ak = forceatoms[i++];
1546 al = forceatoms[i++];
1547 t2 = pbc_rvec_sub(pbc,x[al],x[ak],r_kl); /* 3 */
1554 cos_phi = cos_angle(r_ij,r_kl); /* 25 */
1555 phi = acos(cos_phi); /* 10 */
1557 *dvdlambda += dopdihs_min(forceparams[type].pdihs.cpA,
1558 forceparams[type].pdihs.cpB,
1559 forceparams[type].pdihs.phiA,
1560 forceparams[type].pdihs.phiB,
1561 forceparams[type].pdihs.mult,
1562 phi,lambda,&vid,&dVdphi); /* 40 */
1566 cos_phi2 = sqr(cos_phi); /* 1 */
1568 st = -dVdphi*gmx_invsqrt(1 - cos_phi2); /* 12 */
1569 sth = st*cos_phi; /* 1 */
1570 nrij2 = iprod(r_ij,r_ij); /* 5 */
1571 nrkl2 = iprod(r_kl,r_kl); /* 5 */
1573 c = st*gmx_invsqrt(nrij2*nrkl2); /* 11 */
1574 cij = sth/nrij2; /* 10 */
1575 ckl = sth/nrkl2; /* 10 */
1577 for (m=0; m<DIM; m++) { /* 18+18 */
1578 f_i[m] = (c*r_kl[m]-cij*r_ij[m]);
1582 f_k[m] = (c*r_ij[m]-ckl*r_kl[m]);
1589 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
1592 rvec_inc(fshift[t1],f_i);
1593 rvec_dec(fshift[CENTRAL],f_i);
1596 ivec_sub(SHIFT_IVEC(g,ak),SHIFT_IVEC(g,al),dt);
1599 rvec_inc(fshift[t2],f_k);
1600 rvec_dec(fshift[CENTRAL],f_k);
1605 return vtot; /* 184 / 157 (bZAxis) total */
1608 real angres(int nbonds,
1609 const t_iatom forceatoms[],const t_iparams forceparams[],
1610 const rvec x[],rvec f[],rvec fshift[],
1611 const t_pbc *pbc,const t_graph *g,
1612 real lambda,real *dvdlambda,
1613 const t_mdatoms *md,t_fcdata *fcd,
1614 int *global_atom_index)
1616 return low_angres(nbonds,forceatoms,forceparams,x,f,fshift,pbc,g,
1617 lambda,dvdlambda,FALSE);
1620 real angresz(int nbonds,
1621 const t_iatom forceatoms[],const t_iparams forceparams[],
1622 const rvec x[],rvec f[],rvec fshift[],
1623 const t_pbc *pbc,const t_graph *g,
1624 real lambda,real *dvdlambda,
1625 const t_mdatoms *md,t_fcdata *fcd,
1626 int *global_atom_index)
1628 return low_angres(nbonds,forceatoms,forceparams,x,f,fshift,pbc,g,
1629 lambda,dvdlambda,TRUE);
1632 real dihres(int nbonds,
1633 const t_iatom forceatoms[],const t_iparams forceparams[],
1634 const rvec x[],rvec f[],rvec fshift[],
1635 const t_pbc *pbc,const t_graph *g,
1636 real lambda,real *dvdlambda,
1637 const t_mdatoms *md,t_fcdata *fcd,
1638 int *global_atom_index)
1641 int ai,aj,ak,al,i,k,type,t1,t2,t3;
1642 real phi0A,phi0B,dphiA,dphiB,kfacA,kfacB,phi0,dphi,kfac;
1643 real phi,ddphi,ddp,ddp2,dp,sign,d2r,fc,L1;
1644 rvec r_ij,r_kj,r_kl,m,n;
1651 for (i=0; (i<nbonds); )
1653 type = forceatoms[i++];
1654 ai = forceatoms[i++];
1655 aj = forceatoms[i++];
1656 ak = forceatoms[i++];
1657 al = forceatoms[i++];
1659 phi0A = forceparams[type].dihres.phiA*d2r;
1660 dphiA = forceparams[type].dihres.dphiA*d2r;
1661 kfacA = forceparams[type].dihres.kfacA;
1663 phi0B = forceparams[type].dihres.phiB*d2r;
1664 dphiB = forceparams[type].dihres.dphiB*d2r;
1665 kfacB = forceparams[type].dihres.kfacB;
1667 phi0 = L1*phi0A + lambda*phi0B;
1668 dphi = L1*dphiA + lambda*dphiB;
1669 kfac = L1*kfacA + lambda*kfacB;
1671 phi = dih_angle(x[ai],x[aj],x[ak],x[al],pbc,r_ij,r_kj,r_kl,m,n,
1677 fprintf(debug,"dihres[%d]: %d %d %d %d : phi=%f, dphi=%f, kfac=%f\n",
1678 k++,ai,aj,ak,al,phi0,dphi,kfac);
1680 /* phi can jump if phi0 is close to Pi/-Pi, which will cause huge
1681 * force changes if we just apply a normal harmonic.
1682 * Instead, we first calculate phi-phi0 and take it modulo (-Pi,Pi).
1683 * This means we will never have the periodicity problem, unless
1684 * the dihedral is Pi away from phiO, which is very unlikely due to
1688 make_dp_periodic(&dp);
1694 else if (dp < -dphi)
1706 vtot += 0.5*kfac*ddp2;
1709 *dvdlambda += 0.5*(kfacB - kfacA)*ddp2;
1710 /* lambda dependence from changing restraint distances */
1713 *dvdlambda -= kfac*ddp*((dphiB - dphiA)+(phi0B - phi0A));
1717 *dvdlambda += kfac*ddp*((dphiB - dphiA)-(phi0B - phi0A));
1719 do_dih_fup(ai,aj,ak,al,ddphi,r_ij,r_kj,r_kl,m,n,
1720 f,fshift,pbc,g,x,t1,t2,t3); /* 112 */
1727 real unimplemented(int nbonds,
1728 const t_iatom forceatoms[],const t_iparams forceparams[],
1729 const rvec x[],rvec f[],rvec fshift[],
1730 const t_pbc *pbc,const t_graph *g,
1731 real lambda,real *dvdlambda,
1732 const t_mdatoms *md,t_fcdata *fcd,
1733 int *global_atom_index)
1735 gmx_impl("*** you are using a not implemented function");
1737 return 0.0; /* To make the compiler happy */
1740 real rbdihs(int nbonds,
1741 const t_iatom forceatoms[],const t_iparams forceparams[],
1742 const rvec x[],rvec f[],rvec fshift[],
1743 const t_pbc *pbc,const t_graph *g,
1744 real lambda,real *dvdlambda,
1745 const t_mdatoms *md,t_fcdata *fcd,
1746 int *global_atom_index)
1748 const real c0=0.0,c1=1.0,c2=2.0,c3=3.0,c4=4.0,c5=5.0;
1749 int type,ai,aj,ak,al,i,j;
1751 rvec r_ij,r_kj,r_kl,m,n;
1752 real parmA[NR_RBDIHS];
1753 real parmB[NR_RBDIHS];
1754 real parm[NR_RBDIHS];
1755 real cos_phi,phi,rbp,rbpBA;
1756 real v,sign,ddphi,sin_phi;
1758 real L1 = 1.0-lambda;
1762 for(i=0; (i<nbonds); ) {
1763 type = forceatoms[i++];
1764 ai = forceatoms[i++];
1765 aj = forceatoms[i++];
1766 ak = forceatoms[i++];
1767 al = forceatoms[i++];
1769 phi=dih_angle(x[ai],x[aj],x[ak],x[al],pbc,r_ij,r_kj,r_kl,m,n,
1770 &sign,&t1,&t2,&t3); /* 84 */
1772 /* Change to polymer convention */
1776 phi -= M_PI; /* 1 */
1779 /* Beware of accuracy loss, cannot use 1-sqrt(cos^2) ! */
1782 for(j=0; (j<NR_RBDIHS); j++) {
1783 parmA[j] = forceparams[type].rbdihs.rbcA[j];
1784 parmB[j] = forceparams[type].rbdihs.rbcB[j];
1785 parm[j] = L1*parmA[j]+lambda*parmB[j];
1787 /* Calculate cosine powers */
1788 /* Calculate the energy */
1789 /* Calculate the derivative */
1792 dvdl_term += (parmB[0]-parmA[0]);
1797 rbpBA = parmB[1]-parmA[1];
1798 ddphi += rbp*cosfac;
1801 dvdl_term += cosfac*rbpBA;
1803 rbpBA = parmB[2]-parmA[2];
1804 ddphi += c2*rbp*cosfac;
1807 dvdl_term += cosfac*rbpBA;
1809 rbpBA = parmB[3]-parmA[3];
1810 ddphi += c3*rbp*cosfac;
1813 dvdl_term += cosfac*rbpBA;
1815 rbpBA = parmB[4]-parmA[4];
1816 ddphi += c4*rbp*cosfac;
1819 dvdl_term += cosfac*rbpBA;
1821 rbpBA = parmB[5]-parmA[5];
1822 ddphi += c5*rbp*cosfac;
1825 dvdl_term += cosfac*rbpBA;
1827 ddphi = -ddphi*sin_phi; /* 11 */
1829 do_dih_fup(ai,aj,ak,al,ddphi,r_ij,r_kj,r_kl,m,n,
1830 f,fshift,pbc,g,x,t1,t2,t3); /* 112 */
1833 *dvdlambda += dvdl_term;
1838 int cmap_setup_grid_index(int ip, int grid_spacing, int *ipm1, int *ipp1, int *ipp2)
1844 ip = ip + grid_spacing - 1;
1846 else if(ip > grid_spacing)
1848 ip = ip - grid_spacing - 1;
1857 im1 = grid_spacing - 1;
1859 else if(ip == grid_spacing-2)
1863 else if(ip == grid_spacing-1)
1877 real cmap_dihs(int nbonds,
1878 const t_iatom forceatoms[],const t_iparams forceparams[],
1879 const gmx_cmap_t *cmap_grid,
1880 const rvec x[],rvec f[],rvec fshift[],
1881 const t_pbc *pbc,const t_graph *g,
1882 real lambda,real *dvdlambda,
1883 const t_mdatoms *md,t_fcdata *fcd,
1884 int *global_atom_index)
1888 int a1i,a1j,a1k,a1l,a2i,a2j,a2k,a2l;
1890 int t11,t21,t31,t12,t22,t32;
1891 int iphi1,ip1m1,ip1p1,ip1p2;
1892 int iphi2,ip2m1,ip2p1,ip2p2;
1894 int pos1,pos2,pos3,pos4,tmp;
1896 real ty[4],ty1[4],ty2[4],ty12[4],tc[16],tx[16];
1897 real phi1,psi1,cos_phi1,sin_phi1,sign1,xphi1;
1898 real phi2,psi2,cos_phi2,sin_phi2,sign2,xphi2;
1899 real dx,xx,tt,tu,e,df1,df2,ddf1,ddf2,ddf12,vtot;
1900 real ra21,rb21,rg21,rg1,rgr1,ra2r1,rb2r1,rabr1;
1901 real ra22,rb22,rg22,rg2,rgr2,ra2r2,rb2r2,rabr2;
1902 real fg1,hg1,fga1,hgb1,gaa1,gbb1;
1903 real fg2,hg2,fga2,hgb2,gaa2,gbb2;
1906 rvec r1_ij, r1_kj, r1_kl,m1,n1;
1907 rvec r2_ij, r2_kj, r2_kl,m2,n2;
1908 rvec f1_i,f1_j,f1_k,f1_l;
1909 rvec f2_i,f2_j,f2_k,f2_l;
1911 rvec f1,g1,h1,f2,g2,h2;
1912 rvec dtf1,dtg1,dth1,dtf2,dtg2,dth2;
1913 ivec jt1,dt1_ij,dt1_kj,dt1_lj;
1914 ivec jt2,dt2_ij,dt2_kj,dt2_lj;
1918 int loop_index[4][4] = {
1925 /* Total CMAP energy */
1930 /* Five atoms are involved in the two torsions */
1931 type = forceatoms[n++];
1932 ai = forceatoms[n++];
1933 aj = forceatoms[n++];
1934 ak = forceatoms[n++];
1935 al = forceatoms[n++];
1936 am = forceatoms[n++];
1938 /* Which CMAP type is this */
1939 cmapA = forceparams[type].cmap.cmapA;
1940 cmapd = cmap_grid->cmapdata[cmapA].cmap;
1948 phi1 = dih_angle(x[a1i], x[a1j], x[a1k], x[a1l], pbc, r1_ij, r1_kj, r1_kl, m1, n1,
1949 &sign1, &t11, &t21, &t31); /* 84 */
1951 cos_phi1 = cos(phi1);
1953 a1[0] = r1_ij[1]*r1_kj[2]-r1_ij[2]*r1_kj[1];
1954 a1[1] = r1_ij[2]*r1_kj[0]-r1_ij[0]*r1_kj[2];
1955 a1[2] = r1_ij[0]*r1_kj[1]-r1_ij[1]*r1_kj[0]; /* 9 */
1957 b1[0] = r1_kl[1]*r1_kj[2]-r1_kl[2]*r1_kj[1];
1958 b1[1] = r1_kl[2]*r1_kj[0]-r1_kl[0]*r1_kj[2];
1959 b1[2] = r1_kl[0]*r1_kj[1]-r1_kl[1]*r1_kj[0]; /* 9 */
1961 tmp = pbc_rvec_sub(pbc,x[a1l],x[a1k],h1);
1963 ra21 = iprod(a1,a1); /* 5 */
1964 rb21 = iprod(b1,b1); /* 5 */
1965 rg21 = iprod(r1_kj,r1_kj); /* 5 */
1971 rabr1 = sqrt(ra2r1*rb2r1);
1973 sin_phi1 = rg1 * rabr1 * iprod(a1,h1) * (-1);
1975 if(cos_phi1 < -0.5 || cos_phi1 > 0.5)
1977 phi1 = asin(sin_phi1);
1987 phi1 = -M_PI - phi1;
1993 phi1 = acos(cos_phi1);
2001 xphi1 = phi1 + M_PI; /* 1 */
2003 /* Second torsion */
2009 phi2 = dih_angle(x[a2i], x[a2j], x[a2k], x[a2l], pbc, r2_ij, r2_kj, r2_kl, m2, n2,
2010 &sign2, &t12, &t22, &t32); /* 84 */
2012 cos_phi2 = cos(phi2);
2014 a2[0] = r2_ij[1]*r2_kj[2]-r2_ij[2]*r2_kj[1];
2015 a2[1] = r2_ij[2]*r2_kj[0]-r2_ij[0]*r2_kj[2];
2016 a2[2] = r2_ij[0]*r2_kj[1]-r2_ij[1]*r2_kj[0]; /* 9 */
2018 b2[0] = r2_kl[1]*r2_kj[2]-r2_kl[2]*r2_kj[1];
2019 b2[1] = r2_kl[2]*r2_kj[0]-r2_kl[0]*r2_kj[2];
2020 b2[2] = r2_kl[0]*r2_kj[1]-r2_kl[1]*r2_kj[0]; /* 9 */
2022 tmp = pbc_rvec_sub(pbc,x[a2l],x[a2k],h2);
2024 ra22 = iprod(a2,a2); /* 5 */
2025 rb22 = iprod(b2,b2); /* 5 */
2026 rg22 = iprod(r2_kj,r2_kj); /* 5 */
2032 rabr2 = sqrt(ra2r2*rb2r2);
2034 sin_phi2 = rg2 * rabr2 * iprod(a2,h2) * (-1);
2036 if(cos_phi2 < -0.5 || cos_phi2 > 0.5)
2038 phi2 = asin(sin_phi2);
2048 phi2 = -M_PI - phi2;
2054 phi2 = acos(cos_phi2);
2062 xphi2 = phi2 + M_PI; /* 1 */
2064 /* Range mangling */
2067 xphi1 = xphi1 + 2*M_PI;
2069 else if(xphi1>=2*M_PI)
2071 xphi1 = xphi1 - 2*M_PI;
2076 xphi2 = xphi2 + 2*M_PI;
2078 else if(xphi2>=2*M_PI)
2080 xphi2 = xphi2 - 2*M_PI;
2083 /* Number of grid points */
2084 dx = 2*M_PI / cmap_grid->grid_spacing;
2086 /* Where on the grid are we */
2087 iphi1 = (int)(xphi1/dx);
2088 iphi2 = (int)(xphi2/dx);
2090 iphi1 = cmap_setup_grid_index(iphi1, cmap_grid->grid_spacing, &ip1m1,&ip1p1,&ip1p2);
2091 iphi2 = cmap_setup_grid_index(iphi2, cmap_grid->grid_spacing, &ip2m1,&ip2p1,&ip2p2);
2093 pos1 = iphi1*cmap_grid->grid_spacing+iphi2;
2094 pos2 = ip1p1*cmap_grid->grid_spacing+iphi2;
2095 pos3 = ip1p1*cmap_grid->grid_spacing+ip2p1;
2096 pos4 = iphi1*cmap_grid->grid_spacing+ip2p1;
2098 ty[0] = cmapd[pos1*4];
2099 ty[1] = cmapd[pos2*4];
2100 ty[2] = cmapd[pos3*4];
2101 ty[3] = cmapd[pos4*4];
2103 ty1[0] = cmapd[pos1*4+1];
2104 ty1[1] = cmapd[pos2*4+1];
2105 ty1[2] = cmapd[pos3*4+1];
2106 ty1[3] = cmapd[pos4*4+1];
2108 ty2[0] = cmapd[pos1*4+2];
2109 ty2[1] = cmapd[pos2*4+2];
2110 ty2[2] = cmapd[pos3*4+2];
2111 ty2[3] = cmapd[pos4*4+2];
2113 ty12[0] = cmapd[pos1*4+3];
2114 ty12[1] = cmapd[pos2*4+3];
2115 ty12[2] = cmapd[pos3*4+3];
2116 ty12[3] = cmapd[pos4*4+3];
2118 /* Switch to degrees */
2119 dx = 360.0 / cmap_grid->grid_spacing;
2120 xphi1 = xphi1 * RAD2DEG;
2121 xphi2 = xphi2 * RAD2DEG;
2123 for(i=0;i<4;i++) /* 16 */
2126 tx[i+4] = ty1[i]*dx;
2127 tx[i+8] = ty2[i]*dx;
2128 tx[i+12] = ty12[i]*dx*dx;
2132 for(i=0;i<4;i++) /* 1056 */
2139 xx = xx + cmap_coeff_matrix[k*16+idx]*tx[k];
2147 tt = (xphi1-iphi1*dx)/dx;
2148 tu = (xphi2-iphi2*dx)/dx;
2159 l1 = loop_index[i][3];
2160 l2 = loop_index[i][2];
2161 l3 = loop_index[i][1];
2163 e = tt * e + ((tc[i*4+3]*tu+tc[i*4+2])*tu + tc[i*4+1])*tu+tc[i*4];
2164 df1 = tu * df1 + (3.0*tc[l1]*tt+2.0*tc[l2])*tt+tc[l3];
2165 df2 = tt * df2 + (3.0*tc[i*4+3]*tu+2.0*tc[i*4+2])*tu+tc[i*4+1];
2166 ddf1 = tu * ddf1 + 2.0*3.0*tc[l1]*tt+2.0*tc[l2];
2167 ddf2 = tt * ddf2 + 2.0*3.0*tc[4*i+3]*tu+2.0*tc[4*i+2];
2170 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) +
2171 3.0*tu*tu*(tc[7]+2.0*tc[11]*tt+3.0*tc[15]*tt*tt);
2176 ddf1 = ddf1 * fac * fac;
2177 ddf2 = ddf2 * fac * fac;
2178 ddf12 = ddf12 * fac * fac;
2183 /* Do forces - first torsion */
2184 fg1 = iprod(r1_ij,r1_kj);
2185 hg1 = iprod(r1_kl,r1_kj);
2186 fga1 = fg1*ra2r1*rgr1;
2187 hgb1 = hg1*rb2r1*rgr1;
2193 dtf1[i] = gaa1 * a1[i];
2194 dtg1[i] = fga1 * a1[i] - hgb1 * b1[i];
2195 dth1[i] = gbb1 * b1[i];
2197 f1[i] = df1 * dtf1[i];
2198 g1[i] = df1 * dtg1[i];
2199 h1[i] = df1 * dth1[i];
2202 f1_j[i] = -f1[i] - g1[i];
2203 f1_k[i] = h1[i] + g1[i];
2206 f[a1i][i] = f[a1i][i] + f1_i[i];
2207 f[a1j][i] = f[a1j][i] + f1_j[i]; /* - f1[i] - g1[i] */
2208 f[a1k][i] = f[a1k][i] + f1_k[i]; /* h1[i] + g1[i] */
2209 f[a1l][i] = f[a1l][i] + f1_l[i]; /* h1[i] */
2212 /* Do forces - second torsion */
2213 fg2 = iprod(r2_ij,r2_kj);
2214 hg2 = iprod(r2_kl,r2_kj);
2215 fga2 = fg2*ra2r2*rgr2;
2216 hgb2 = hg2*rb2r2*rgr2;
2222 dtf2[i] = gaa2 * a2[i];
2223 dtg2[i] = fga2 * a2[i] - hgb2 * b2[i];
2224 dth2[i] = gbb2 * b2[i];
2226 f2[i] = df2 * dtf2[i];
2227 g2[i] = df2 * dtg2[i];
2228 h2[i] = df2 * dth2[i];
2231 f2_j[i] = -f2[i] - g2[i];
2232 f2_k[i] = h2[i] + g2[i];
2235 f[a2i][i] = f[a2i][i] + f2_i[i]; /* f2[i] */
2236 f[a2j][i] = f[a2j][i] + f2_j[i]; /* - f2[i] - g2[i] */
2237 f[a2k][i] = f[a2k][i] + f2_k[i]; /* h2[i] + g2[i] */
2238 f[a2l][i] = f[a2l][i] + f2_l[i]; /* - h2[i] */
2244 copy_ivec(SHIFT_IVEC(g,a1j), jt1);
2245 ivec_sub(SHIFT_IVEC(g,a1i), jt1,dt1_ij);
2246 ivec_sub(SHIFT_IVEC(g,a1k), jt1,dt1_kj);
2247 ivec_sub(SHIFT_IVEC(g,a1l), jt1,dt1_lj);
2248 t11 = IVEC2IS(dt1_ij);
2249 t21 = IVEC2IS(dt1_kj);
2250 t31 = IVEC2IS(dt1_lj);
2252 copy_ivec(SHIFT_IVEC(g,a2j), jt2);
2253 ivec_sub(SHIFT_IVEC(g,a2i), jt2,dt2_ij);
2254 ivec_sub(SHIFT_IVEC(g,a2k), jt2,dt2_kj);
2255 ivec_sub(SHIFT_IVEC(g,a2l), jt2,dt2_lj);
2256 t12 = IVEC2IS(dt2_ij);
2257 t22 = IVEC2IS(dt2_kj);
2258 t32 = IVEC2IS(dt2_lj);
2262 t31 = pbc_rvec_sub(pbc,x[a1l],x[a1j],h1);
2263 t32 = pbc_rvec_sub(pbc,x[a2l],x[a2j],h2);
2271 rvec_inc(fshift[t11],f1_i);
2272 rvec_inc(fshift[CENTRAL],f1_j);
2273 rvec_inc(fshift[t21],f1_k);
2274 rvec_inc(fshift[t31],f1_l);
2276 rvec_inc(fshift[t21],f2_i);
2277 rvec_inc(fshift[CENTRAL],f2_j);
2278 rvec_inc(fshift[t22],f2_k);
2279 rvec_inc(fshift[t32],f2_l);
2286 /***********************************************************
2288 * G R O M O S 9 6 F U N C T I O N S
2290 ***********************************************************/
2291 real g96harmonic(real kA,real kB,real xA,real xB,real x,real lambda,
2294 const real half=0.5;
2295 real L1,kk,x0,dx,dx2;
2299 kk = L1*kA+lambda*kB;
2300 x0 = L1*xA+lambda*xB;
2307 dvdlambda = half*(kB-kA)*dx2 + (xA-xB)*kk*dx;
2314 /* That was 21 flops */
2317 real g96bonds(int nbonds,
2318 const t_iatom forceatoms[],const t_iparams forceparams[],
2319 const rvec x[],rvec f[],rvec fshift[],
2320 const t_pbc *pbc,const t_graph *g,
2321 real lambda,real *dvdlambda,
2322 const t_mdatoms *md,t_fcdata *fcd,
2323 int *global_atom_index)
2325 int i,m,ki,ai,aj,type;
2326 real dr2,fbond,vbond,fij,vtot;
2331 for(i=0; (i<nbonds); ) {
2332 type = forceatoms[i++];
2333 ai = forceatoms[i++];
2334 aj = forceatoms[i++];
2336 ki = pbc_rvec_sub(pbc,x[ai],x[aj],dx); /* 3 */
2337 dr2 = iprod(dx,dx); /* 5 */
2339 *dvdlambda += g96harmonic(forceparams[type].harmonic.krA,
2340 forceparams[type].harmonic.krB,
2341 forceparams[type].harmonic.rA,
2342 forceparams[type].harmonic.rB,
2343 dr2,lambda,&vbond,&fbond);
2345 vtot += 0.5*vbond; /* 1*/
2348 fprintf(debug,"G96-BONDS: dr = %10g vbond = %10g fbond = %10g\n",
2349 sqrt(dr2),vbond,fbond);
2353 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
2356 for (m=0; (m<DIM); m++) { /* 15 */
2361 fshift[CENTRAL][m]-=fij;
2367 real g96bond_angle(const rvec xi,const rvec xj,const rvec xk,const t_pbc *pbc,
2368 rvec r_ij,rvec r_kj,
2370 /* Return value is the angle between the bonds i-j and j-k */
2374 *t1 = pbc_rvec_sub(pbc,xi,xj,r_ij); /* 3 */
2375 *t2 = pbc_rvec_sub(pbc,xk,xj,r_kj); /* 3 */
2377 costh=cos_angle(r_ij,r_kj); /* 25 */
2382 real g96angles(int nbonds,
2383 const t_iatom forceatoms[],const t_iparams forceparams[],
2384 const rvec x[],rvec f[],rvec fshift[],
2385 const t_pbc *pbc,const t_graph *g,
2386 real lambda,real *dvdlambda,
2387 const t_mdatoms *md,t_fcdata *fcd,
2388 int *global_atom_index)
2390 int i,ai,aj,ak,type,m,t1,t2;
2392 real cos_theta,dVdt,va,vtot;
2393 real rij_1,rij_2,rkj_1,rkj_2,rijrkj_1;
2395 ivec jt,dt_ij,dt_kj;
2398 for(i=0; (i<nbonds); ) {
2399 type = forceatoms[i++];
2400 ai = forceatoms[i++];
2401 aj = forceatoms[i++];
2402 ak = forceatoms[i++];
2404 cos_theta = g96bond_angle(x[ai],x[aj],x[ak],pbc,r_ij,r_kj,&t1,&t2);
2406 *dvdlambda += g96harmonic(forceparams[type].harmonic.krA,
2407 forceparams[type].harmonic.krB,
2408 forceparams[type].harmonic.rA,
2409 forceparams[type].harmonic.rB,
2410 cos_theta,lambda,&va,&dVdt);
2413 rij_1 = gmx_invsqrt(iprod(r_ij,r_ij));
2414 rkj_1 = gmx_invsqrt(iprod(r_kj,r_kj));
2415 rij_2 = rij_1*rij_1;
2416 rkj_2 = rkj_1*rkj_1;
2417 rijrkj_1 = rij_1*rkj_1; /* 23 */
2421 fprintf(debug,"G96ANGLES: costheta = %10g vth = %10g dV/dct = %10g\n",
2424 for (m=0; (m<DIM); m++) { /* 42 */
2425 f_i[m]=dVdt*(r_kj[m]*rijrkj_1 - r_ij[m]*rij_2*cos_theta);
2426 f_k[m]=dVdt*(r_ij[m]*rijrkj_1 - r_kj[m]*rkj_2*cos_theta);
2427 f_j[m]=-f_i[m]-f_k[m];
2434 copy_ivec(SHIFT_IVEC(g,aj),jt);
2436 ivec_sub(SHIFT_IVEC(g,ai),jt,dt_ij);
2437 ivec_sub(SHIFT_IVEC(g,ak),jt,dt_kj);
2441 rvec_inc(fshift[t1],f_i);
2442 rvec_inc(fshift[CENTRAL],f_j);
2443 rvec_inc(fshift[t2],f_k); /* 9 */
2449 real cross_bond_bond(int nbonds,
2450 const t_iatom forceatoms[],const t_iparams forceparams[],
2451 const rvec x[],rvec f[],rvec fshift[],
2452 const t_pbc *pbc,const t_graph *g,
2453 real lambda,real *dvdlambda,
2454 const t_mdatoms *md,t_fcdata *fcd,
2455 int *global_atom_index)
2457 /* Potential from Lawrence and Skimmer, Chem. Phys. Lett. 372 (2003)
2460 int i,ai,aj,ak,type,m,t1,t2;
2462 real vtot,vrr,s1,s2,r1,r2,r1e,r2e,krr;
2464 ivec jt,dt_ij,dt_kj;
2467 for(i=0; (i<nbonds); ) {
2468 type = forceatoms[i++];
2469 ai = forceatoms[i++];
2470 aj = forceatoms[i++];
2471 ak = forceatoms[i++];
2472 r1e = forceparams[type].cross_bb.r1e;
2473 r2e = forceparams[type].cross_bb.r2e;
2474 krr = forceparams[type].cross_bb.krr;
2476 /* Compute distance vectors ... */
2477 t1 = pbc_rvec_sub(pbc,x[ai],x[aj],r_ij);
2478 t2 = pbc_rvec_sub(pbc,x[ak],x[aj],r_kj);
2480 /* ... and their lengths */
2484 /* Deviations from ideality */
2488 /* Energy (can be negative!) */
2493 svmul(-krr*s2/r1,r_ij,f_i);
2494 svmul(-krr*s1/r2,r_kj,f_k);
2496 for (m=0; (m<DIM); m++) { /* 12 */
2497 f_j[m] = -f_i[m] - f_k[m];
2505 copy_ivec(SHIFT_IVEC(g,aj),jt);
2507 ivec_sub(SHIFT_IVEC(g,ai),jt,dt_ij);
2508 ivec_sub(SHIFT_IVEC(g,ak),jt,dt_kj);
2512 rvec_inc(fshift[t1],f_i);
2513 rvec_inc(fshift[CENTRAL],f_j);
2514 rvec_inc(fshift[t2],f_k); /* 9 */
2520 real cross_bond_angle(int nbonds,
2521 const t_iatom forceatoms[],const t_iparams forceparams[],
2522 const rvec x[],rvec f[],rvec fshift[],
2523 const t_pbc *pbc,const t_graph *g,
2524 real lambda,real *dvdlambda,
2525 const t_mdatoms *md,t_fcdata *fcd,
2526 int *global_atom_index)
2528 /* Potential from Lawrence and Skimmer, Chem. Phys. Lett. 372 (2003)
2531 int i,ai,aj,ak,type,m,t1,t2,t3;
2532 rvec r_ij,r_kj,r_ik;
2533 real vtot,vrt,s1,s2,s3,r1,r2,r3,r1e,r2e,r3e,krt,k1,k2,k3;
2535 ivec jt,dt_ij,dt_kj;
2538 for(i=0; (i<nbonds); ) {
2539 type = forceatoms[i++];
2540 ai = forceatoms[i++];
2541 aj = forceatoms[i++];
2542 ak = forceatoms[i++];
2543 r1e = forceparams[type].cross_ba.r1e;
2544 r2e = forceparams[type].cross_ba.r2e;
2545 r3e = forceparams[type].cross_ba.r3e;
2546 krt = forceparams[type].cross_ba.krt;
2548 /* Compute distance vectors ... */
2549 t1 = pbc_rvec_sub(pbc,x[ai],x[aj],r_ij);
2550 t2 = pbc_rvec_sub(pbc,x[ak],x[aj],r_kj);
2551 t3 = pbc_rvec_sub(pbc,x[ai],x[ak],r_ik);
2553 /* ... and their lengths */
2558 /* Deviations from ideality */
2563 /* Energy (can be negative!) */
2564 vrt = krt*s3*(s1+s2);
2570 k3 = -krt*(s1+s2)/r3;
2571 for(m=0; (m<DIM); m++) {
2572 f_i[m] = k1*r_ij[m] + k3*r_ik[m];
2573 f_k[m] = k2*r_kj[m] - k3*r_ik[m];
2574 f_j[m] = -f_i[m] - f_k[m];
2577 for (m=0; (m<DIM); m++) { /* 12 */
2585 copy_ivec(SHIFT_IVEC(g,aj),jt);
2587 ivec_sub(SHIFT_IVEC(g,ai),jt,dt_ij);
2588 ivec_sub(SHIFT_IVEC(g,ak),jt,dt_kj);
2592 rvec_inc(fshift[t1],f_i);
2593 rvec_inc(fshift[CENTRAL],f_j);
2594 rvec_inc(fshift[t2],f_k); /* 9 */
2600 static real bonded_tab(const char *type,int table_nr,
2601 const bondedtable_t *table,real kA,real kB,real r,
2602 real lambda,real *V,real *F)
2604 real k,tabscale,*VFtab,rt,eps,eps2,Yt,Ft,Geps,Heps2,Fp,VV,FF;
2608 k = (1.0 - lambda)*kA + lambda*kB;
2610 tabscale = table->scale;
2615 if (n0 >= table->n) {
2616 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",
2617 type,table_nr,r,n0,n0+1,table->n);
2624 Geps = VFtab[nnn+2]*eps;
2625 Heps2 = VFtab[nnn+3]*eps2;
2626 Fp = Ft + Geps + Heps2;
2628 FF = Fp + Geps + 2.0*Heps2;
2630 *F = -k*FF*tabscale;
2632 dvdlambda = (kB - kA)*VV;
2636 /* That was 22 flops */
2639 real tab_bonds(int nbonds,
2640 const t_iatom forceatoms[],const t_iparams forceparams[],
2641 const rvec x[],rvec f[],rvec fshift[],
2642 const t_pbc *pbc,const t_graph *g,
2643 real lambda,real *dvdlambda,
2644 const t_mdatoms *md,t_fcdata *fcd,
2645 int *global_atom_index)
2647 int i,m,ki,ai,aj,type,table;
2648 real dr,dr2,fbond,vbond,fij,vtot;
2653 for(i=0; (i<nbonds); ) {
2654 type = forceatoms[i++];
2655 ai = forceatoms[i++];
2656 aj = forceatoms[i++];
2658 ki = pbc_rvec_sub(pbc,x[ai],x[aj],dx); /* 3 */
2659 dr2 = iprod(dx,dx); /* 5 */
2660 dr = dr2*gmx_invsqrt(dr2); /* 10 */
2662 table = forceparams[type].tab.table;
2664 *dvdlambda += bonded_tab("bond",table,
2665 &fcd->bondtab[table],
2666 forceparams[type].tab.kA,
2667 forceparams[type].tab.kB,
2668 dr,lambda,&vbond,&fbond); /* 22 */
2674 vtot += vbond;/* 1*/
2675 fbond *= gmx_invsqrt(dr2); /* 6 */
2678 fprintf(debug,"TABBONDS: dr = %10g vbond = %10g fbond = %10g\n",
2682 ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
2685 for (m=0; (m<DIM); m++) { /* 15 */
2690 fshift[CENTRAL][m]-=fij;
2696 real tab_angles(int nbonds,
2697 const t_iatom forceatoms[],const t_iparams forceparams[],
2698 const rvec x[],rvec f[],rvec fshift[],
2699 const t_pbc *pbc,const t_graph *g,
2700 real lambda,real *dvdlambda,
2701 const t_mdatoms *md,t_fcdata *fcd,
2702 int *global_atom_index)
2704 int i,ai,aj,ak,t1,t2,type,table;
2706 real cos_theta,cos_theta2,theta,dVdt,va,vtot;
2707 ivec jt,dt_ij,dt_kj;
2710 for(i=0; (i<nbonds); ) {
2711 type = forceatoms[i++];
2712 ai = forceatoms[i++];
2713 aj = forceatoms[i++];
2714 ak = forceatoms[i++];
2716 theta = bond_angle(x[ai],x[aj],x[ak],pbc,
2717 r_ij,r_kj,&cos_theta,&t1,&t2); /* 41 */
2719 table = forceparams[type].tab.table;
2721 *dvdlambda += bonded_tab("angle",table,
2722 &fcd->angletab[table],
2723 forceparams[type].tab.kA,
2724 forceparams[type].tab.kB,
2725 theta,lambda,&va,&dVdt); /* 22 */
2728 cos_theta2 = sqr(cos_theta); /* 1 */
2729 if (cos_theta2 < 1) {
2736 st = dVdt*gmx_invsqrt(1 - cos_theta2); /* 12 */
2737 sth = st*cos_theta; /* 1 */
2740 fprintf(debug,"ANGLES: theta = %10g vth = %10g dV/dtheta = %10g\n",
2741 theta*RAD2DEG,va,dVdt);
2743 nrkj2=iprod(r_kj,r_kj); /* 5 */
2744 nrij2=iprod(r_ij,r_ij);
2746 cik=st*gmx_invsqrt(nrkj2*nrij2); /* 12 */
2747 cii=sth/nrij2; /* 10 */
2748 ckk=sth/nrkj2; /* 10 */
2750 for (m=0; (m<DIM); m++) { /* 39 */
2751 f_i[m]=-(cik*r_kj[m]-cii*r_ij[m]);
2752 f_k[m]=-(cik*r_ij[m]-ckk*r_kj[m]);
2753 f_j[m]=-f_i[m]-f_k[m];
2759 copy_ivec(SHIFT_IVEC(g,aj),jt);
2761 ivec_sub(SHIFT_IVEC(g,ai),jt,dt_ij);
2762 ivec_sub(SHIFT_IVEC(g,ak),jt,dt_kj);
2766 rvec_inc(fshift[t1],f_i);
2767 rvec_inc(fshift[CENTRAL],f_j);
2768 rvec_inc(fshift[t2],f_k);
2774 real tab_dihs(int nbonds,
2775 const t_iatom forceatoms[],const t_iparams forceparams[],
2776 const rvec x[],rvec f[],rvec fshift[],
2777 const t_pbc *pbc,const t_graph *g,
2778 real lambda,real *dvdlambda,
2779 const t_mdatoms *md,t_fcdata *fcd,
2780 int *global_atom_index)
2782 int i,type,ai,aj,ak,al,table;
2784 rvec r_ij,r_kj,r_kl,m,n;
2785 real phi,sign,ddphi,vpd,vtot;
2788 for(i=0; (i<nbonds); ) {
2789 type = forceatoms[i++];
2790 ai = forceatoms[i++];
2791 aj = forceatoms[i++];
2792 ak = forceatoms[i++];
2793 al = forceatoms[i++];
2795 phi=dih_angle(x[ai],x[aj],x[ak],x[al],pbc,r_ij,r_kj,r_kl,m,n,
2796 &sign,&t1,&t2,&t3); /* 84 */
2798 table = forceparams[type].tab.table;
2800 /* Hopefully phi+M_PI never results in values < 0 */
2801 *dvdlambda += bonded_tab("dihedral",table,
2802 &fcd->dihtab[table],
2803 forceparams[type].tab.kA,
2804 forceparams[type].tab.kB,
2805 phi+M_PI,lambda,&vpd,&ddphi);
2808 do_dih_fup(ai,aj,ak,al,-ddphi,r_ij,r_kj,r_kl,m,n,
2809 f,fshift,pbc,g,x,t1,t2,t3); /* 112 */
2812 fprintf(debug,"pdih: (%d,%d,%d,%d) phi=%g\n",
2820 real calc_one_bond(FILE *fplog,int ftype, const t_idef *idef,
2821 rvec x[], rvec f[], t_forcerec *fr,
2822 const t_pbc *pbc,const t_graph *g,
2823 gmx_enerdata_t *enerd, t_nrnb *nrnb,
2824 real *lambda, real *dvdl,
2825 const t_mdatoms *md,t_fcdata *fcd,
2826 int *global_atom_index, gmx_bool bPrintSepPot)
2828 int ind,nat1,nbonds,efptFTYPE;
2832 if (IS_RESTRAINT_TYPE(ftype))
2834 efptFTYPE = efptRESTRAINT;
2838 efptFTYPE = efptBONDED;
2841 if (ftype<F_GB12 || ftype>F_GB14)
2843 if (interaction_function[ftype].flags & IF_BOND &&
2844 !(ftype == F_CONNBONDS || ftype == F_POSRES))
2846 ind = interaction_function[ftype].nrnb_ind;
2847 nat1 = interaction_function[ftype].nratoms+1;
2848 nbonds = idef->il[ftype].nr;
2849 iatoms = idef->il[ftype].iatoms;
2852 if (ftype < F_LJ14 || ftype > F_LJC_PAIRS_NB)
2856 v = cmap_dihs(nbonds,iatoms,
2857 idef->iparams,&idef->cmap_grid,
2858 (const rvec*)x,f,fr->fshift,
2859 pbc,g,lambda[efptFTYPE],&(dvdl[efptFTYPE]),
2860 md,fcd,global_atom_index);
2864 v = interaction_function[ftype].ifunc(nbonds,iatoms,
2866 (const rvec*)x,f,fr->fshift,
2867 pbc,g,lambda[efptFTYPE],&(dvdl[efptFTYPE]),
2868 md,fcd,global_atom_index);
2870 enerd->dvdl_nonlin[efptFTYPE] += dvdl[efptFTYPE];
2873 fprintf(fplog," %-23s #%4d V %12.5e dVdl %12.5e\n",
2874 interaction_function[ftype].longname,
2875 nbonds/nat1,v,lambda[efptFTYPE]);
2880 v = do_listed_vdw_q(ftype,nbonds,iatoms,
2882 (const rvec*)x,f,fr->fshift,
2884 md,fr,&enerd->grpp,global_atom_index);
2885 enerd->dvdl_nonlin[efptCOUL] += dvdl[efptCOUL];
2886 enerd->dvdl_nonlin[efptVDW] += dvdl[efptVDW];
2890 fprintf(fplog," %-5s + %-15s #%4d dVdl %12.5e\n",
2891 interaction_function[ftype].longname,
2892 interaction_function[F_LJ14].longname,nbonds/nat1,dvdl[efptVDW]);
2893 fprintf(fplog," %-5s + %-15s #%4d dVdl %12.5e\n",
2894 interaction_function[ftype].longname,
2895 interaction_function[F_COUL14].longname,nbonds/nat1,dvdl[efptCOUL]);
2900 inc_nrnb(nrnb,ind,nbonds/nat1);
2908 /* WARNING! THIS FUNCTION MUST EXACTLY TRACK THE calc_one_bond
2909 function, or horrible things will happen when doing free energy
2910 calculations! In a good coding world, this would not be a
2911 different function, but for speed reasons, it needs to be made a
2912 separate function. TODO for 5.0 - figure out a way to reorganize
2913 to reduce duplication.
2916 real calc_one_bond_foreign(FILE *fplog,int ftype, const t_idef *idef,
2917 rvec x[], rvec f[], t_forcerec *fr,
2918 const t_pbc *pbc,const t_graph *g,
2919 gmx_enerdata_t *enerd, t_nrnb *nrnb,
2920 real *lambda, real *dvdl,
2921 const t_mdatoms *md,t_fcdata *fcd,
2922 int *global_atom_index, gmx_bool bPrintSepPot)
2924 int ind,nat1,nbonds,efptFTYPE,nbonds_np;
2928 if (IS_RESTRAINT_TYPE(ftype))
2930 efptFTYPE = efptRESTRAINT;
2934 efptFTYPE = efptBONDED;
2937 if (ftype<F_GB12 || ftype>F_GB14)
2939 if (interaction_function[ftype].flags & IF_BOND &&
2940 !(ftype == F_CONNBONDS || ftype == F_POSRES))
2942 ind = interaction_function[ftype].nrnb_ind;
2943 nat1 = interaction_function[ftype].nratoms+1;
2944 nbonds_np = idef->il[ftype].nr_nonperturbed;
2945 nbonds = idef->il[ftype].nr - nbonds_np;
2946 iatoms = idef->il[ftype].iatoms + nbonds_np;
2949 if (ftype < F_LJ14 || ftype > F_LJC_PAIRS_NB)
2953 v = cmap_dihs(nbonds,iatoms,
2954 idef->iparams,&idef->cmap_grid,
2955 (const rvec*)x,f,fr->fshift,
2956 pbc,g,lambda[efptFTYPE],&(dvdl[efptFTYPE]),md,fcd,
2961 v = interaction_function[ftype].ifunc(nbonds,iatoms,
2963 (const rvec*)x,f,fr->fshift,
2964 pbc,g,lambda[efptFTYPE],&dvdl[efptFTYPE],
2965 md,fcd,global_atom_index);
2970 v = do_listed_vdw_q(ftype,nbonds,iatoms,
2972 (const rvec*)x,f,fr->fshift,
2974 md,fr,&enerd->grpp,global_atom_index);
2978 inc_nrnb(nrnb,ind,nbonds/nat1);
2986 void calc_bonds(FILE *fplog,const gmx_multisim_t *ms,
2988 rvec x[],history_t *hist,
2989 rvec f[],t_forcerec *fr,
2990 const t_pbc *pbc,const t_graph *g,
2991 gmx_enerdata_t *enerd,t_nrnb *nrnb,
2993 const t_mdatoms *md,
2994 t_fcdata *fcd,int *global_atom_index,
2995 t_atomtypes *atype, gmx_genborn_t *born,
2996 gmx_bool bPrintSepPot,gmx_large_int_t step)
2998 int i,ftype,nbonds,ind,nat;
2999 real v,dvdl[efptNR],dvdl_dum[efptNR]; /* The dummy array is to have a place to store the dhdl at other values
3000 of lambda, which will be thrown away in the end*/
3002 const t_pbc *pbc_null;
3005 for (i=0;i<efptNR;i++)
3019 fprintf(fplog,"Step %s: bonded V and dVdl for this node\n",
3020 gmx_step_str(step,buf));
3026 p_graph(debug,"Bondage is fun",g);
3032 /* Do pre force calculation stuff which might require communication */
3033 if (idef->il[F_ORIRES].nr) {
3034 epot[F_ORIRESDEV] = calc_orires_dev(ms,idef->il[F_ORIRES].nr,
3035 idef->il[F_ORIRES].iatoms,
3036 idef->iparams,md,(const rvec*)x,
3039 if (idef->il[F_DISRES].nr) {
3040 calc_disres_R_6(ms,idef->il[F_DISRES].nr,
3041 idef->il[F_DISRES].iatoms,
3042 idef->iparams,(const rvec*)x,pbc_null,
3046 /* Loop over all bonded force types to calculate the bonded forces */
3047 for(ftype=0; (ftype<F_NRE); ftype++)
3049 v = calc_one_bond(fplog,ftype,idef,x,
3050 f,fr,pbc_null,g,enerd,nrnb,lambda,dvdl,
3051 md,fcd,global_atom_index,bPrintSepPot);
3054 /* Copy the sum of violations for the distance restraints from fcd */
3057 epot[F_DISRESVIOL] = fcd->disres.sumviol;
3061 void calc_bonds_lambda(FILE *fplog,
3065 const t_pbc *pbc,const t_graph *g,
3066 gmx_enerdata_t *enerd,t_nrnb *nrnb,
3068 const t_mdatoms *md,
3070 int *global_atom_index)
3072 int i,ftype,nbonds_np,nbonds,ind,nat;
3073 real v,dr,dr2,*epot;
3074 real dvdl_dum[efptNR];
3075 rvec *f,*fshift_orig;
3076 const t_pbc *pbc_null;
3090 snew(f,fr->natoms_force);
3091 /* We want to preserve the fshift array in forcerec */
3092 fshift_orig = fr->fshift;
3093 snew(fr->fshift,SHIFTS);
3095 /* Loop over all bonded force types to calculate the bonded forces */
3096 for(ftype=0; (ftype<F_NRE); ftype++)
3098 v = calc_one_bond_foreign(fplog,ftype,idef,x,
3099 f,fr,pbc_null,g,enerd,nrnb,lambda,dvdl_dum,
3100 md,fcd,global_atom_index,FALSE);
3105 fr->fshift = fshift_orig;