replaced PPPM by P3M-AD: a few lines in pme.c
authorBerk Hess <hess@kth.se>
Tue, 24 Apr 2012 07:48:49 +0000 (09:48 +0200)
committerBerk Hess <hess@kth.se>
Wed, 25 Apr 2012 20:07:40 +0000 (22:07 +0200)
The deprecated PPPM method has been replaced by P3M-AD: a PPPM method
with analytical derivative. The full code path of P3M-AD is identical
to PME, except for the moduli calculation, which use the influence
function optimized for the grid.

Change-Id: I53d08d9ff4e909dc1a34dce668f4dea8f26f728e

24 files changed:
include/coulomb.h
include/pppm.h [deleted file]
include/types/enums.h
include/update.h
share/html/online/mdp_opt.html
src/gmxlib/copyrite.c
src/gmxlib/names.c
src/gmxlib/shift_util.c
src/kernel/grompp.c
src/kernel/md.c
src/kernel/md_openmm.c
src/kernel/readir.c
src/kernel/runner.c
src/mdlib/coupling.c
src/mdlib/force.c
src/mdlib/forcerec.c
src/mdlib/ghat.c [deleted file]
src/mdlib/md_support.c
src/mdlib/minimize.c
src/mdlib/pme.c
src/mdlib/pppm.c [deleted file]
src/mdlib/sim_util.c
src/mdlib/tables.c
src/tools/gmx_membed.c

index 62c4023ac6a670dd76d06bd910345608ac03b7b6..6fb810d28395c40e7bfedabc10fac5fc1358393e 100644 (file)
@@ -88,18 +88,6 @@ void
 set_shift_consts(FILE *log,real r1,real rc,rvec box,
                             t_forcerec *fr);
 
-real
-shift_LRcorrection(FILE *fp,int start,int natoms,
-                              t_commrec *cr,t_forcerec *fr,
-                              real charge[],t_blocka *excl,rvec x[],
-                              gmx_bool bOld,matrix box,matrix lrvir);
-/* Calculate the self energy and forces
- * when using long range electrostatics methods.
- * Part of this is a constant, it is computed only once and stored in
- * a local variable. The remainder is computed every step.
- * PBC is taken into account. (Erik L.) 
- */
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/pppm.h b/include/pppm.h
deleted file mode 100644 (file)
index 887a263..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gromacs Runs On Most of All Computer Systems
- */
-
-#ifndef _pppm_h
-#define _pppm_h
-
-#include <stdio.h>
-#include "typedefs.h"
-#include "gmxcomplex.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int gmx_pppm_init(FILE *log,      t_commrec *cr,
-                        const output_env_t oenv, gmx_bool bVerbose,
-                        gmx_bool bOld,      matrix box,
-                        char *ghatfn,   t_inputrec *ir,
-                         gmx_bool bReproducible);
-/* Setup stuff for PPPM. 
- * Either reads a ghat function from file (when the file exists)
- * or generate a ghat function from scratch.
- */
-
-int gmx_pppm_do(FILE *log,       gmx_pme_t pme,
-                      gmx_bool bVerbose,
-                      rvec x[],        rvec f[],
-                      real charge[],   rvec box,
-                      real phi[],      t_commrec *cr,
-                      int start,       int nt,
-                      t_nrnb *nrnb,
-                      int pme_order,   real *energy);
-/* Do a PPPM calculation for the long range electrostatics. */
-
-/******************************************************************
- *
- *   ROUTINES FOR GHAT MANIPULATION
- *
- ******************************************************************/
-real gk(real k,real rc,real r1);
-/* Compute the Ghat function for a single k-value */
-
-real gknew(real k,real rc,real r1);
-/* Compute the (new!) Ghat function for a single k-value */
-
-void pr_scalar_gk(const char *fn,const output_env_t oenv,
-                         int nx,int ny,int nz, rvec box,real ***ghat);
-
-void mk_ghat(FILE *fp,int nx,int ny,int nz,
-                    real ***ghat, rvec box,real r1,real rc,gmx_bool bSym,gmx_bool bOld);
-/* Generate a Ghat function from scratch. The ghat grid should
- * be allocated using the mk_rgrid function. When bSym, only
- * the first octant of the function is generated by direct calculation
- * and the above mentioned function is called for computing the rest.
- * When !bOld a new experimental function form will be used.
- */
-
-real ***rd_ghat(FILE *log,const output_env_t oenv,char *fn,ivec igrid,
-                       rvec gridspacing, rvec beta,int *porder,
-                       real *rshort,real *rlong);
-/* Read a Ghat function from a file as generated by the program
- * mk_ghat. The grid size (number of grid points) is returned in
- * igrid, the space between grid points in gridspacing,
- * beta is a constant that determines the contribution of first
- * and second neighbours in the grid to the force
- * (See Luty et al. JCP 103 (1995) 3014)
- * porder determines whether 8 (when porder = 1) or 27 (when
- * porder = 2) neighbouring grid points are used for spreading
- * the charge.
- * rshort and rlong are the lengths used for generating the Ghat
- * function.
- */
-                 
-void wr_ghat(const char *fn,const output_env_t oenv, 
-                    int n1max,int n2max, int n3max,real h1,
-                   real h2,real h3,real ***ghat,int nalias,
-                   int porder,int niter,gmx_bool bSym,rvec beta,
-                   real r1,real rc,real pval,real zval,real eref,real qopt);
-/* Write a ghat file. (see above) */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
index ab7dd6722525a2dc6487970ab5dfb9fff5a861d0..5b05f748b93b3933c0805899ab09ce388197a461 100644 (file)
@@ -77,7 +77,7 @@ enum {
  * separately (through the implicit_solvent option).
  */
 enum {
-  eelCUT,     eelRF,     eelGRF,   eelPME,  eelEWALD,  eelPPPM
+  eelCUT,     eelRF,     eelGRF,   eelPME,  eelEWALD,  eelP3M_AD
   eelPOISSON, eelSWITCH, eelSHIFT, eelUSER, eelGB_NOTUSED, eelRF_NEC, eelENCADSHIFT, 
   eelPMEUSER, eelPMESWITCH, eelPMEUSERSWITCH, eelRF_ZERO, eelNR
 };
@@ -89,8 +89,8 @@ enum {
 
 #define EEL_RF(e) ((e) == eelRF || (e) == eelGRF || (e) == eelRF_NEC || (e) == eelRF_ZERO )
 
-#define EEL_PME(e)  ((e) == eelPME || (e) == eelPMESWITCH || (e) == eelPMEUSER || (e) == eelPMEUSERSWITCH)
-#define EEL_FULL(e) (EEL_PME(e) || (e) == eelPPPM || (e) == eelPOISSON || (e) == eelEWALD)
+#define EEL_PME(e)  ((e) == eelPME || (e) == eelPMESWITCH || (e) == eelPMEUSER || (e) == eelPMEUSERSWITCH || (e) == eelP3M_AD)
+#define EEL_FULL(e) (EEL_PME(e) || (e) == eelPOISSON || (e) == eelEWALD)
 
 #define EEL_SWITCHED(e) ((e) == eelSWITCH || (e) == eelSHIFT || (e) == eelENCADSHIFT || (e) == eelPMESWITCH || (e) == eelPMEUSERSWITCH)
 
index d21c33bab1e2eb379bc5a003a4bb8ce713f9244c..618fda7cbebb01e40030d9f41e7be690d4a5282c 100644 (file)
@@ -217,11 +217,10 @@ void update_annealing_target_temp(t_grpopts *opts,real t);
 real calc_temp(real ekin,real nrdf);
 /* Calculate the temperature */
 
-real calc_pres(int ePBC,int nwall,matrix box,
-                     tensor ekin,tensor vir,tensor pres,real Elr);
+real calc_pres(int ePBC,int nwall,matrix box,tensor ekin,tensor vir,
+              tensor pres);
 /* Calculate the pressure tensor, returns the scalar pressure.
- * The unit of pressure is bar, If Elr != 0
- * a long range correction based on Ewald/PPPM is made (see c-code)
+ * The unit of pressure is bar.
  */
 
 void parrinellorahman_pcoupl(FILE *fplog,gmx_large_int_t step,
index cf6cf4713ee01faf6332fff8a34e21348915c0ff..3dcad45bd49c811647813895c08a3b66d402ab9b 100644 (file)
@@ -493,7 +493,7 @@ and is thus extremely slow for large systems. It is included mainly for
 reference - in most cases PME will perform much better.</dd>
 
 <dt><b><!--Idx-->PME<!--EIdx--></b></dt>
-<dd>Fast Particle-Mesh Ewald electrostatics. Direct space is similar
+<dd>Fast smooth Particle-Mesh Ewald (SPME) electrostatics. Direct space is similar
 to the Ewald sum, while the reciprocal part is performed with
 FFTs. Grid dimensions are controlled with <b>fourierspacing</b> and the
 interpolation order with <b>pme-order</b>. With a grid spacing of 0.1
@@ -503,16 +503,11 @@ might try 0.15 nm. When running in parallel the interpolation
 parallelizes better than the FFT, so try decreasing grid dimensions
 while increasing interpolation.</dd>
 
-<dt><b><!--Idx-->PPPM<!--EIdx--></b></dt>
-<dd>Particle-Particle Particle-Mesh algorithm for long range
-electrostatic interactions.
-Use for example <b>rlist</b><tt>=0.9</tt>, <b>rcoulomb</b><tt>=0.9</TT>.
-The grid dimensions are controlled by <b>fourierspacing</b>.
-Reasonable grid spacing for PPPM is 0.05-0.1 nm.
-See <tt>Shift</tt> for the details of the particle-particle potential.
-<br>
-NOTE: PPPM is not functional in the current version, but we plan to implement
-PPPM through a small modification of the PME code.</dd>
+<dt><b><!--Idx-->P3M-AD<!--EIdx--></b></dt>
+<dd>Particle-Particle Particle-Mesh algorithm with analytical derivative
+for for long range electrostatic interactions. The method and code
+is identical to SPME, except that the influence function is optimized
+for the grid. This gives a slight increase in accuracy.</dd>
 
 <dt><b><!--Idx-->Reaction-Field<!--EIdx--></b></dt>
 <dd>Reaction field with Coulomb cut-off <b>rcoulomb</b>,
@@ -726,7 +721,7 @@ energy group pairs.
 <h3>Ewald</h3>
 <dl>
 <dt><b>fourierspacing: (0.12) [nm]</b></dt>
-<dd>The maximum grid spacing for the FFT grid when using PPPM or PME.
+<dd>The maximum grid spacing for the FFT grid when using PME or P3M.
 For ordinary Ewald the spacing times the box dimensions determines the
 highest magnitude to use in each direction. In all cases
 each direction can be overridden by entering a non-zero value for
@@ -739,7 +734,7 @@ by the same factor.</dd>
 
 <dt><b>fourier-nx (0) ; fourier-ny (0) ; fourier-nz: (0)</b></dt>
 <dd>Highest magnitude of wave vectors in reciprocal space when using Ewald.</dd>
-<dd>Grid size when using PPPM or PME. These values override
+<dd>Grid size when using PME or P3M. These values override
 <b>fourierspacing</b> per direction. The best choice is powers of
 2, 3, 5 and 7. Avoid large primes.</dd>
 
index e720b8faf95a7ea6859dd7708f6a6d84776da956..00d326a4aa131bd1d0cbce9a6bcaa154361910b6 100644 (file)
@@ -547,8 +547,17 @@ void please_cite(FILE *fp,const char *key)
       "M. Hoefling, N. Lima, D. Haenni, C.A.M. Seidel, B. Schuler, H. Grubmuller",
       "Structural Heterogeneity and Quantitative FRET Efficiency Distributions of Polyprolines through a Hybrid Atomistic Simulation and Monte Carlo Approach",
       "PLoS ONE",
-      6, 2011, "e19791"
-    }
+      6, 2011, "e19791" },
+    { "Hockney1988",
+      "R. W. Hockney and J. W. Eastwood",
+      "Computer simulation using particles",
+      "IOP, Bristol",
+      1, 1988, "1" },
+    { "Ballenegger2012",
+      "V. Ballenegger, J.J. Cerda, and C. Holm",
+      "How to Convert SPME to P3M: Influence Functions and Error Estimates",
+      "J. Chem. Theory Comput.",
+      8, 2012, "936-947" }
   };
 #define NSTR (int)asize(citedb)
   
