Merge origin/release-4-6 into master
[alexxy/gromacs.git] / src / gromacs / mdlib / tables.c
index 44a42f7c550b115984e5f371d37ae780abf3bb61..7be0435b4c6a668858c6182ea9c37b532c935a01 100644 (file)
@@ -140,12 +140,14 @@ static double v_ewald_lr(double beta,double r)
     }
 }
 
-void table_spline3_fill_ewald_lr(real *tabf,real *tabv,
-                                 int ntab,int tableformat,
-                                 real dx,real beta)
+void table_spline3_fill_ewald_lr(real *table_f,
+                                 real *table_v,
+                                 real *table_fdv0,
+                                 int   ntab,
+                                 real  dx,
+                                 real  beta)
 {
     real tab_max;
-    int stride=0;
     int i,i_inrange;
     double dc,dc_new;
     gmx_bool bOutOfRange;
@@ -169,13 +171,6 @@ void table_spline3_fill_ewald_lr(real *tabf,real *tabv,
      * The rms force error is the max error times 1/sqrt(5)=0.45.
      */
 
-    switch (tableformat)
-    {
-    case tableformatF:    stride = 1; break;
-    case tableformatFDV0: stride = 4; break;
-    default: gmx_incons("Unknown table format");
-    }
-
     bOutOfRange = FALSE;
     i_inrange = ntab;
     v_inrange = 0;
@@ -199,20 +194,9 @@ void table_spline3_fill_ewald_lr(real *tabf,real *tabv,
             vi = v_inrange - dc*(i - i_inrange)*dx;
         }
 
-        switch (tableformat)
+        if(table_v!=NULL)
         {
-        case tableformatF:
-            if (tabv != NULL)
-            {
-                tabv[i] = vi;
-            }
-            break;
-        case tableformatFDV0:
-            tabf[i*stride+2] = vi;
-            tabf[i*stride+3] = 0;
-            break;
-        default:
-            gmx_incons("Unknown table format");
+            table_v[i] = vi;
         }
 
         if (i == 0)
@@ -244,12 +228,12 @@ void table_spline3_fill_ewald_lr(real *tabf,real *tabv,
         if (i == ntab - 1)
         {
             /* Fill the table with the force, minus the derivative of the spline */
-            tabf[i*stride] = -dc;
+            table_f[i] = -dc;
         }
         else
         {
             /* tab[i] will contain the average of the splines over the two intervals */
-            tabf[i*stride] += -0.5*dc;
+            table_f[i] += -0.5*dc;
         }
 
         if (!bOutOfRange)
@@ -275,19 +259,27 @@ void table_spline3_fill_ewald_lr(real *tabf,real *tabv,
             }
         }
 
-        tabf[(i-1)*stride] = -0.5*dc;
+        table_f[(i-1)] = -0.5*dc;
     }
     /* Currently the last value only contains half the force: double it */
-    tabf[0] *= 2;
+    table_f[0] *= 2;
 
-    if (tableformat == tableformatFDV0)
+    if(table_v!=NULL && table_fdv0!=NULL)
     {
-        /* Store the force difference in the second entry */
-        for(i=0; i<ntab-1; i++)
+        /* Copy to FDV0 table too. Allocation occurs in forcerec.c,
+         * init_ewald_f_table().
+         */
+        for(i=0;i<ntab-1;i++)
         {
-            tabf[i*stride+1] = tabf[(i+1)*stride] - tabf[i*stride];
+            table_fdv0[4*i]     = table_f[i];
+            table_fdv0[4*i+1]   = table_f[i+1]-table_f[i];
+            table_fdv0[4*i+2]   = table_v[i];
+            table_fdv0[4*i+3]   = 0.0;
         }
-        tabf[(ntab-1)*stride+1] = -tabf[i*stride];
+        table_fdv0[4*(ntab-1)]    = table_f[(ntab-1)];
+        table_fdv0[4*(ntab-1)+1]  = -table_f[(ntab-1)];
+        table_fdv0[4*(ntab-1)+2]  = table_v[(ntab-1)];
+        table_fdv0[4*(ntab-1)+3]  = 0.0;
     }
 }
 
