Fixing copyright issues and code contributors
[alexxy/gromacs.git] / src / mdlib / shakef.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team,
6  * check out http://www.gromacs.org for more information.
7  * Copyright (c) 2012,2013, by the GROMACS development team, led by
8  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9  * others, as listed in the AUTHORS file in the top-level source
10  * directory and at http://www.gromacs.org.
11  *
12  * GROMACS is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public License
14  * as published by the Free Software Foundation; either version 2.1
15  * of the License, or (at your option) any later version.
16  *
17  * GROMACS is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with GROMACS; if not, see
24  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
26  *
27  * If you want to redistribute modifications to GROMACS, please
28  * consider that scientific software is very special. Version
29  * control is crucial - bugs must be traceable. We will be happy to
30  * consider code for inclusion in the official distribution, but
31  * derived work must not be called official GROMACS. Details are found
32  * in the README & COPYING files - if they are missing, get the
33  * official version at http://www.gromacs.org.
34  *
35  * To help us fund GROMACS development, we humbly ask that you cite
36  * the research papers on the package. Check out http://www.gromacs.org.
37  */
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42 #include <math.h>
43 #include "sysstuff.h"
44 #include "typedefs.h"
45 #include "smalloc.h"
46 #include "pbc.h"
47 #include "txtdump.h"
48 #include "vec.h"
49 #include "nrnb.h"
50 #include "constr.h"
51
52 typedef struct gmx_shakedata
53 {
54     rvec *rij;
55     real *M2;
56     real *tt;
57     real *dist2;
58     int  nalloc;
59     /* SOR stuff */
60     real delta;
61     real omega;
62     real gamma;
63 } t_gmx_shakedata;
64
65 gmx_shakedata_t shake_init()
66 {
67     gmx_shakedata_t d;
68
69     snew(d,1);
70
71     d->nalloc = 0;
72     d->rij    = NULL;
73     d->M2     = NULL;
74     d->tt     = NULL;
75     d->dist2  = NULL;
76
77     /* SOR initialization */
78     d->delta = 0.1;
79     d->omega = 1.0;
80     d->gamma = 1000000;
81
82     return d;
83 }
84
85 static void pv(FILE *log,char *s,rvec x)
86 {
87   int m;
88
89   fprintf(log,"%5s:",s);
90   for(m=0; (m<DIM); m++)
91     fprintf(log,"  %10.3f",x[m]);
92   fprintf(log,"\n");
93   fflush(log);
94 }
95
96 void cshake(atom_id iatom[],int ncon,int *nnit,int maxnit,
97             real dist2[],real xp[],real rij[],real m2[],real omega,
98             real invmass[],real tt[],real lagr[],int *nerror)
99 {
100   /*
101    *     r.c. van schaik and w.f. van gunsteren
102    *     eth zuerich
103    *     june 1992
104    *     Adapted for use with Gromacs by David van der Spoel november 92 and later.
105    */
106   /* default should be increased! MRS 8/4/2009 */
107   const   real mytol=1e-10;
108   
109   int     ll,i,j,i3,j3,l3;
110   int     ix,iy,iz,jx,jy,jz;
111   real    toler,rpij2,rrpr,tx,ty,tz,diff,acor,im,jm;
112   real    xh,yh,zh,rijx,rijy,rijz;
113   real    tix,tiy,tiz;
114   real    tjx,tjy,tjz;
115   int     nit,error,nconv;
116   real    iconvf;
117
118   error=0;
119   nconv=1;
120   for (nit=0; (nit<maxnit) && (nconv != 0) && (error == 0); nit++) {
121     nconv=0;
122     for(ll=0; (ll<ncon) && (error == 0); ll++) {
123       l3    = 3*ll;
124       rijx  = rij[l3+XX];
125       rijy  = rij[l3+YY];
126       rijz  = rij[l3+ZZ];
127       i     = iatom[l3+1];
128       j     = iatom[l3+2];
129       i3    = 3*i;
130       j3    = 3*j;
131       ix    = i3+XX;
132       iy    = i3+YY;
133       iz    = i3+ZZ;
134       jx    = j3+XX;
135       jy    = j3+YY;
136       jz    = j3+ZZ;
137       
138       tx      = xp[ix]-xp[jx];
139       ty      = xp[iy]-xp[jy];
140       tz      = xp[iz]-xp[jz];
141       rpij2   = tx*tx+ty*ty+tz*tz;
142       toler   = dist2[ll];
143       diff    = toler-rpij2;
144       
145       /* iconvf is less than 1 when the error is smaller than a bound */
146       /* But if tt is too big, then it will result in looping in iconv */
147
148       iconvf = fabs(diff)*tt[ll];
149       
150       if (iconvf > 1) {
151           nconv   = iconvf;
152           rrpr    = rijx*tx+rijy*ty+rijz*tz;
153         
154           if (rrpr < toler*mytol) 
155               error=ll+1;
156           else {
157               acor      = omega*diff*m2[ll]/rrpr;
158               lagr[ll] += acor;
159               xh        = rijx*acor;
160               yh        = rijy*acor;
161               zh        = rijz*acor;
162               im        = invmass[i];
163               jm        = invmass[j];
164               xp[ix] += xh*im;
165               xp[iy] += yh*im;
166               xp[iz] += zh*im;
167               xp[jx] -= xh*jm;
168               xp[jy] -= yh*jm;
169               xp[jz] -= zh*jm;
170           }
171       }
172     }
173   }
174   *nnit=nit;
175   *nerror=error;
176 }
177
178 int vec_shakef(FILE *fplog,gmx_shakedata_t shaked,
179                int natoms,real invmass[],int ncon,
180                t_iparams ip[],t_iatom *iatom,
181                real tol,rvec x[],rvec prime[],real omega,
182                gmx_bool bFEP,real lambda,real lagr[],
183                real invdt,rvec *v,
184                gmx_bool bCalcVir,tensor vir_r_m_dr,int econq, 
185                t_vetavars *vetavar)
186 {
187     rvec *rij;
188     real *M2,*tt,*dist2;
189     int     maxnit=1000;
190     int     nit=0,ll,i,j,type;
191     t_iatom *ia;
192     real    L1,tol2,toler;
193     real    mm=0.,tmp;
194     int     error=0;
195     real    g,vscale,rscale,rvscale;
196
197     if (ncon > shaked->nalloc)
198     {
199         shaked->nalloc = over_alloc_dd(ncon);
200         srenew(shaked->rij,shaked->nalloc);
201         srenew(shaked->M2,shaked->nalloc);
202         srenew(shaked->tt,shaked->nalloc);
203         srenew(shaked->dist2,shaked->nalloc);
204     }
205     rij   = shaked->rij;
206     M2    = shaked->M2;
207     tt    = shaked->tt;
208     dist2 = shaked->dist2;
209
210     L1=1.0-lambda;
211     tol2=2.0*tol;
212     ia=iatom;
213     for(ll=0; (ll<ncon); ll++,ia+=3) {
214         type  = ia[0];
215         i=ia[1];
216         j=ia[2];
217         
218         mm=2*(invmass[i]+invmass[j]);
219         rij[ll][XX]=x[i][XX]-x[j][XX];
220         rij[ll][YY]=x[i][YY]-x[j][YY];
221         rij[ll][ZZ]=x[i][ZZ]-x[j][ZZ];
222         M2[ll]=1.0/mm;
223         if (bFEP) 
224             toler = sqr(L1*ip[type].constr.dA + lambda*ip[type].constr.dB);
225         else
226             toler = sqr(ip[type].constr.dA);
227         dist2[ll] = toler;
228         tt[ll] = 1.0/(toler*tol2);
229     }
230     
231     switch (econq) {
232     case econqCoord:
233         cshake(iatom,ncon,&nit,maxnit,dist2,prime[0],rij[0],M2,omega,invmass,tt,lagr,&error);
234         break;
235     case econqVeloc:
236         crattle(iatom,ncon,&nit,maxnit,dist2,prime[0],rij[0],M2,omega,invmass,tt,lagr,&error,invdt,vetavar);
237         break;
238     }
239     
240     if (nit >= maxnit) {
241         if (fplog) {
242             fprintf(fplog,"Shake did not converge in %d steps\n",maxnit);
243         }
244         fprintf(stderr,"Shake did not converge in %d steps\n",maxnit);
245         nit=0;
246     }
247     else if (error != 0) 
248     {
249         if (fplog)
250             fprintf(fplog,"Inner product between old and new vector <= 0.0!\n"
251                     "constraint #%d atoms %u and %u\n",
252                     error-1,iatom[3*(error-1)+1]+1,iatom[3*(error-1)+2]+1);
253         fprintf(stderr,"Inner product between old and new vector <= 0.0!\n"
254                 "constraint #%d atoms %u and %u\n",
255                 error-1,iatom[3*(error-1)+1]+1,iatom[3*(error-1)+2]+1);
256         nit=0;
257     }
258     
259     /* Constraint virial and correct the lagrange multipliers for the length */
260     
261     ia=iatom;
262     
263     for(ll=0; (ll<ncon); ll++,ia+=3) 
264     {
265
266         if ((econq == econqCoord) && v!=NULL) 
267         {
268             /* Correct the velocities */
269             mm = lagr[ll]*invmass[ia[1]]*invdt/vetavar->rscale;
270             for(i=0; i<DIM; i++)
271             {
272                 v[ia[1]][i] += mm*rij[ll][i];
273             }
274             mm = lagr[ll]*invmass[ia[2]]*invdt/vetavar->rscale;
275             for(i=0; i<DIM; i++)
276             {
277                 v[ia[2]][i] -= mm*rij[ll][i];
278             }
279             /* 16 flops */
280         }
281         
282         /* constraint virial */
283         if (bCalcVir)
284         {
285             if (econq == econqCoord) 
286             {
287                 mm = lagr[ll]/vetavar->rvscale;
288             } 
289             if (econq == econqVeloc) 
290             {
291                 mm = lagr[ll]/(vetavar->vscale*vetavar->vscale_nhc[0]);
292             }
293             for(i=0; i<DIM; i++) 
294             {
295                 tmp = mm*rij[ll][i];
296                 for(j=0; j<DIM; j++) 
297                 {
298                     vir_r_m_dr[i][j] -= tmp*rij[ll][j];
299                 }
300             }
301             /* 21 flops */
302         }
303         
304         /* Correct the lagrange multipliers for the length  */
305         /* (more details would be useful here . . . )*/
306         
307         type  = ia[0];
308         if (bFEP) 
309         {
310             toler = L1*ip[type].constr.dA + lambda*ip[type].constr.dB;
311         }
312         else
313         {
314             toler = ip[type].constr.dA;
315             lagr[ll] *= toler;
316         }
317     }
318     
319     return nit;
320 }
321
322 static void check_cons(FILE *log,int nc,rvec x[],rvec prime[], rvec v[],
323                        t_iparams ip[],t_iatom *iatom,
324                        real invmass[], int econq)
325 {
326   t_iatom *ia;
327   int     ai,aj;
328   int     i;
329   real    d,dp;
330   rvec    dx,dv;
331   
332   fprintf(log,
333           "    i     mi      j     mj      before       after   should be\n");
334   ia=iatom;
335   for(i=0; (i<nc); i++,ia+=3) {
336     ai=ia[1];
337     aj=ia[2];
338     rvec_sub(x[ai],x[aj],dx);
339     d=norm(dx);
340     
341     switch (econq) {
342     case econqCoord:
343         rvec_sub(prime[ai],prime[aj],dx);
344         dp=norm(dx);
345         fprintf(log,"%5d  %5.2f  %5d  %5.2f  %10.5f  %10.5f  %10.5f\n",
346                 ai+1,1.0/invmass[ai],
347                 aj+1,1.0/invmass[aj],d,dp,ip[ia[0]].constr.dA);
348         break;
349     case econqVeloc:
350         rvec_sub(v[ai],v[aj],dv);
351         d=iprod(dx,dv);
352         rvec_sub(prime[ai],prime[aj],dv);
353         dp=iprod(dx,dv);
354         fprintf(log,"%5d  %5.2f  %5d  %5.2f  %10.5f  %10.5f  %10.5f\n",
355                 ai+1,1.0/invmass[ai],
356                 aj+1,1.0/invmass[aj],d,dp,0.);
357         break;
358     }
359   }
360 }
361
362 gmx_bool bshakef(FILE *log,gmx_shakedata_t shaked,
363                  int natoms,real invmass[],int nblocks,int sblock[],
364                  t_idef *idef,t_inputrec *ir,rvec x_s[],rvec prime[],
365                  t_nrnb *nrnb,real *lagr,real lambda,real *dvdlambda,
366                  real invdt,rvec *v,gmx_bool bCalcVir,tensor vir_r_m_dr,
367                  gmx_bool bDumpOnError,int econq,t_vetavars *vetavar)
368 {
369   t_iatom *iatoms;
370   real    *lam,dt_2,dvdl;
371   int     i,n0,ncons,blen,type;
372   int     tnit=0,trij=0;
373   
374 #ifdef DEBUG
375   fprintf(log,"nblocks=%d, sblock[0]=%d\n",nblocks,sblock[0]);
376 #endif
377
378   ncons=idef->il[F_CONSTR].nr/3;
379
380   for(i=0; i<ncons; i++)
381     lagr[i] =0;
382   
383   iatoms = &(idef->il[F_CONSTR].iatoms[sblock[0]]);
384   lam    = lagr;
385   for(i=0; (i<nblocks); ) {
386     blen  = (sblock[i+1]-sblock[i]);
387     blen /= 3;
388     n0 = vec_shakef(log,shaked,natoms,invmass,blen,idef->iparams,
389                     iatoms,ir->shake_tol,x_s,prime,shaked->omega,
390                     ir->efep!=efepNO,lambda,lam,invdt,v,bCalcVir,vir_r_m_dr,
391                     econq,vetavar);
392
393 #ifdef DEBUGSHAKE
394     check_cons(log,blen,x_s,prime,v,idef->iparams,iatoms,invmass,econq);
395 #endif
396     
397     if (n0 == 0) {
398         if (bDumpOnError && log) 
399         {
400             {
401                 check_cons(log,blen,x_s,prime,v,idef->iparams,iatoms,invmass,econq);
402             }
403         }
404         return FALSE;
405     }
406     tnit   += n0*blen;
407     trij   += blen;
408     iatoms += 3*blen;   /* Increment pointer! */
409     lam    += blen;
410     i++;
411   }
412   /* only for position part? */
413   if (econq == econqCoord) {
414       if (ir->efep != efepNO) {
415           dt_2 = 1/sqr(ir->delta_t);
416           dvdl = 0;
417           for(i=0; i<ncons; i++) {
418               type = idef->il[F_CONSTR].iatoms[3*i];
419               dvdl += lagr[i]*dt_2*
420                   (idef->iparams[type].constr.dB-idef->iparams[type].constr.dA);
421           }
422           *dvdlambda += dvdl;
423       }
424   }
425 #ifdef DEBUG
426   fprintf(log,"tnit: %5d  omega: %10.5f\n",tnit,omega);
427 #endif
428   if (ir->bShakeSOR) {
429     if (tnit > shaked->gamma) {
430       shaked->delta *= -0.5;
431     }
432     shaked->omega += shaked->delta;
433     shaked->gamma  = tnit;
434   }
435   inc_nrnb(nrnb,eNR_SHAKE,tnit);
436   inc_nrnb(nrnb,eNR_SHAKE_RIJ,trij);
437   if (v)
438     inc_nrnb(nrnb,eNR_CONSTR_V,trij*2);
439   if (bCalcVir)
440     inc_nrnb(nrnb,eNR_CONSTR_VIR,trij);
441   
442   return TRUE;
443 }
444
445 void crattle(atom_id iatom[],int ncon,int *nnit,int maxnit,
446              real dist2[],real vp[],real rij[],real m2[],real omega,
447              real invmass[],real tt[],real lagr[],int *nerror,real invdt,t_vetavars *vetavar)
448 {
449     /*
450      *     r.c. van schaik and w.f. van gunsteren
451      *     eth zuerich
452      *     june 1992
453      *     Adapted for use with Gromacs by David van der Spoel november 92 and later.
454      *     rattle added by M.R. Shirts, April 2004, from code written by Jay Ponder in TINKER 
455      *     second part of rattle algorithm
456      */
457     
458     const   real mytol=1e-10;
459     
460     int     ll,i,j,i3,j3,l3,ii;
461     int     ix,iy,iz,jx,jy,jz;
462     real    toler,rijd,vpijd, vx,vy,vz,diff,acor,xdotd,fac,im,jm,imdt,jmdt;
463     real    xh,yh,zh,rijx,rijy,rijz;
464     real    tix,tiy,tiz;
465     real    tjx,tjy,tjz;
466     int     nit,error,nconv;
467     real    veta,vscale_nhc,iconvf;
468
469     veta = vetavar->veta;
470     vscale_nhc = vetavar->vscale_nhc[0];  /* for now, just use the first state */
471     
472     error=0;
473     nconv=1;
474     for (nit=0; (nit<maxnit) && (nconv != 0) && (error == 0); nit++) {
475         nconv=0;
476         for(ll=0; (ll<ncon) && (error == 0); ll++) {
477             l3    = 3*ll;
478             rijx  = rij[l3+XX];
479             rijy  = rij[l3+YY];
480             rijz  = rij[l3+ZZ];
481             i     = iatom[l3+1];
482             j     = iatom[l3+2];
483             i3    = 3*i;
484             j3    = 3*j;
485             ix    = i3+XX;
486             iy    = i3+YY;
487             iz    = i3+ZZ;
488             jx    = j3+XX;
489             jy    = j3+YY;
490             jz    = j3+ZZ;
491             vx      = vp[ix]-vp[jx];
492             vy      = vp[iy]-vp[jy];
493             vz      = vp[iz]-vp[jz];
494             
495             vpijd   = vx*rijx+vy*rijy+vz*rijz;
496             toler   = dist2[ll];
497             /* this is r(t+dt) \dotproduct \dot{r}(t+dt) */
498             xdotd   = vpijd*vscale_nhc + veta*toler;
499             
500             /* iconv is zero when the error is smaller than a bound */
501             iconvf   = fabs(xdotd)*(tt[ll]/invdt);
502             
503             if (iconvf > 1) {
504                 nconv     = iconvf;
505                 fac       = omega*2.0*m2[ll]/toler;
506                 acor      = -fac*xdotd;
507                 lagr[ll] += acor;                
508                 
509                 xh        = rijx*acor;
510                 yh        = rijy*acor;
511                 zh        = rijz*acor;
512                 
513                 im        = invmass[i]/vscale_nhc;
514                 jm        = invmass[j]/vscale_nhc;
515                 
516                 vp[ix] += xh*im;
517                 vp[iy] += yh*im;
518                 vp[iz] += zh*im;
519                 vp[jx] -= xh*jm;
520                 vp[jy] -= yh*jm;
521                 vp[jz] -= zh*jm;
522             }
523         }
524     }
525     *nnit=nit;
526     *nerror=error;
527 }