index 71fc24d20661f350cbc8c421f4a5f76e3adf8d5c..51e5d04c23f73621c87dee1e1473dd462540f450 100644 (file)
@@ -72,7 +72,7 @@ const char *ptype_str[eptNR+1] = {
 
 const char *eel_names[eelNR+1] = {
   "Cut-off", "Reaction-Field", "Generalized-Reaction-Field",
-  "PME", "Ewald", "PPPM", "Poisson", "Switch", "Shift", "User", 
+  "PME", "Ewald", "P3M-AD", "Poisson", "Switch", "Shift", "User", 
   "Generalized-Born", "Reaction-Field-nec", "Encad-shift", 
   "PME-User", "PME-Switch", "PME-User-Switch", 
   "Reaction-Field-zero", NULL
index 16d47f755c912b945ef270dab5f694c563470a03..c4cee2257c988deca87d816842b51054dd7839b9 100644 (file)
@@ -49,7 +49,6 @@
 #include "writeps.h"
 #include "macros.h"
 #include "xvgr.h"
-#include "pppm.h"
 #include "gmxfio.h"
 
 #include "thread_mpi.h"
@@ -115,186 +114,3 @@ void set_shift_consts(FILE *log,real r1,real rc,rvec box,t_forcerec *fr)
   tMPI_Thread_mutex_unlock(&shift_mutex);
 #endif
 }
-
-real gk(real k,real rc,real r1)
-/* Spread function in Fourier space. Eqs. 56-64 */
-{
-  real N,gg;
-  
-  N  = N0*p4(k);
-
-  /* c1 thru c6 consts are global variables! */  
-  gg = (FourPi_V / (N*k)) * 
-    ( c1*k*cos(k*rc) + (c2+c3*k*k)*sin(k*rc) + 
-      c4*k*cos(k*r1) + (c5+c6*k*k)*sin(k*r1) );
-  
-  return gg;
-}
-
-real gknew(real k,real rc,real r1)
-{
-  real rck,rck2;
-  
-  rck = rc*k;
-  rck2= rck*rck;
-  
-  return -15.0*((rck2-3.0)*sin(rck) + 3*rck*cos(rck))/(Vol*rck2*rck2*rck);
-}
-
-real calc_dx2dx(rvec xi,rvec xj,rvec box,rvec dx)
-{
-  int  m;
-  real ddx,dx2;
-  
-  dx2=0;
-  for(m=0; (m<DIM); m++) {
-    ddx=xj[m]-xi[m];
-    if (ddx < -0.5*box[m])
-      ddx+=box[m];
-    else if (ddx >= 0.5*box[m])
-      ddx-=box[m];
-    dx[m]=ddx;
-    dx2 += ddx*ddx;
-  }
-  return dx2;
-}
-
-real shiftfunction(real r1,real rc,real R)
-{
-  real dr;
-
-  if (R <= r1)
-    return 0.0;
-  else if (R >= rc)
-    return -1.0/(R*R);
-  
-  dr=R-r1;
-  
-  return A*dr*dr+B*dr*dr*dr;
-}
-
-real potential(real r1,real rc,real R)
-{
-  if (R < r1)
-    return (1.0/R-C);
-  else if (R <= rc)
-    return (1.0/R - A_3*p3(R-r1) - B_4*p4(R-r1) - C);
-  else 
-    return 0.0;
-}
-
-
-
-real shift_LRcorrection(FILE *fp,int start,int natoms,
-                       t_commrec *cr,t_forcerec *fr,
-                       real charge[],t_blocka *excl,rvec x[],
-                       gmx_bool bOld,matrix box,matrix lr_vir)
-{
-  static gmx_bool bFirst=TRUE;
-  static real Vself;
-  int    i,i1,i2,j,k,m,iv,jv;
-  int *AA;
-  double qq; /* Necessary for precision */
-  double isp=0.564189583547756;
-  real   qi,dr,dr2,dr_1,dr_3,fscal,Vexcl,qtot=0;
-  rvec   df,dx;
-  real   r1=fr->rcoulomb_switch;
-  real   rc=fr->rcoulomb;
-  ivec   shift;     
-  
-  if (bFirst) {
-    qq =0;  
-    for(i=start; (i<start+natoms); i++) 
-      qq  += charge[i]*charge[i];
-    
-    /* Obsolete, until we implement dipole and charge corrections.
-       qtot=0;
-       for(i=0;i<nsb->natoms;i++)
-       qtot+=charge[i];
-    */
-   
-    Vself = 0.5*C*ONE_4PI_EPS0*qq;
-    if(debug) {
-       fprintf(fp,"Long Range corrections for shifted interactions:\n");
-       fprintf(fp,"r1 = %g, rc=%g\n",r1,rc);
-       fprintf(fp,"start=%d,natoms=%d\n",start,natoms);
-       fprintf(fp,"qq = %g, Vself=%g\n",qq,Vself);
-    }
-    
-  }
-  AA = excl->a;
-  Vexcl = 0;
-  for(i=start; (i<start+natoms); i++) {
-    /* Initiate local variables (for this i-particle) to 0 */
-    i1  = excl->index[i];
-    i2  = excl->index[i+1];
-    qi  = charge[i]*ONE_4PI_EPS0;
-
-    /* Loop over excluded neighbours */
-    for(j=i1; (j<i2); j++) {
-      k = AA[j];
-      /* 
-       * First we must test whether k <> i, and then, because the
-       * exclusions are all listed twice i->k and k->i we must select
-       * just one of the two.
-       * As a minor optimization we only compute forces when the charges
-       * are non-zero.
-       */
-      if (k > i) {
-       qq = qi*charge[k];
-       if (qq != 0.0) {
-         dr2 = 0;
-         rvec_sub(x[i],x[k],dx);
-         for(m=DIM-1; m>=0; m--) {
-           if (dx[m] > 0.5*box[m][m])
-             rvec_dec(dx,box[m]);
-           else if (dx[m] < -0.5*box[m][m])
-             rvec_inc(dx,box[m]);
-           
-           dr2  += dx[m]*dx[m];
-         }
-         dr_1    = gmx_invsqrt(dr2);
-         dr      = 1.0/dr_1;
-         dr_3    = dr_1*dr_1*dr_1;
-         /* Compute exclusion energy and scalar force */
-
-         Vexcl  += qq*(dr_1-potential(r1,rc,dr));
-         fscal   = qq*(-shiftfunction(r1,rc,dr))*dr_3;
-         
-         if ((fscal != 0) && debug)
-           fprintf(debug,"i: %d, k: %d, dr: %.3f fscal: %.3f\n",i,k,dr,fscal);
-           
-         /* The force vector is obtained by multiplication with the 
-          * distance vector 
-          */
-         svmul(fscal,dx,df);
-         rvec_inc(fr->f_novirsum[k],df);
-         rvec_dec(fr->f_novirsum[i],df);
-         for(iv=0;iv<DIM;iv++)
-             for(jv=0;jv<DIM;jv++)
-                 lr_vir[iv][jv]+=0.5*dx[iv]*df[jv];
-       }
-      }
-    }
-  }
-  if (bFirst && debug)
-    fprintf(fp,"Long Range correction: Vexcl=%g\n",Vexcl);
-  
-  bFirst = FALSE;
-  /* Return the correction to the energy */
-  return (-(Vself+Vexcl));
-}
-  
-real phi_aver(int natoms,real phi[])
-{
-  real phitot;
-  int  i;
-
-  phitot=0;  
-  for(i=0; (i<natoms); i++)
-    phitot=phitot+phi[i];
-    
-  return (phitot/natoms);
-}
-
index baa8f76dd4bb5dc38af2582eee4623a5a1f2d5be..d3b43bbcb268638472fe755a94608cfe043f0aec 100644 (file)
@@ -1571,10 +1571,6 @@ int main (int argc, char *argv[])
       svmul(ir->wall_ewald_zfac,box[ZZ],box[ZZ]);
     max_spacing = calc_grid(stdout,box,opts->fourierspacing,
                             &(ir->nkx),&(ir->nky),&(ir->nkz));
-    if ((ir->coulombtype == eelPPPM) && (max_spacing > 0.1)) {
-        set_warning_line(wi,mdparin,-1);
-        warning_note(wi,"Grid spacing larger then 0.1 while using PPPM.");
-    }
   }
 
   if (ir->ePull != epullNO)