@@ -345,7 +337,7 @@ static void evaluate_table(real VFtab[], int offset, int stride,
 }
 
 static void copy2table(int n,int offset,int stride,
-                      double x[],double Vtab[],double Ftab[],
+                      double x[],double Vtab[],double Ftab[],real scalefactor,
                       real dest[])
 {
 /* Use double prec. for the intermediary variables
@@ -371,10 +363,10 @@ static void copy2table(int n,int offset,int stride,
       H   = 0;
     }
     nn0 = offset + i*stride;
-    dest[nn0]   = Vtab[i];
-    dest[nn0+1] = F;
-    dest[nn0+2] = G;
-    dest[nn0+3] = H;
+    dest[nn0]   = scalefactor*Vtab[i];
+    dest[nn0+1] = scalefactor*F;
+    dest[nn0+2] = scalefactor*G;
+    dest[nn0+3] = scalefactor*H;
   }
 }
 
@@ -762,30 +754,31 @@ static void fill_table(t_tabledata *td,int tp,const t_forcerec *fr)
 
     switch (tp) {
     case etabLJ6:
-      /* Dispersion */
-      Vtab  = -r6;
-      Ftab  = 6.0*Vtab/r;
-      break;
+            /* Dispersion */
+            Vtab = -r6;
+            Ftab = 6.0*Vtab/r;
+            break;
     case etabLJ6Switch:
     case etabLJ6Shift:
       /* Dispersion */
       if (r < rc) {      
-       Vtab  = -r6;
-       Ftab  = 6.0*Vtab/r;
+          Vtab = -r6;
+          Ftab = 6.0*Vtab/r;
+          break;
       }
       break;
     case etabLJ12:
-      /* Repulsion */
-      Vtab  = r12;
-      Ftab  = reppow*Vtab/r;
+            /* Repulsion */
+            Vtab  = r12;
+            Ftab  = reppow*Vtab/r;
       break;
     case etabLJ12Switch:
     case etabLJ12Shift:
       /* Repulsion */
       if (r < rc) {                
-       Vtab  = r12;
-       Ftab  = reppow*Vtab/r;
-      }  
+          Vtab  = r12;
+          Ftab  = reppow*Vtab/r;
+      }
       break;
        case etabLJ6Encad:
         if(r < rc) {
@@ -798,9 +791,9 @@ static void fill_table(t_tabledata *td,int tp,const t_forcerec *fr)
         break;
     case etabLJ12Encad:
         if(r < rc) {
-            Vtab  = r12-12.0*(rc-r)*rc6*rc6/rc-1.0*rc6*rc6;
-            Ftab  = 12.0*r12/r-12.0*rc6*rc6/rc;
-        } else { /* r>rc */ 
+            Vtab  = -(r6-6.0*(rc-r)*rc6/rc-rc6);
+            Ftab  = -(6.0*r6/r-6.0*rc6/rc);
+        } else { /* r>rc */
             Vtab  = 0;
             Ftab  = 0;
         } 
@@ -876,8 +869,8 @@ static void fill_table(t_tabledata *td,int tp,const t_forcerec *fr)
     if ((r > r1) && bSwitch) {
       Ftab = Ftab*swi - Vtab*swi1;
       Vtab = Vtab*swi;
-    }  
-    
+    }
+
     /* Convert to single precision when we store to mem */
     td->v[i]  = Vtab;
     td->f[i]  = Ftab;