index 3a507181a4876176ea44c35c3cce736cfa26fb5f..1f6004f1db1396f4e26dad8999356d50d79efbb9 100644 (file)
@@ -64,7 +64,6 @@
 #include "disre.h"
 #include "orires.h"
 #include "dihre.h"
-#include "pppm.h"
 #include "pme.h"
 #include "mdatoms.h"
 #include "repl_ex.h"
index 2087658565d7821499aa344edc5334442df3574d..208877c5c2ea2fcffddd1ca4c7d73306090e7f84 100644 (file)
@@ -67,7 +67,6 @@
 #include "disre.h"
 #include "orires.h"
 #include "dihre.h"
-#include "pppm.h"
 #include "pme.h"
 #include "mdatoms.h"
 #include "qmmm.h"
index ad739580dbdaf8909cf1496d6d17cd25332be9e1..3b6e4e7f4b68e1829aa959b45dc8125a886ffb65 100644 (file)
@@ -351,9 +351,8 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
       warning_note(wi,"Tumbling and or flying ice-cubes: We are not removing rotation around center of mass in a non-periodic system. You should probably set comm_mode = ANGULAR.");
   }
   
-  sprintf(err_buf,"Free-energy not implemented for Ewald and PPPM");
-  CHECK((ir->coulombtype==eelEWALD || ir->coulombtype==eelPPPM)
-       && (ir->efep!=efepNO));
+  sprintf(err_buf,"Free-energy not implemented for Ewald");
+  CHECK((ir->coulombtype==eelEWALD) && (ir->efep!=efepNO));
   
   sprintf(err_buf,"Twin-range neighbour searching (NS) with simple NS"
          " algorithm not implemented");
@@ -432,9 +431,6 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
               (trace(ir->compress) == 0 && ir->compress[YY][XX] <= 0 &&
                ir->compress[ZZ][XX] <= 0 && ir->compress[ZZ][YY] <= 0));
         
-        sprintf(err_buf,"pressure coupling with PPPM not implemented, use PME");
-        CHECK(ir->coulombtype == eelPPPM);
-
         if (epcPARRINELLORAHMAN == ir->epct && opts->bGenVel)
         {
             sprintf(warn_buf,
@@ -448,11 +444,6 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
             warning(wi,warn_buf);
         }
     }