@@ -1020,7 +1013,8 @@ t_forcetable make_tables(FILE *out,const output_env_t oenv,
   gmx_bool        b14only,bReadTab,bGenTab;
   real        x0,y0,yp;
   int         i,j,k,nx,nx0,tabsel[etiNR];
-  
+  real        scalefactor;
+
   t_forcetable table;
 
   b14only = (flags & GMX_MAKETABLES_14ONLY);
@@ -1040,6 +1034,12 @@ t_forcetable make_tables(FILE *out,const output_env_t oenv,
   nx0             = 10;
   nx              = 0;
   
+  table.interaction   = GMX_TABLE_INTERACTION_ELEC_VDWREP_VDWDISP;
+  table.format        = GMX_TABLE_FORMAT_CUBICSPLINE_YFGH;
+  table.formatsize    = 4;
+  table.ninteractions = 3;
+  table.stride        = table.formatsize*table.ninteractions;
+
   /* Check whether we have to read or generate */
   bReadTab = FALSE;
   bGenTab  = FALSE;
@@ -1085,7 +1085,7 @@ t_forcetable make_tables(FILE *out,const output_env_t oenv,
    * numbers per nx+1 data points. For performance reasons we want
    * the table data to be aligned to 16-byte.
    */
-  snew_aligned(table.tab, 12*(nx+1)*sizeof(real),16);
+  snew_aligned(table.data, 12*(nx+1)*sizeof(real),16);
 
   for(k=0; (k<etiNR); k++) {
     if (tabsel[k] != etabUSER) {
@@ -1100,7 +1100,27 @@ t_forcetable make_tables(FILE *out,const output_env_t oenv,
                td[k].nx,b14only?"1-4 ":"",tprops[tabsel[k]].name,
                td[k].tabscale);
     }
-    copy2table(table.n,k*4,12,td[k].x,td[k].v,td[k].f,table.tab);
+
+    /* Set scalefactor for c6/c12 tables. This is because we save flops in the non-table kernels
+     * by including the derivative constants (6.0 or 12.0) in the parameters, since
+     * we no longer calculate force in most steps. This means the c6/c12 parameters
+     * have been scaled up, so we need to scale down the table interactions too.
+     * It comes here since we need to scale user tables too.
+     */
+      if(k==etiLJ6)
+      {
+          scalefactor = 1.0/6.0;
+      }
+      else if(k==etiLJ12 && tabsel[k]!=etabEXPMIN)
+      {
+          scalefactor = 1.0/12.0;
+      }
+      else
+      {
+          scalefactor = 1.0;
+      }
+
+    copy2table(table.n,k*4,12,td[k].x,td[k].v,td[k].f,scalefactor,table.data);
     
     if (bDebugMode() && bVerbose) {
       if (b14only)
@@ -1110,7 +1130,7 @@ t_forcetable make_tables(FILE *out,const output_env_t oenv,
       /* plot the output 5 times denser than the table data */
       for(i=5*((nx0+1)/2); i<5*table.n; i++) {
        x0 = i*table.r/(5*(table.n-1));
-       evaluate_table(table.tab,4*k,12,table.scale,x0,&y0,&yp);
+       evaluate_table(table.data,4*k,12,table.scale,x0,&y0,&yp);
        fprintf(fp,"%15.10e  %15.10e  %15.10e\n",x0,y0,yp);
       }
       gmx_fio_fclose(fp);
@@ -1155,12 +1175,17 @@ t_forcetable make_gb_table(FILE *out,const output_env_t oenv,
         * use etiNR (since we only have one table, but ...) 
         */
        snew(td,1);
-       table.r         = fr->gbtabr;
-       table.scale     = fr->gbtabscale;
-       table.scale_exp = 0;
-       table.n         = table.scale*table.r;
-       nx0             = 0;
-       nx              = table.scale*table.r;
+    table.interaction   = GMX_TABLE_INTERACTION_ELEC;
+    table.format        = GMX_TABLE_FORMAT_CUBICSPLINE_YFGH;
+       table.r             = fr->gbtabr;
+       table.scale         = fr->gbtabscale;
+       table.scale_exp     = 0;
+       table.n             = table.scale*table.r;
+    table.formatsize    = 4;
+    table.ninteractions = 1;
+    table.stride        = table.formatsize*table.ninteractions;
+       nx0                 = 0;
+       nx                  = table.scale*table.r;
        
        /* Check whether we have to read or generate 
         * We will always generate a table, so remove the read code
@@ -1178,7 +1203,7 @@ t_forcetable make_gb_table(FILE *out,const output_env_t oenv,
         * to do this :-)
         */
        
-       snew_aligned(table.tab,4*nx,16);
+       snew_aligned(table.data,4*nx,16);
        
        init_table(out,nx,nx0,table.scale,&(td[0]),!bReadTab);
        
@@ -1207,7 +1232,7 @@ t_forcetable make_gb_table(FILE *out,const output_env_t oenv,
                
     }
        
-       copy2table(table.n,0,4,td[0].x,td[0].v,td[0].f,table.tab);
+       copy2table(table.n,0,4,td[0].x,td[0].v,td[0].f,1.0,table.data);
        
        if(bDebugMode())
     {
@@ -1218,7 +1243,7 @@ t_forcetable make_gb_table(FILE *out,const output_env_t oenv,
                {
                        /* x0=i*table.r/(5*table.n); */
                        x0=i*table.r/table.n;
-                       evaluate_table(table.tab,0,4,table.scale,x0,&y0,&yp);
+                       evaluate_table(table.data,0,4,table.scale,x0,&y0,&yp);
                        fprintf(fp,"%15.10e  %15.10e  %15.10e\n",x0,y0,yp);
                        
                }
@@ -1236,7 +1261,7 @@ t_forcetable make_gb_table(FILE *out,const output_env_t oenv,
         Ftab = (r-0.25*r*expterm)/((r2+expterm)*sqrt(r2+expterm));
         
         
-        evaluate_table(table.tab,0,4,table.scale,r,&y0,&yp);
+        evaluate_table(table.data,0,4,table.scale,r,&y0,&yp);
         printf("gb: i=%d, x0=%g, y0=%15.15f, Vtab=%15.15f, yp=%15.15f, Ftab=%15.15f\n",i,r, y0, Vtab, yp, Ftab);
         
         abs_error_r=fabs(y0-Vtab);
@@ -1338,9 +1363,9 @@ t_forcetable make_atf_table(FILE *out,const output_env_t oenv,
         * to do this :-)
         */
        
-    snew_aligned(table.tab,4*nx,16);
-       
-       copy2table(table.n,0,4,td[0].x,td[0].v,td[0].f,table.tab);
+    snew_aligned(table.data,4*nx,16);
+
+       copy2table(table.n,0,4,td[0].x,td[0].v,td[0].f,1.0,table.data);
        
        if(bDebugMode())
          {
@@ -1352,7 +1377,7 @@ t_forcetable make_atf_table(FILE *out,const output_env_t oenv,
              {
                /* x0=i*table.r/(5*table.n); */
                x0 = i*table.r/(5*(table.n-1));
-               evaluate_table(table.tab,0,4,table.scale,x0,&y0,&yp);
+               evaluate_table(table.data,0,4,table.scale,x0,&y0,&yp);
                fprintf(fp,"%15.10e  %15.10e  %15.10e\n",x0,y0,yp);
                
              }
@@ -1361,6 +1386,13 @@ t_forcetable make_atf_table(FILE *out,const output_env_t oenv,
 
        done_tabledata(&(td[0]));
        sfree(td);
+
+    table.interaction   = GMX_TABLE_INTERACTION_ELEC_VDWREP_VDWDISP;
+    table.format        = GMX_TABLE_FORMAT_CUBICSPLINE_YFGH;
+    table.formatsize    = 4;
+    table.ninteractions = 3;
+    table.stride        = table.formatsize*table.ninteractions;
+
        
        return table;
 }
@@ -1387,8 +1419,8 @@ bondedtable_t make_bonded_table(FILE *fplog,char *fn,int angle)
   }
   tab.n = td.nx;
   tab.scale = td.tabscale;
-  snew(tab.tab,tab.n*4);
-  copy2table(tab.n,0,4,td.x,td.v,td.f,tab.tab);
+  snew(tab.data,tab.n*4);
+  copy2table(tab.n,0,4,td.x,td.v,td.f,1.0,tab.data);
   done_tabledata(&td);
 
   return tab;