-    else if (ir->coulombtype == eelPPPM)
-    {
-        sprintf(warn_buf,"The pressure with PPPM is incorrect, if you need the pressure use PME");
-        warning(wi,warn_buf);
-    }
     
     if (EI_VV(ir->eI))
     {
@@ -467,10 +458,6 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
 
   /* ELECTROSTATICS */
   /* More checks are in triple check (grompp.c) */
-    if (ir->coulombtype == eelPPPM)
-    {
-        warning_error(wi,"PPPM is not functional in the current version, we plan to implement PPPM through a small modification of the PME code");
-    }
 
   if (ir->coulombtype == eelSWITCH) {
     sprintf(warn_buf,"coulombtype = %s is only for testing purposes and can lead to serious artifacts, advice: use coulombtype = %s",
@@ -538,7 +525,7 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
              eel_names[ir->coulombtype]);
       CHECK(ir->rcoulomb > ir->rlist);
     } else {
-      if (ir->coulombtype == eelPME) {
+      if (ir->coulombtype == eelPME || ir->coulombtype == eelP3M_AD) {
        sprintf(err_buf,
                "With coulombtype = %s, rcoulomb must be equal to rlist\n"
                "If you want optimal energy conservation or exact integration use %s",
index 22f81c2215f6ca51c99196ecd640fd84b6d85e39..fe17bf069f4882d07a87841a153c19c1c94ef35b 100644 (file)
@@ -55,7 +55,6 @@
 #include "disre.h"
 #include "orires.h"
 #include "dihre.h"
-#include "pppm.h"
 #include "pme.h"
 #include "mdatoms.h"
 #include "repl_ex.h"
@@ -753,22 +752,6 @@ int mdrunner(int nthreads_requested, FILE *fplog,t_commrec *cr,int nfile,
             }
         }
 
-        /* Initiate PPPM if necessary */
-        if (fr->eeltype == eelPPPM)
-        {
-            if (mdatoms->nChargePerturbed)
-            {
-                gmx_fatal(FARGS,"Free energy with %s is not implemented",
-                          eel_names[fr->eeltype]);
-            }
-            status = gmx_pppm_init(fplog,cr,oenv,FALSE,TRUE,box,
-                                   getenv("GMXGHAT"),inputrec, (Flags & MD_REPRODUCIBLE));
-            if (status != 0)
-            {
-                gmx_fatal(FARGS,"Error %d initializing PPPM",status);
-            }
-        }
-
         if (EEL_PME(fr->eeltype))
         {
             ewaldcoeff = fr->ewaldcoeff;
index 90815f04f02cf58cbfee90facd8549ea4fd2bc88..d12382fe47dd18e56951f21c24b547a2f5680f5d 100644 (file)
@@ -212,10 +212,7 @@ static void boxv_trotter(t_inputrec *ir, real *veta, real dt, tensor box,
     alpha *= ekind->tcstat[0].ekinscalef_nhc;
     msmul(ekind->ekin,alpha,ekinmod);  
     
-    /* for now, we use Elr = 0, because if you want to get it right, you
-       really should be using PME. Maybe print a warning? */
-    
-    pscal   = calc_pres(ir->ePBC,nwall,box,ekinmod,vir,localpres,0.0) + pcorr;
+    pscal   = calc_pres(ir->ePBC,nwall,box,ekinmod,vir,localpres) + pcorr;
     
     vol = det(box);
     GW = (vol*(MassQ->Winv/PRESFAC))*(DIM*pscal - trace(ir->ref_p));   /* W is in ps^2 * bar * nm^3 */
@@ -232,10 +229,10 @@ static void boxv_trotter(t_inputrec *ir, real *veta, real dt, tensor box,
  */
 
 real calc_pres(int ePBC,int nwall,matrix box,tensor ekin,tensor vir,
-               tensor pres,real Elr)
+               tensor pres)
 {
     int  n,m;
-    real fac,Plr;
+    real fac;
     
     if (ePBC==epbcNONE || (ePBC==epbcXY && nwall!=2))
         clear_mat(pres);
@@ -245,21 +242,10 @@ real calc_pres(int ePBC,int nwall,matrix box,tensor ekin,tensor vir,
          * het systeem...       
          */
         
-        /* Long range correction for periodic systems, see
-         * Neumann et al. JCP
-         * divide by 6 because it is multiplied by fac later on.
-         * If Elr = 0, no correction is made.
-         */
-        
-        /* This formula should not be used with Ewald or PME, 
-         * where the full long-range virial is calculated. EL 990823
-         */
-        Plr = Elr/6.0;
-        
         fac=PRESFAC*2.0/det(box);
         for(n=0; (n<DIM); n++)
             for(m=0; (m<DIM); m++)
-                pres[n][m]=(ekin[n][m]-vir[n][m]+Plr)*fac;
+                pres[n][m] = (ekin[n][m] - vir[n][m])*fac;
         
         if (debug) {
             pr_rvecs(debug,0,"PC: pres",pres,DIM);
index 6d0917912c27648b8deb1868f6e2da31601b05e7..79b12d888e420a89bf0c12c348f545e626f5c87a 100644 (file)
@@ -56,7 +56,6 @@
 #include "mshift.h"
 #include "txtdump.h"
 #include "coulomb.h"
-#include "pppm.h"
 #include "pme.h"
 #include "mdrun.h"
 #include "domdec.h"
@@ -420,27 +419,16 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
                 Vcorr = 0;
             }
         }
-        else
-        {
-            Vcorr = shift_LRcorrection(fplog,md->start,md->homenr,cr,fr,
-                                       md->chargeA,excl,x,TRUE,box,
-                                       fr->vir_el_recip);
-        }
         
         dvdlambda = 0;
         status = 0;
         switch (fr->eeltype)
         {
-        case eelPPPM:
-            status = gmx_pppm_do(fplog,fr->pmedata,FALSE,x,fr->f_novirsum,
-                                 md->chargeA,
-                                 box_size,fr->phi,cr,md->start,md->homenr,
-                                 nrnb,ir->pme_order,&Vlr);
-            break;
         case eelPME:
         case eelPMESWITCH:
         case eelPMEUSER:
         case eelPMEUSERSWITCH:
+        case eelP3M_AD:
             if (cr->duty & DUTY_PME)
             {
                 if (fr->n_tpi == 0 || (flags & GMX_FORCE_STATECHANGED))
index 6b17c0a70f8887455101eef6428ee28a40f5d977..975c0547918b9db7e25c2de3f243655efdebe7e6 100644 (file)
@@ -1475,7 +1475,15 @@ void init_forcerec(FILE *fp,
         {
             if (fp)
                 fprintf(fp,"Will do PME sum in reciprocal space.\n");
-            please_cite(fp,"Essmann95a");
+            if (ir->coulombtype == eelP3M_AD)
+            {
+                please_cite(fp,"Hockney1988");
+                please_cite(fp,"Ballenegger2012");
+            }
+            else
+            {
+                please_cite(fp,"Essmann95a");
+            }
             
             if (ir->ewald_geometry == eewg3DC)
             {
@@ -1510,27 +1518,12 @@ void init_forcerec(FILE *fp,
     {
         init_generalized_rf(fp,mtop,ir,fr);
     }
-    else if (EEL_FULL(fr->eeltype) || (fr->eeltype == eelSHIFT) || 
-             (fr->eeltype == eelUSER) || (fr->eeltype == eelSWITCH))
+    else if (fr->eeltype == eelSHIFT)
     {
-        /* We must use the long range cut-off for neighboursearching...
-         * An extra range of e.g. 0.1 nm (half the size of a charge group)
-         * is necessary for neighboursearching. This allows diffusion 
-         * into the cut-off range (between neighborlist updates), 
-         * and gives more accurate forces because all atoms within the short-range
-         * cut-off rc must be taken into account, while the ns criterium takes
-         * only those with the center of geometry within the cut-off.
-         * (therefore we have to add half the size of a charge group, plus
-         * something to account for diffusion if we have nstlist > 1)
-         */
         for(m=0; (m<DIM); m++)
             box_size[m]=box[m][m];
         
-        if (fr->eeltype == eelPPPM && fr->phi == NULL)
-            snew(fr->phi,natoms);
-        
-        if ((fr->eeltype==eelPPPM) || (fr->eeltype==eelPOISSON) || 
-            (fr->eeltype == eelSHIFT && fr->rcoulomb > fr->rcoulomb_switch))
+        if ((fr->eeltype == eelSHIFT && fr->rcoulomb > fr->rcoulomb_switch))
             set_shift_consts(fp,fr->rcoulomb_switch,fr->rcoulomb,box_size,fr);
     }
     
diff --git a/src/mdlib/ghat.c b/src/mdlib/ghat.c
deleted file mode 100644 (file)
index e28d44e..0000000
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GROwing Monsters And Cloning Shrimps
- */
-/* This file is completely threadsafe - keep it that way! */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include "typedefs.h"
-#include "futil.h"
-#include "vec.h"
-#include "physics.h"
-#include "coulomb.h"
-#include "pppm.h"
-#include "xvgr.h"
-#include "gmxfio.h"
-#include "pppm.h"
-#include "smalloc.h"
-
-static void calc_k(rvec lll,int ix,int iy,int iz,int nx,int ny,int nz,rvec k)
-{
-#define IDX(i,n,x)  (i<=n/2) ? (i*x) : ((i-n)*x)
-  k[XX] = IDX(ix,nx,lll[XX]);
-  k[YY] = IDX(iy,ny,lll[YY]);
-  k[ZZ] = IDX(iz,nz,lll[ZZ]);
-#undef IDX
-}
-
-void symmetrize_ghat(int nx,int ny,int nz,real ***ghat)
-/* Symmetrize the Ghat function. It is assumed that the 
- * first octant of the Ghat function is either read or generated
- * (all k-vectors from 0..nx/2 0..ny/2 0..nz/2).
- * Since Gk depends on the absolute value of k only, 
- * symmetry operations may shorten the time to generate it.
- */
-{
-  int  i,j,k;
-  int  iip,jjp,kkp;
-  real ggg;
-
-  /* fprintf(stderr,"Symmetrizing Ghat function\n");   */
-  /* Only the lower octant of the rectangle has been saved,
-   * so we must construct the other 7 octants by symmetry operations.
-   */
-  for(i=0; (i<=nx/2); i++) {
-    iip = (nx-i) % nx;
-    for(j=0; (j<=ny/2); j++) {
-      jjp = (ny-j) % ny;
-      for(k=0; (k<=nz/2); k++) {
-       kkp = (nz-k) % nz;
-       ggg                 = ghat[i][j][k];
-       ghat[i]  [jjp][k]   = ggg;
-       ghat[i]  [j]  [kkp] = ggg;
-       ghat[i]  [jjp][kkp] = ggg;
-       ghat[iip][j]  [k]   = ggg;
-       ghat[iip][jjp][k]   = ggg;
-       ghat[iip][j]  [kkp] = ggg;
-       ghat[iip][jjp][kkp] = ggg;
-      }
-    }
-  }
-}
-
-void mk_ghat(FILE *fp,int nx,int ny,int nz,real ***ghat,
-            rvec box,real r1,real rc,gmx_bool bSym,gmx_bool bOld)
-{
-  int  ix,iy,iz;
-  int  ixmax,iymax,izmax;
-  real k2,ggg;
-  rvec k,lll;
-  
-  calc_lll(box,lll);
-    
-  if (bSym) {
-    ixmax=nx/2+1;
-    iymax=ny/2+1;
-    izmax=nz/2+1;
-  }
-  else {
-    ixmax=nx;
-    iymax=ny;
-    izmax=nz;
-  }
-  /* Loop over lattice vectors in fourier space */    
-  for(ix=0; (ix < ixmax); ix++) {
-    for(iy=0; (iy < iymax); iy++) {
-      for(iz=0; (iz < izmax); iz++) {
-       calc_k(lll,ix,iy,iz,nx,ny,nz,k);
-       k2 = iprod(k,k);
-       if ((ix == 0) && (iy == 0) && (iz == 0))
-         ggg = 0.0;
-       else {
-         if (bOld)
-           ggg = gk(sqrt(k2),rc,r1)/(k2*EPSILON0);
-         else
-           ggg = gknew(sqrt(k2),rc,r1)/(k2*EPSILON0);
-       }
-       ghat[ix][iy][iz]=ggg;
-      }
-    }
-  }
-  if (bSym)
-    symmetrize_ghat(nx,ny,nz,ghat);
-}
-
-void wr_ghat(const char *fn,const output_env_t oenv,  
-            int n1max,int n2max,int n3max,real h1,real h2,real h3,
-            real ***ghat,int nalias,int porder,int niter,gmx_bool bSym,rvec beta,
-            real r1,real rc,real pval,real zval,real eref,real qopt)
-{
-  FILE *fp;
-  int  N1MAX,N2MAX,N3MAX;
-  gmx_bool bNL=FALSE;
-  real rx,ry,rz;
-  int  ii,jj,kk,nn;
-  
-  fp = gmx_fio_fopen(fn,"w");
-  fprintf(fp,"%8d  %8d  %8d  %15.10e  %15.10e %15.10e\n",
-         n1max,n2max,n3max,h1,h2,h3);
-  fprintf(fp,"%8d  %8d  %8d  %8d  %15.10e  %15.10e  %15.10e\n",
-         nalias,porder,niter,bSym,beta[XX],beta[YY],beta[ZZ]);
-  fprintf(fp,"%10g  %10g  %10g  %10g  %10g  %10g\n",
-         rc,r1,pval,zval,eref,qopt);
-  
-  if (bSym) {
-    N1MAX = n1max/2+1;
-    N2MAX = n2max/2+1;
-    N3MAX = n3max/2+1;
-  }
-  else {
-    N1MAX = n1max;
-    N2MAX = n2max;
-    N3MAX = n3max;
-  }
-  for(ii=0; (ii<N1MAX); ii++) {
-    for(jj=0; (jj<N2MAX); jj++) {
-      for(kk=0,nn=1; (kk<N3MAX); kk++,nn++) { 
-       bNL=FALSE;
-       fprintf(fp,"  %12.5e",ghat[ii][jj][kk]);
-       if ((nn % 6) == 0) {
-         fprintf(fp,"\n");
-         bNL=TRUE;
-       }
-      }
-      if (!bNL)
-       fprintf(fp,"\n");
-    }
-  }
-  gmx_fio_fclose(fp);
-  
-  fp=xvgropen("ghat.xvg","G-Hat","k","gk",oenv);
-  for(ii=0; (ii<N1MAX); ii++) {
-    rx=sqr((real)(ii*h1));
-    for(jj=0; (jj<N2MAX); jj++) {
-      ry=rx+sqr((real)(jj*h2));
-      for(kk=0; (kk<N3MAX); kk++) {
-       rz=ry+sqr((real)(kk*h3));
-       fprintf(fp,"%10g  %10g\n",sqrt(rz),ghat[ii][jj][kk]);
-      }
-    }
-  }
-  gmx_fio_fclose(fp);
-}
-
-void pr_scalar_gk(const char *fn,const output_env_t oenv,int nx,int ny,int nz,
-                  rvec box,real ***ghat)
-{
-  FILE *fp;
-  int  ii,jj,kk;
-  real k1;
-  rvec k,lll;
-  
-  calc_lll(box,lll);
-  
-  fp=xvgropen(fn,"G-Hat","k","gk",oenv);
-  for(ii=0; (ii<nx); ii++) {
-    for(jj=0; (jj<ny); jj++) {
-      for(kk=0; (kk<nz); kk++) {
-       calc_k(lll,ii,jj,kk,nx,ny,nz,k);
-       k1 = norm(k);
-       fprintf(fp,"%10g  %10g\n",k1,ghat[ii][jj][kk]);
-      }
-    }
-  }
-  gmx_fio_fclose(fp);
-}
-
-static real ***mk_rgrid(int nx,int ny,int nz)
-{
-  real *ptr1;
-  real **ptr2;
-  real ***ptr3;
-  int  i,j,n2,n3;
-
-  snew(ptr1,nx*ny*nz);
-  snew(ptr2,nx*ny);
-  snew(ptr3,nx);
-
-  n2=n3=0;
-  for(i=0; (i<nx); i++) {
-    ptr3[i]=&(ptr2[n2]);
-    for(j=0; (j<ny); j++,n2++) {
-      ptr2[n2] = &(ptr1[n3]);
-      n3 += nz;
-    }
-  }
-  return ptr3;
-}
-
-real ***rd_ghat(FILE *log,const output_env_t oenv,char *fn,ivec igrid,
-                rvec gridspace, rvec beta,int *porder,real *r1,real *rc)
-{
-  FILE   *in;
-  real   ***gh;
-  double gx,gy,gz,alX,alY,alZ,ddd;
-  double acut,pval,zval,eref,qopt,r11;
-  int    nalias,niter,bSym;
-  int    ix,iy,iz,ixmax,iymax,izmax;
-  
-  in=gmx_fio_fopen(fn,"r");
-  if(6 != fscanf(in,"%d%d%d%lf%lf%lf",&ix,&iy,&iz,&gx,&gy,&gz))
-  {
-      gmx_fatal(FARGS,"Error reading from file %s",fn);
-  }
-
-
-  igrid[XX]=ix, igrid[YY]=iy, igrid[ZZ]=iz;
-  gridspace[XX]=gx,  gridspace[YY]=gy,  gridspace[ZZ]=gz;
-  if(7 != fscanf(in,"%d%d%d%d%lf%lf%lf",&nalias,porder,&niter,&bSym,&alX,&alY,&alZ))
-  {
-      gmx_fatal(FARGS,"Error reading from file %s",fn);
-  }
-
-  if(6 != fscanf(in,"%lf%lf%lf%lf%lf%lf",&acut,&r11,&pval,&zval,&eref,&qopt))
-  {
-    gmx_fatal(FARGS,"Error reading from file %s",fn);
-  }
-
-  *r1 = r11;
-  *rc = acut;
-  
-  fprintf(log,"\nOpened %s for reading ghat function\n",fn);
-  fprintf(log,"gridsize: %10d %10d %10d\n",ix,iy,iz);
-  fprintf(log,"spacing:  %10g %10g %10g\n",gx,gy,gz);
-  fprintf(log,"    nalias    porder     niter      bSym      beta[X-Z]\n"
-         "%10d%10d%10d%10d%10g%10g%10g\n",
-         nalias,*porder,niter,bSym,alX,alY,alZ);
-  fprintf(log,"      acut        r1      pval      zval      eref      qopt\n"
-         "%10g%10g%10g%10g%10g%10g\n",acut,*r1,pval,zval,eref,qopt);
-  fflush(log);
-  
-  beta[XX] = alX;
-  beta[YY] = alY;
-  beta[ZZ] = alZ;
-  
-  gh      = mk_rgrid(ix,iy,iz);
-  if (bSym) {
-    ixmax=igrid[XX]/2+1;
-    iymax=igrid[YY]/2+1;
-    izmax=igrid[ZZ]/2+1;
-  }
-  else {
-    ixmax=igrid[XX];
-    iymax=igrid[YY];
-    izmax=igrid[ZZ];
-  }
-  fprintf(log,"Reading ghat of %d %d %d\n",ixmax,iymax,izmax);
-  for(ix=0; (ix<ixmax); ix++)
-    for(iy=0; (iy<iymax); iy++)
-      for(iz=0; (iz<izmax); iz++) {
-       if( 1 != fscanf(in,"%lf",&ddd))
-        {
-           gmx_fatal(FARGS,"Error reading from file %s",fn);
-       }
-
-       gh[ix][iy][iz] = ddd;
-      }
-  gmx_fio_fclose(in);
-
-  wr_ghat("output.hat",oenv,igrid[XX],igrid[YY],igrid[ZZ],gx,gy,gz,gh,
-         nalias,*porder,niter,bSym,beta,
-         *r1,*rc,pval,zval,eref,qopt);
-    
-  if (bSym) 
-    symmetrize_ghat(igrid[XX],igrid[YY],igrid[ZZ],gh);
-  
-  fprintf(log,"\nSuccessfully read ghat function!\n");
-  
-  
-  return gh;
-}
-
index ab439a939ce3027e3483ce7262faa3427ddcbb44..77b04beb2e7332572e6b7748942c0f1d024e7af9 100644 (file)
@@ -479,8 +479,7 @@ void compute_globals(FILE *fplog, gmx_global_stat_t gstat, t_commrec *cr, t_inpu
          * Use the box from last timestep since we already called update().
          */
         
-        enerd->term[F_PRES] = calc_pres(fr->ePBC,ir->nwall,box,ekind->ekin,total_vir,pres,
-                                        (fr->eeltype==eelPPPM)?enerd->term[F_COUL_RECIP]:0.0);
+        enerd->term[F_PRES] = calc_pres(fr->ePBC,ir->nwall,box,ekind->ekin,total_vir,pres);
         
         /* Calculate long range corrections to pressure and energy */
         /* this adds to enerd->term[F_PRES] and enerd->term[F_ETOT], 
index c53c2f00860ae76f8080cae90fb932ad5c0834cd..c4ff969ccb2a6b774a9f222297886c2b84b068b5 100644 (file)
@@ -700,8 +700,7 @@ static void evaluate_energy(FILE *fplog,gmx_bool bVerbose,t_commrec *cr,
 
   clear_mat(ekin);
   enerd->term[F_PRES] =
-    calc_pres(fr->ePBC,inputrec->nwall,ems->s.box,ekin,vir,pres,
-             (fr->eeltype==eelPPPM)?enerd->term[F_COUL_RECIP]:0.0);
+    calc_pres(fr->ePBC,inputrec->nwall,ems->s.box,ekin,vir,pres);
 
   sum_dhdl(enerd,ems->s.lambda,inputrec);
 
index 62c04a1b17dcd308e3b59479ecbeccfe48505a62..91753f25377a1e0967d7ea6917b417158f99143e 100644 (file)
@@ -268,6 +268,7 @@ typedef struct gmx_pme {
     gmx_bool bPPnode;        /* Node also does particle-particle forces */
     gmx_bool bFEP;           /* Compute Free energy contribution */
     int nkx,nky,nkz;         /* Grid dimensions */
+    gmx_bool bP3M;           /* Do P3M: optimize the influence function */
     int pme_order;
     real epsilon_r;
 
@@ -2427,8 +2428,8 @@ void make_dft_mod(real *mod,real *data,int ndata)
 }
 
 
-
-void make_bspline_moduli(splinevec bsp_mod,int nx,int ny,int nz,int order)
+static void make_bspline_moduli(splinevec bsp_mod,
+                                int nx,int ny,int nz,int order)
 {
   int nmax=max(nx,max(ny,nz));
   real *data,*ddata,*bsp_data;
@@ -2474,6 +2475,87 @@ void make_bspline_moduli(splinevec bsp_mod,int nx,int ny,int nz,int order)
   sfree(bsp_data);
 }
 
+
+/* Return the P3M optimal influence function */
+static double do_p3m_influence(double z, int order)
+{
+    double z2,z4;
+
+    z2 = z*z;
+    z4 = z2*z2;
+
+    /* The formula and most constants can be found in:
+     * Ballenegger et al., JCTC 8, 936 (2012)
+     */
+    switch(order)
+    {
+    case 2:
+        return 1.0 - 2.0*z2/3.0;
+        break;
+    case 3:
+        return 1.0 - z2 + 2.0*z4/15.0;
+        break;
+    case 4:
+        return 1.0 - 4.0*z2/3.0 + 2.0*z4/5.0 + 4.0*z2*z4/315.0;
+        break;
+    case 5:
+        return 1.0 - 5.0*z2/3.0 + 7.0*z4/9.0 - 17.0*z2*z4/189.0 + 2.0*z4*z4/2835.0;
+        break;
+    case 6:
+        return 1.0 - 2.0*z2 + 19.0*z4/15.0 - 256.0*z2*z4/945.0 + 62.0*z4*z4/4725.0 + 4.0*z2*z4*z4/155925.0;
+        break;
+    case 7:
+        return 1.0 - 7.0*z2/3.0 + 28.0*z4/15.0 - 16.0*z2*z4/27.0 + 26.0*z4*z4/405.0 - 2.0*z2*z4*z4/1485.0 + 4.0*z4*z4*z4/6081075.0;
+    case 8:
+        return 1.0 - 8.0*z2/3.0 + 116.0*z4/45.0 - 344.0*z2*z4/315.0 + 914.0*z4*z4/4725.0 - 248.0*z4*z4*z2/22275.0 + 21844.0*z4*z4*z4/212837625.0 - 8.0*z4*z4*z4*z2/638512875.0;
+        break;
+    }
+
+    return 0.0;
+}
+
+/* Calculate the P3M B-spline moduli for one dimension */
+static void make_p3m_bspline_moduli_dim(real *bsp_mod,int n,int order)
+{
+    double zarg,zai,sinzai,infl;
+    int    maxk,i;
+
+    if (order > 8)
+    {
+        gmx_fatal(FARGS,"The current P3M code only supports orders up to 8");
+    }
+
+    zarg = M_PI/n;
+
+    maxk = (n + 1)/2;
+
+    for(i=-maxk; i<0; i++)
+    {
+        zai    = zarg*i;
+        sinzai = sin(zai);
+        infl   = do_p3m_influence(sinzai,order);
+        bsp_mod[n+i] = infl*infl*pow(sinzai/zai,-2.0*order);
+    }
+    bsp_mod[0] = 1.0;
+    for(i=1; i<maxk; i++)
+    {
+        zai    = zarg*i;
+        sinzai = sin(zai);
+        infl   = do_p3m_influence(sinzai,order);
+        bsp_mod[i] = infl*infl*pow(sinzai/zai,-2.0*order);
+    }
+}
+
+/* Calculate the P3M B-spline moduli */
+static void make_p3m_bspline_moduli(splinevec bsp_mod,
+                                    int nx,int ny,int nz,int order)
+{
+    make_p3m_bspline_moduli_dim(bsp_mod[XX],nx,order);
+    make_p3m_bspline_moduli_dim(bsp_mod[YY],ny,order);
+    make_p3m_bspline_moduli_dim(bsp_mod[ZZ],nz,order);
+}
+
+
 static void setup_coordinate_communication(pme_atomcomm_t *atc)
 {
   int nslab,n,i;
@@ -2938,6 +3020,7 @@ int gmx_pme_init(gmx_pme_t *         pmedata,
     pme->nkx         = ir->nkx;
     pme->nky         = ir->nky;
     pme->nkz         = ir->nkz;
+    pme->bP3M        = (ir->coulombtype == eelP3M_AD || getenv("GMX_PME_P3M") != NULL);
     pme->pme_order   = ir->pme_order;
     pme->epsilon_r   = ir->epsilon_r;
 
@@ -3108,7 +3191,16 @@ int gmx_pme_init(gmx_pme_t *         pmedata,
         pme->cfftgridB          = NULL;
     }
 
-    make_bspline_moduli(pme->bsp_mod,pme->nkx,pme->nky,pme->nkz,pme->pme_order);
+    if (!pme->bP3M)
+    {
+        /* Use plain SPME B-spline interpolation */
+        make_bspline_moduli(pme->bsp_mod,pme->nkx,pme->nky,pme->nkz,pme->pme_order);
+    }
+    else
+    {
+        /* Use the P3M grid-optimized influence function */
+        make_p3m_bspline_moduli(pme->bsp_mod,pme->nkx,pme->nky,pme->nkz,pme->pme_order);
+    }
 
     /* Use atc[0] for spreading */
     init_atomcomm(pme,&pme->atc[0],cr,nnodes_major > 1 ? 0 : 1,TRUE);
@@ -4256,6 +4348,10 @@ int gmx_pme_do(gmx_pme_t pme,
             }
         }
     }
+    else
+    {
+        *energy = 0;
+    }
 
     if (debug)
     {
diff --git a/src/mdlib/pppm.c b/src/mdlib/pppm.c
deleted file mode 100644 (file)
index b4a4f86..0000000
+++ /dev/null
@@ -1,687 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GROwing Monsters And Cloning Shrimps
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <math.h>
-#include "physics.h"
-#include "typedefs.h"
-#include "smalloc.h"
-#include "vec.h"
-#include "xvgr.h"
-#include "gmx_fatal.h"
-#include "txtdump.h"
-#include "network.h"
-#include "nrnb.h"
-#include "pppm.h"
-#include "coulomb.h"
-#include "mdrun.h"
-#include "gmx_fft.h"
-#include "pme.h"
-
-#ifdef GMX_MPI
-#include "gmx_parallel_3dfft.h"
-#endif
-
-#define llim  (-1)
-#define ulim   (1)
-#define llim2 (-3)
-#define ulim2  (3)
-
-
-
-/* PPPM temporarily disabled while working on 2D PME */
-#define DISABLE_PPPM
-
-
-
-#ifndef DISABLE_PPPM
-
-/* TODO: fix thread-safety */
-
-static void calc_invh(rvec box,int nx,int ny,int nz,rvec invh)
-{
-  invh[XX] = nx/box[XX];
-  invh[YY] = ny/box[YY];
-  invh[ZZ] = nz/box[ZZ];
-}
-
-static void calc_weights(int iatom,int nx,int ny,int nz,
-                        rvec x,rvec box,rvec invh,ivec ixyz,real WXYZ[])
-{
-  const  real half=0.5;
-  tensor wxyz;
-  real   abc,ttt,fact;
-#ifdef DEBUG
-  real   wtot;
-#endif
-  ivec   nxyz;
-  int    it,j,k,m,nm;
-  real   Wx,Wy,Wzx,Wzy,Wzz;
-  
-  fact = 0.125;
-  
-  nxyz[XX] = nx;
-  nxyz[YY] = ny;
-  nxyz[ZZ] = nz;
-  for(m=0; (m<DIM); m++) {
-    /* Put particle in the box... */  
-    ttt = x[m]*invh[m];
-    
-    /* Round to nearest grid point. Do the math in integer! */
-    it  = (ttt+0.5);
-    nm  = nxyz[m];
-    if (it < 0) {
-      ttt+=nm;
-      it +=nm;
-    }
-    else if (it >= nm) {
-      ttt-=nm;
-      it -=nm;
-    }
-    if ((it < 0) || (it >= nxyz[m]))
-      gmx_fatal(FARGS,"iatom = %d, it = %d, x=%f, ttt=%f",iatom,it,x[m],ttt);
-    ixyz[m]    = it;
-    
-    /* Fraction (offset) from grid point */
-    abc        = ttt - (real)ixyz[m];
-    
-    wxyz[m][0] = sqr((real)(half  - abc));
-    wxyz[m][1] = 1.5 - 2.0*sqr(abc);
-    wxyz[m][2] = sqr((real)(half  + abc));
-  }
-  Wzx=wxyz[ZZ][XX];
-  Wzy=wxyz[ZZ][YY];
-  Wzz=wxyz[ZZ][ZZ];
-  for(j=m=0; (j<DIM); j++) {
-    Wx = wxyz[XX][j]*fact;
-    for(k=0; (k<DIM); k++,m+=3) {
-      Wy        = Wx*wxyz[YY][k];
-      WXYZ[m]   = Wy*Wzx;
-      WXYZ[m+1] = Wy*Wzy;
-      WXYZ[m+2] = Wy*Wzz;
-    }
-  }
-#ifdef DEBUG
-  wtot = 0;
-  for(j=0; (j<27); j++)
-    wtot+=WXYZ[j];
-  fprintf(stderr,"wtot = %g\n",wtot);
-#endif
-#ifdef HACK
-  for(j=0; (j<27); j++)
-    WXYZ[j] = 0;
-  WXYZ[13] = 1.0;
-#endif
-}
-
-static void calc_nxyz(int nx,int ny,int nz,
-                     int **nnx,int **nny,int **nnz)
-{
-  int i;
-  
-  snew(*nnx,3*nx);
-  snew(*nny,3*ny);
-  snew(*nnz,3*nz);
-  for(i=0; (i<3*nx); i++)
-    (*nnx)[i] = i % nx;
-  for(i=0; (i<3*ny); i++)
-    (*nny)[i] = i % ny;
-  for(i=0; (i<3*nz); i++)
-    (*nnz)[i] = i % nz;
-}
-       
-static void spread_q(FILE *log,gmx_bool bVerbose,
-                    int start,int nr,
-                    rvec x[],real charge[],rvec box,
-                    t_fftgrid *grid,t_nrnb *nrnb)
-{
-  static gmx_bool bFirst = TRUE;
-  static int  *nnx,*nny,*nnz;
-  rvec   invh;
-  real   qi,qwt;
-#ifdef DEBUG
-  real   qt;
-#endif
-  real   WXYZ[27];
-  ivec   ixyz;
-  int    i,iX,iY,iZ,index;
-  int    jx,jy,jz,jcx,jcy,jcz;
-  int    nxyz;
-  int    nx,ny,nz,nx2,ny2,nz2,la2,la12;
-  real *ptr;
-  
-  unpack_fftgrid(grid,&nx,&ny,&nz,&nx2,&ny2,&nz2,&la2,&la12,TRUE,&ptr);
-  
-  calc_invh(box,nx,ny,nz,invh);
-
-  if (bFirst) {
-    if (log) {
-      fprintf(log,
-             "Spreading Charges using Triangle Shaped on %dx%dx%d grid\n",
-             nx,ny,nz);
-      fprintf(log,"invh = %10g,%10g,%10g\n",invh[XX],invh[YY],invh[ZZ]);
-    }
-  
-    calc_nxyz(nx,ny,nz,&nnx,&nny,&nnz);
-    
-    bFirst = FALSE;
-  }
-
-  for(i=start; (i<start+nr); i++) {
-    qi=charge[i];
-
-    /* Each charge is spread over the nearest 27 grid cells,
-     * thus we loop over -1..1 in X,Y and Z direction
-     * We apply the TSC (triangle shaped charge)
-     * see Luty et. al, JCP 103 (1995) 3014
-     */
-    
-    if (qi != 0.0) {
-      calc_weights(i,nx,ny,nz,x[i],box,invh,ixyz,WXYZ);
-      iX  = ixyz[XX] + nx;
-      iY  = ixyz[YY] + ny;
-      iZ  = ixyz[ZZ] + nz;
-
-#ifdef DEBUG
-      qt=0;
-#endif
-      nxyz = 0;
-      for(jx=-1; (jx<=1); jx++) {
-       jcx = nnx[iX + jx];
-       for(jy=-1; (jy<=1); jy++) {
-         jcy = nny[iY + jy];
-         for(jz=-1; (jz<=1); jz++,nxyz++) {
-           jcz   = nnz[iZ + jz];
-           index = INDEX(jcx,jcy,jcz);
-           qwt   = qi*WXYZ[nxyz];
-           grid->ptr[index]+=qwt;
-#ifdef DEBUG
-           qt   += qwt;
-           if (bVerbose && log)
-             fprintf(log,"spread %4d %2d %2d %2d  %10.3e, weight=%10.3e\n",
-                     index,jcx,jcy,jcz,grid->ptr[index],WXYZ[nxyz]);
-#endif
-         }
-       }
-      }
-#ifdef DEBUG
-      if (log)
-       fprintf(log,"q[%3d] = %6.3f, qwt = %6.3f\n",i,qi,qt);
-#endif
-    }
-  }
-  inc_nrnb(nrnb,eNR_SPREADQ,9*nr);
-  inc_nrnb(nrnb,eNR_WEIGHTS,3*nr);
-}
-
-static real gather_inner(int JCXYZ[],real WXYZ[],int ixw[],int iyw[],int izw[],
-                        int la2,int la12,
-                 real c1x,real c1y,real c1z,real c2x,real c2y,real c2z,
-                 real qi,rvec f,real ptr[])
-{
-  real pi,fX,fY,fZ,weight;
-  int  jxyz,m,jcx,jcy,jcz;
-  int  jcx0,jcy0,jcz0;
-  
-  pi = 0.0;
-  fX = 0.0;
-  fY = 0.0;
-  fZ = 0.0;
-  
-  /* Now loop over 27 surrounding vectors */      
-  for(jxyz=m=0; (jxyz < 27); jxyz++,m+=3) {
-    jcx    = JCXYZ[m];
-    jcy    = JCXYZ[m+1];
-    jcz    = JCXYZ[m+2];
-    weight = WXYZ[jxyz];
-    
-    jcx0   = ixw[jcx];
-    jcy0   = iyw[jcy];
-    jcz0   = izw[jcz];
-
-    /* Electrostatic Potential ! */
-    pi += weight * ptr[INDEX(jcx0,jcy0,jcz0)];
-
-    /* Forces */
-    fX += weight * ((c1x*(ptr[INDEX(ixw[jcx-1],jcy0,jcz0)] - 
-                         ptr[INDEX(ixw[jcx+1],jcy0,jcz0)] )) +
-                   (c2x*(ptr[INDEX(ixw[jcx-2],jcy0,jcz0)] - 
-                         ptr[INDEX(ixw[jcx+2],jcy0,jcz0)] )));
-    fY += weight * ((c1y*(ptr[INDEX(jcx0,iyw[jcy-1],jcz0)] -
-                         ptr[INDEX(jcx0,iyw[jcy+1],jcz0)] ))  +
-                   (c2y*(ptr[INDEX(jcx0,iyw[jcy-2],jcz0)] -
-                         ptr[INDEX(jcx0,iyw[jcy+2],jcz0)] )));
-    fZ += weight * ((c1z*(ptr[INDEX(jcx0,jcy0,izw[jcz-1])] -
-                         ptr[INDEX(jcx0,jcy0,izw[jcz+1])] ))  +
-                   (c2z*(ptr[INDEX(jcx0,jcy0,izw[jcz-2])] -
-                         ptr[INDEX(jcx0,jcy0,izw[jcz+2])] )));
-  }
-  f[XX] += qi*fX;
-  f[YY] += qi*fY;
-  f[ZZ] += qi*fZ;
-  
-  return pi;
-}
-
-static real gather_f(FILE *log,gmx_bool bVerbose,
-                    int start,int nr,rvec x[],rvec f[],real charge[],rvec box,
-                    real pot[],t_fftgrid *grid,rvec beta,t_nrnb *nrnb)
-{
-  static gmx_bool bFirst=TRUE;
-  static int  *nnx,*nny,*nnz;
-  static int  JCXYZ[81];
-  int    i,m;
-  real   energy;
-  real   qi,pi;
-  ivec   ixyz;
-  rvec   invh,c1,c2;
-  real   WXYZ[27];
-  real   c1x,c1y,c1z,c2x,c2y,c2z;
-  int    ixw[7],iyw[7],izw[7];
-  int    ll;
-  int    nx,ny,nz,nx2,ny2,nz2,la2,la12;
-  real *ptr;
-  
-  unpack_fftgrid(grid,&nx,&ny,&nz,&nx2,&ny2,&nz2,&la2,&la12,TRUE,&ptr);
-  
-  calc_invh(box,nx,ny,nz,invh);
-  
-  for(m=0; (m<DIM); m++) {
-    c1[m] = (beta[m]/2.0)*invh[m];
-    c2[m] = ((1.0-beta[m])/4.0)*invh[m];
-  }
-  c1x = c1[XX];
-  c1y = c1[YY];
-  c1z = c1[ZZ];
-  c2x = c2[XX];
-  c2y = c2[YY];
-  c2z = c2[ZZ];
-
-  if (bFirst) {
-    if (log) {
-      fprintf(log,"Gathering Forces using Triangle Shaped on %dx%dx%d grid\n",
-             nx,ny,nz);
-      fprintf(log,"beta = %10g,%10g,%10g\n",beta[XX],beta[YY],beta[ZZ]);
-      fprintf(log,"c1   = %10g,%10g,%10g\n",c1[XX],c1[YY],c1[ZZ]);
-      fprintf(log,"c2   = %10g,%10g,%10g\n",c2[XX],c2[YY],c2[ZZ]);
-      fprintf(log,"invh = %10g,%10g,%10g\n",invh[XX],invh[YY],invh[ZZ]);
-    }
-    calc_nxyz(nx,ny,nz,&nnx,&nny,&nnz);
-
-    for(i=0; (i<27); i++) {
-      JCXYZ[3*i]   = 2 + (i/9);
-      JCXYZ[3*i+1] = 2 + (i/3) % 3;
-      JCXYZ[3*i+2] = 2 + (i % 3); 
-    }
-    
-    bFirst = FALSE;
-  }
-
-  energy=0.0;            
-  for(i=start; (i<start+nr); i++) {
-    /* Each charge is spread over the nearest 27 grid cells,
-     * thus we loop over -1..1 in X,Y and Z direction
-     * We apply the TSC (triangle shaped charge)
-     * see Luty et. al, JCP 103 (1995) 3014
-     */
-     
-    calc_weights(i,nx,ny,nz,x[i],box,invh,ixyz,WXYZ);
-
-    for(ll=llim2; (ll<=ulim2); ll++) {
-      ixw[ll-llim2] = nnx[ixyz[XX]+ll+nx];
-      iyw[ll-llim2] = nny[ixyz[YY]+ll+ny];
-      izw[ll-llim2] = nnz[ixyz[ZZ]+ll+nz];
-    }
-    
-    qi      = charge[i];
-    pi      = gather_inner(JCXYZ,WXYZ,ixw,iyw,izw,la2,la12,
-                          c1x,c1y,c1z,c2x,c2y,c2z,
-                          qi,f[i],ptr);
-    
-    energy += pi*qi;
-    pot[i]  = pi;
-  }
-  
-  inc_nrnb(nrnb,eNR_GATHERF,27*nr);
-  inc_nrnb(nrnb,eNR_WEIGHTS,3*nr);
-  
-  return energy*0.5;
-}
-
-static void convolution(FILE *fp,gmx_bool bVerbose,t_fftgrid *grid,real ***ghat,
-                       t_commrec *cr)
-{
-  int      i,j,k,index;
-  real     gk;
-  int      nx,ny,nz,nx2,ny2,nz2,la2,la12;
-  t_complex  *ptr;
-  int      *nTest;
-  int jstart,jend;
-  
-  unpack_fftgrid(grid,&nx,&ny,&nz,&nx2,&ny2,&nz2,
-                &la2,&la12,FALSE,(real **)&ptr);
-  snew(nTest,grid->nptr);
-  
-  if(PAR(cr)) {
-#if (defined GMX_MPI && !defined GMX_WITHOUT_FFTW)
-    jstart=grid->pfft.local_y_start_after_transpose;
-    jend=jstart+grid->pfft.local_ny_after_transpose;
-
-    for(j=jstart; (j<jend); j++) { /* local cells */
-       for(i=0; (i<nx); i++) {
-           for(k=0;k<(nz/2+1); k++) {
-               gk    = ghat[i][j][k];
-               index = INDEX(j,i,k);
-               ptr[index].re *= gk;
-               ptr[index].im *= gk;
-               nTest[index]++;
-           }
-       }
-    }
-#ifdef DEBUG
-    for(j=jstart; (j<jend); j++) {
-       for(i=0; (i<nx); i++) {
-           for(k=0; k<(nz/2+1); k++) {
-               index = INDEX(j,i,k);
-               if (nTest[index] != 1)
-                   fprintf(fp,"Index %d sucks, set %d times\n",index,nTest[index]);
-           }
-       }
-    }
-#endif /* DEBUG */
-#endif /* GMX_MPI */
-  } else { /* if not running in parallel */
-      for(i=0; (i<nx); i++) {
-         for(j=0; (j<ny); j++) {
-             for(k=0;k<(nz/2+1); k++) {
-                 gk    = ghat[i][j][k];
-                 index = INDEX(i,j,k);
-                 ptr[index].re *= gk;
-                 ptr[index].im *= gk;
-                 nTest[index]++;
-             }
-         }
-      }
-#ifdef DEBUG
-      for(i=0; (i<nx); i++) {
-         for(j=0; (j<ny); j++) {
-             for(k=0; k<(nz/2+1); k++) {
-                 index = INDEX(i,j,k);
-                 if (nTest[index] != 1)
-                     fprintf(fp,"Index %d sucks, set %d times\n",index,nTest[index]);
-             }
-         }
-      }
-#endif 
-  }
-  sfree(nTest);
-}
-
-
-void solve_pppm(FILE *fp,t_commrec *cr,
-               t_fftgrid *grid,real ***ghat,rvec box,
-               gmx_bool bVerbose,t_nrnb *nrnb)
-{
-  int  ntot,npppm;
-  
-  /*  if (bVerbose) 
-      print_fftgrid(fp,"Q-Real",grid,grid->nxyz,"qreal.pdb",box,TRUE);*/
-  
-  gmxfft3D(grid,GMX_FFT_REAL_TO_COMPLEX,cr);
-  
-  /*  if (bVerbose) {
-      print_fftgrid(fp,"Q-k",grid,1.0,"qk-re.pdb",box,TRUE);
-      print_fftgrid(fp,"Q-k",grid,1.0,"qk-im.pdb",box,FALSE);
-      fprintf(stderr,"Doing convolution\n");
-      }*/
-  
-  convolution(fp,bVerbose,grid,ghat,cr); 
-  
-  /*  if (bVerbose) 
-      print_fftgrid(fp,"Convolution",grid,1.0,
-      "convolute.pdb",box,TRUE);*/
-  
-  gmxfft3D(grid,GMX_FFT_COMPLEX_TO_REAL,cr);
-  
-  /*  if (bVerbose) 
-      print_fftgrid(fp,"Potential",grid,1.0,"pot.pdb",box,TRUE);*/
-  
-  ntot  = grid->nxyz;  
-  npppm = ntot*log((real)ntot)/log(2.0);
-  inc_nrnb(nrnb,eNR_FFT,2*npppm);
-  inc_nrnb(nrnb,eNR_CONV,ntot);
-}
-
-
-static rvec      beta;
-static real      ***ghat=NULL;
-static t_fftgrid *grid=NULL;
-
-#endif
-
-
-int gmx_pppm_init(FILE *log,      t_commrec *cr,
-                  const output_env_t oenv, gmx_bool bVerbose,
-                  gmx_bool bOld,      matrix box,
-                  char *ghatfn,   t_inputrec *ir,
-                  gmx_bool bReproducible)
-{
-  int   nx,ny,nz,m,porder;
-  ivec  grids;
-  real  r1,rc;
-  const real tol = 1e-5;
-  rvec  box_diag,spacing;
-
-#ifdef DISABLE_PPPM
-    gmx_fatal(FARGS,"PPPM is not functional in the current version, we plan to implement PPPM through a small modification of the PME code.");
-    return -1;
-#else
-    
-#ifdef GMX_WITHOUT_FFTW
-  gmx_fatal(FARGS,"PPPM used, but GROMACS was compiled without FFTW support!\n");
-#endif
-
-  if (log) {
-    if (cr != NULL) {
-      if (cr->nnodes > 1)
-       fprintf(log,"Initializing parallel PPPM.\n");
-    }
-    fprintf(log,
-           "Will use the PPPM algorithm for long-range electrostatics\n");
-  }
-  for(m=0; m<DIM; m++)
-    box_diag[m] = box[m][m];
-
-  if (!gmx_fexist(ghatfn)) {    
-    beta[XX]=beta[YY]=beta[ZZ]= 1.85;
-    nx     = ir->nkx;
-    ny     = ir->nky;
-    nz     = ir->nkz;
-   
-    if (log) {
-      fprintf(log,"Generating Ghat function\n");
-      fprintf(log,"Grid size is %d x %d x %d\n",nx,ny,nz);
-    }
-
-    if ((nx < 4) || (ny < 4) || (nz < 4)) 
-      gmx_fatal(FARGS,"Grid must be at least 4 points in all directions");
-      
-    ghat   = mk_rgrid(nx,ny,nz);
-    mk_ghat(NULL,nx,ny,nz,ghat,box_diag,
-           ir->rcoulomb_switch,ir->rcoulomb,TRUE,bOld);
-    
-    if (bVerbose)
-      pr_scalar_gk("generghat.xvg",oenv,nx,ny,nz,box_diag,ghat);
-  }
-  else {
-    fprintf(stderr,"Reading Ghat function from %s\n",ghatfn);
-    ghat = rd_ghat(log,oenv,ghatfn,grids,spacing,beta,&porder,&r1,&rc);
-    
-    /* Check whether cut-offs correspond */
-    if ((fabs(r1-ir->rcoulomb_switch)>tol) || (fabs(rc-ir->rcoulomb)>tol)) {
-      if (log) {
-       fprintf(log,"rcoulomb_switch = %10.3e  rcoulomb = %10.3e"
-               "  r1 = %10.3e  rc = %10.3e\n",
-               ir->rcoulomb_switch,ir->rcoulomb,r1,rc);
-       fflush(log);
-      }
-      gmx_fatal(FARGS,"Cut-off lengths in tpb file and Ghat file %s "
-                 "do not match\nCheck your log file!",ghatfn);
-    }
-      
-    /* Check whether boxes correspond */
-    for(m=0; (m<DIM); m++)
-      if (fabs(box_diag[m]-grids[m]*spacing[m]) > tol) {
-       if (log) {
-         pr_rvec(log,0,"box",box_diag,DIM,TRUE);
-         pr_rvec(log,0,"grid-spacing",spacing,DIM,TRUE);
-         pr_ivec(log,0,"grid size",grids,DIM,TRUE);
-         fflush(log);
-       }
-       gmx_fatal(FARGS,"Box sizes in tpb file and Ghat file %s do not match\n"
-                   "Check your log file!",ghatfn);
-      }
-
-    if (porder != 2)
-      gmx_fatal(FARGS,"porder = %d, should be 2 in %s",porder,ghatfn);
-      
-    nx = grids[XX];
-    ny = grids[YY];
-    nz = grids[ZZ];
-    
-    if (bVerbose)
-      pr_scalar_gk("optimghat.xvg",oenv,nx,ny,nz,box_diag,ghat);
-  }
-  /* Now setup the FFT things */
-#ifdef GMX_MPI
-  cr->mpi_comm_mygroup=cr->mpi_comm_mysim;
-#endif
-  grid = mk_fftgrid(nx,ny,nz,NULL,NULL,cr,bReproducible);
-  
-  return 0;
-#endif
-}
-
-int gmx_pppm_do(FILE *log,       gmx_pme_t pme,
-               gmx_bool bVerbose,
-               rvec x[],        rvec f[],
-               real charge[],   rvec box,
-               real phi[],      t_commrec *cr,
-               int start,       int nr,
-               t_nrnb *nrnb,
-               int pme_order,   real *energy)
-{
-#ifdef DISABLE_PPPM
-    gmx_fatal(FARGS,"PPPM temporarily disabled while working on 2DPME\n");
-    return -1;
-#else
-
-    /* Make the grid empty */
-  clear_fftgrid(grid);
-  
-  /* First step: spreading the charges over the grid. */
-  spread_q(log,bVerbose,start,nr,x,charge,box,grid,nrnb);
-  
-  /* In the parallel code we have to sum the grids from neighbouring nodes */
-  if (PAR(cr))
-    gmx_sum_qgrid(pme,cr,grid,GMX_SUM_QGRID_FORWARD);
-  
-  /* Second step: solving the poisson equation in Fourier space */
-  solve_pppm(log,cr,grid,ghat,box,bVerbose,nrnb);
-  
-  /* In the parallel code we have to sum once again... */
-  if (PAR(cr))
-    gmx_sum_qgrid(pme,cr,grid,GMX_SUM_QGRID_BACKWARD);
-  
-  /* Third and last step: gather the forces, energies and potential
-   * from the grid.
-   */
-  *energy = gather_f(log,bVerbose,start,nr,x,f,charge,box,
-                    phi,grid,beta,nrnb);
-  
-  return 0;
-#endif
-}
-
-#ifndef DISABLE_PPPM
-static int gmx_pppm_opt_do(FILE *log,       gmx_pme_t pme,
-                          t_inputrec *ir,  gmx_bool bVerbose,
-                          int natoms,
-                          rvec x[],        rvec f[],
-                          real charge[],   rvec box,
-                          real phi[],      t_commrec *cr,
-                          t_nrnb *nrnb,    rvec beta,
-                          t_fftgrid *grid, gmx_bool bOld,
-                          real *energy)
-{
-  real      ***ghat;
-  int       nx,ny,nz;
-  
-  if (log)
-    fprintf(log,"Generating Ghat function\n");
-  nx     = ir->nkx;
-  ny     = ir->nky;
-  nz     = ir->nkz;
-  ghat   = mk_rgrid(nx,ny,nz);
-  mk_ghat(NULL,nx,ny,nz,ghat,box,ir->rcoulomb_switch,ir->rcoulomb,TRUE,bOld);
-  
-  /* pr_scalar_gk("generghat.xvg",nx,ny,nz,box,ghat); */
-  
-  /* Now start the actual PPPM procedure.
-   * First step: spreading the charges over the grid.
-   */
-  /* Make the grid empty */
-  clear_fftgrid(grid);
-  
-  spread_q(log,bVerbose,0,natoms,x,charge,box,grid,nrnb);
-  
-  /* Second step: solving the poisson equation in Fourier space */
-  solve_pppm(log,cr,grid,ghat,box,bVerbose,nrnb);
-  
-  /* Third and last step: gather the forces, energies and potential
-   * from the grid.
-   */
-  *energy = gather_f(log,bVerbose,0,natoms,x,f,charge,box,phi,grid,beta,nrnb);
-
-  free_rgrid(ghat,nx,ny);
-    
-  return 0;
-}
-
-#endif
index f5cbedd5f9380961b0fae4b40dc588d30b5ca4cc..eb0fb8408e9ad5a3f68b57078126055b9e9120d1 100644 (file)
@@ -70,7 +70,6 @@
 #include "force.h"
 #include "bondf.h"
 #include "pme.h"
-#include "pppm.h"
 #include "disre.h"
 #include "orires.h"
 #include "network.h"
index 5e9f62cd9a38a87d2e9a6965680097df4e70b35e..f0c73782ec758e4ac3decbaaad7672ef56d4eeed 100644 (file)
@@ -737,7 +737,6 @@ static void set_table_type(int tabsel[],const t_forcerec *fr,gmx_bool b14only)
   case eelCUT:
     tabsel[etiCOUL] = etabCOUL;
     break;
-  case eelPPPM:
   case eelPOISSON:
     tabsel[etiCOUL] = etabShift;
     break;
@@ -749,6 +748,7 @@ static void set_table_type(int tabsel[],const t_forcerec *fr,gmx_bool b14only)
     break;
   case eelEWALD:
   case eelPME:
+  case eelP3M_AD:
     tabsel[etiCOUL] = etabEwald;
     break;
   case eelPMESWITCH:
index ce5c3e68d35de15def40e966be7bf925f6f498bf..e9d35b7e7614f7538bc37fb2f148172f6811ecfd 100644 (file)
@@ -75,7 +75,6 @@
 #include "disre.h"
 #include "orires.h"
 #include "dihre.h"
-#include "pppm.h"
 #include "pme.h"
 #include "mdatoms.h"
 #include "qmmm.h"
@@ -3247,22 +3246,6 @@ int mdrunner_membed(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             }
         }
 
-        /* Initiate PPPM if necessary */
-        if (fr->eeltype == eelPPPM)
-        {
-            if (mdatoms->nChargePerturbed)
-            {
-                gmx_fatal(FARGS,"Free energy with %s is not implemented",
-                          eel_names[fr->eeltype]);
-            }
-            status = gmx_pppm_init(fplog,cr,oenv,FALSE,TRUE,box,
-                                   getenv("GMXGHAT"),inputrec, (Flags & MD_REPRODUCIBLE));
-            if (status != 0)
-            {
-                gmx_fatal(FARGS,"Error %d initializing PPPM",status);
-            }
-        }
-
         if (EEL_PME(fr->eeltype))
         {
             ewaldcoeff = fr->ewaldcoeff;