diff --git a/src/ppm_comp_pp_cell.f b/src/ppm_comp_pp_cell.f
new file mode 100644
index 0000000000000000000000000000000000000000..6c4aa778cb7ac1d86b9ecf2be408c73a973345f3
--- /dev/null
+++ b/src/ppm_comp_pp_cell.f
@@ -0,0 +1,799 @@
+      !-------------------------------------------------------------------------
+      !  Subroutine   :                  ppm_comp_pp_cell
+      !-------------------------------------------------------------------------
+      !  Parallel Particle Mesh Library (PPM)
+      !  ETH Zurich
+      !  CH-8092 Zurich, Switzerland
+      !-------------------------------------------------------------------------
+
+#if   __KERNEL == __INTERNAL
+#if   __KIND == __SINGLE_PRECISION
+      SUBROUTINE ppm_comp_pp_cell_si(xp,Np,pdata,lda,lsymm,kernel,kpar,   &
+     &    nsublist,Nm,clist,cutoff2,dpd,info)
+#elif __KIND == __DOUBLE_PRECISION
+      SUBROUTINE ppm_comp_pp_cell_di(xp,Np,pdata,lda,lsymm,kernel,kpar,   &
+     &    nsublist,Nm,clist,cutoff2,dpd,info)
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_cell_sci(xp,Np,pdata,lda,lsymm,kernel,kpar,  &
+     &    nsublist,Nm,clist,cutoff2,dpd,info)
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_cell_dci(xp,Np,pdata,lda,lsymm,kernel,kpar,  &
+     &    nsublist,Nm,clist,cutoff2,dpd,info)
+#endif
+#elif __KERNEL == __USER_FUNCTION
+#if   __KIND == __SINGLE_PRECISION
+      SUBROUTINE ppm_comp_pp_cell_su(xp,Np,pdata,lda,lsymm,kernel,kpar,   &
+     &    nsublist,Nm,clist,cutoff2,dpd,info)
+#elif __KIND == __DOUBLE_PRECISION
+      SUBROUTINE ppm_comp_pp_cell_du(xp,Np,pdata,lda,lsymm,kernel,kpar,   &
+     &    nsublist,Nm,clist,cutoff2,dpd,info)
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_cell_scu(xp,Np,pdata,lda,lsymm,kernel,kpar,  &
+     &    nsublist,Nm,clist,cutoff2,dpd,info)
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_cell_dcu(xp,Np,pdata,lda,lsymm,kernel,kpar,  &
+     &    nsublist,Nm,clist,cutoff2,dpd,info)
+#endif
+#elif __KERNEL == __LOOKUP_TABLE
+#if   __KIND == __SINGLE_PRECISION
+      SUBROUTINE ppm_comp_pp_cell_st(xp,Np,pdata,lda,lsymm,kernel,kpar,  &
+     &    nsublist,Nm,clist,cutoff2,dpd,info)
+#elif __KIND == __DOUBLE_PRECISION
+      SUBROUTINE ppm_comp_pp_cell_dt(xp,Np,pdata,lda,lsymm,kernel,kpar,  &
+     &    nsublist,Nm,clist,cutoff2,dpd,info)
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_cell_sct(xp,Np,pdata,lda,lsymm,kernel,kpar, &
+     &    nsublist,Nm,clist,cutoff2,dpd,info)
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_cell_dct(xp,Np,pdata,lda,lsymm,kernel,kpar, &
+     &    nsublist,Nm,clist,cutoff2,dpd,info)
+#endif
+#endif
+      !!! This routine computes kernel interactions by direct
+      !!! particle-particle interactions using cell lists.
+      !!!
+      !!! [NOTE]
+      !!! Loops over lda have been explicitly unrolled for the cases of
+      !!! `lda.EQ.1` and `lda.EQ.2` to allow vectorization in these cases.
+      !!!
+      !!! [WARNING]
+      !!! clist has to be created by the user program before
+      !!! calling this routine. ppm_neighlist_clist should be
+      !!! used for this. The reason is that this allows the
+      !!! user to have multiple cell lists and call this
+      !!! routine for the appropriate one. Do not forget to
+      !!! call ppm_neighlist_clist_destroy and to DELLOCATE
+      !!! Nm after the cell lists are no longer needed.
+      !!!
+      !!! [NOTE]
+      !!! dpd needs to be allocated to proper size before
+      !!! calling this routine. Also, this routine is not
+      !!! resetting dpd to zero before doing the PP
+      !!! interactions. This allows contributions from
+      !!! different kernels to be accumulated. If needed,
+      !!! set it to zero before calling this routine the
+      !!! first time.
+      !-------------------------------------------------------------------------
+      !  Modules
+      !-------------------------------------------------------------------------
+      USE ppm_module_data
+      USE ppm_module_data_neighlist
+      USE ppm_module_substart
+      USE ppm_module_substop
+      USE ppm_module_error
+      USE ppm_module_neighlist_MkNeighIdx
+      IMPLICIT NONE
+#if   __KIND == __SINGLE_PRECISION | __KIND == __SINGLE_PRECISION_COMPLEX
+      INTEGER, PARAMETER :: MK = ppm_kind_single
+#elif __KIND == __DOUBLE_PRECISION | __KIND == __DOUBLE_PRECISION_COMPLEX
+      INTEGER, PARAMETER :: MK = ppm_kind_double
+#endif
+      !-------------------------------------------------------------------------
+      !  Includes
+      !-------------------------------------------------------------------------
+#include "ppm_define.h"
+      !-------------------------------------------------------------------------
+      !  Arguments
+      !-------------------------------------------------------------------------
+      REAL(MK)   , DIMENSION(:,:), INTENT(IN   ) :: xp
+      !!! particle co-ordinates
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:,:), INTENT(IN   ) :: pdata
+      !!! particle strengths used for interaction.
+      !!! Overloaded type: single,double
+      REAL(MK)   , DIMENSION(:,:), INTENT(  OUT) :: dpd
+      !!! Change of particle data (pdata) due to interaction.
+      !!! This is not initialized by this routine!
+      !!! Overloaded types: single,double.
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:,:), INTENT(IN   ) :: pdata
+      !!! particle strengths used for interaction.
+      !!! Overloaded types: single complex, double complex.
+      COMPLEX(MK), DIMENSION(:,:), INTENT(  OUT) :: dpd
+      !!! Change of particle data (pdata) due to interaction.
+      !!! This is not initialized by this routine!
+      !!! Overloaded types: single complex, double complex.
+#endif
+      INTEGER                    , INTENT(IN   ) :: Np
+      !!! number of particles on this proc.
+      INTEGER                    , INTENT(IN   ) :: lda
+      !!! lading dimension of pdata.
+      INTEGER                    , INTENT(IN   ) :: nsublist
+      !!! number of subdomains on the local processor
+#if   __KERNEL == __INTERNAL
+      INTEGER                    , INTENT(IN   ) :: kernel
+      !!! kernel to be used for PP interactions. To use ppm-internal
+      !!! kernels, specify one of:
+      !!!
+      !!! ---------------------------------------
+      !!!    ppm_param_kerel_laplace2d_2p
+      !!!      (2nd order Laplacian, polynomial in 2D)
+      !!!    ppm_param_kerel_laplace3d_2p
+      !!!      (2nd order Laplacian, polynomial in 3D)
+      !!! ---------------------------------------
+      !!!
+      !!! To use your own kernel function, pass the function pointer here.
+      !!! Your function should take one argument and return one value.
+      !!! The third possibility is to pass a lookup table with tabulated
+      !!! kernel values. Such a table can be created using
+      !!! ppm_comp_pp_mk_table.
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:)  , INTENT(IN   ) :: kpar
+      !!! Kernel parameters. See documentation or ppm_comp_pp_kernels.inc
+      !!! for description. Type can be single, double
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:)  , INTENT(IN   ) :: kpar
+      !!! Kernel parameters. See documentation or ppm_comp_pp_kernels.inc
+      !!! for description. Type can be single complex or double complex.
+#endif
+#elif __KERNEL == __LOOKUP_TABLE
+      REAL(MK)                   , INTENT(IN   ) :: kpar
+      !!! Kernel parameters. Lookup table version.
+      !!! Pass dxtableinv (the inverse of the table spacing) as a scalar here.
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:  ), INTENT(IN   ) :: kernel
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:  ), INTENT(IN   ) :: kernel
+#endif
+      !!! lookup table with tabulated kernel values. Such a table can
+      !!! be created using <<ppm_comp_pp_mk_table>>.
+#endif
+      LOGICAL                    , INTENT(IN   ) :: lsymm
+      !!! Do symmetric PP interactions?
+      TYPE(ppm_type_ptr_to_clist), DIMENSION(:), INTENT(IN) :: clist
+      !!! Cell list as a list of ptr_to_clist.
+      !!!
+      !!! particle index list of isub: `clist(isub)%lpdx(:)`                   +
+      !!! pointer to first particle in ibox of isub: ` clist(isub)%lhbx(ibox)`
+      INTEGER    , DIMENSION(:,:), INTENT(IN   ) :: Nm
+      !!! number of cells in x,y,(z) directions (including the ghosts cells)
+      !!! in each subdomain.
+      !!!
+      !!! 1st index: direction. second index: subid.
+      REAL(MK)                   , INTENT(IN   ) :: cutoff2
+      !!! Squared PP interaction cutoff. Should be .LE. cell size.
+      INTEGER                    , INTENT(  OUT) :: info
+      !!! Returns status, 0 upon success
+      !-------------------------------------------------------------------------
+      !  Local variables
+      !-------------------------------------------------------------------------
+      ! counters
+      INTEGER                                    :: i,idom,ibox,jbox,idx
+      INTEGER                                    :: ipart,jpart,ip,jp
+      INTEGER                                    :: cbox,iinter,j,k,ispec
+      ! coordinate differences
+      REAL(MK)                                   :: dx,dy,dz
+      REAL(MK)                                   :: factor,factor2
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)                                   :: summ,summ2
+      REAL(MK)                                   :: eta,dm
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK)                                :: summ,summ2
+      COMPLEX(MK)                                :: eta,dm
+#endif
+      ! square of inter particle distance
+      REAL(MK)                                   :: dij,dij2,dij4,dij5
+      ! start and end particle in a box
+      INTEGER                                    :: istart,iend,jstart,jend
+      ! cell neighbor lists
+      INTEGER, DIMENSION(:,:), POINTER           :: inp,jnp
+      ! number of interactions for each cell
+      INTEGER, SAVE                              :: nnp
+      ! cell offsets for box index
+      INTEGER                                    :: n1,n2,nz
+      REAL(MK)                                   :: t0
+      !-------------------------------------------------------------------------
+      !  Externals
+      !-------------------------------------------------------------------------
+#if   __KERNEL == __USER_FUNCTION
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:)  , INTENT(IN   ) :: kpar
+      INTERFACE
+          FUNCTION kernel(x,kpar)
+              IMPLICIT NONE
+#if   __KIND == __SINGLE_PRECISION | __KIND == __SINGLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0E0)
+#elif __KIND == __DOUBLE_PRECISION | __KIND == __DOUBLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0D0)
+#endif
+              REAL(MK), INTENT(IN) :: x
+              REAL(MK), DIMENSION(:), INTENT(IN) :: kpar
+              REAL(MK) :: kernel
+          END FUNCTION kernel
+      END INTERFACE
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:)  , INTENT(IN   ) :: kpar
+      INTERFACE
+          FUNCTION kernel(x,kpar)
+              IMPLICIT NONE
+#if   __KIND == __SINGLE_PRECISION | __KIND == __SINGLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0E0)
+#elif __KIND == __DOUBLE_PRECISION | __KIND == __DOUBLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0D0)
+#endif
+              REAL(MK), INTENT(IN) :: x
+              COMPLEX(MK), DIMENSION(:), INTENT(IN) :: kpar
+              COMPLEX(MK) :: kernel
+          END FUNCTION kernel
+      END INTERFACE
+#endif
+#endif
+
+      !-------------------------------------------------------------------------
+      !  Initialise
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_comp_pp_cell',t0,info)
+
+      !-------------------------------------------------------------------------
+      !  Check arguments.
+      !-------------------------------------------------------------------------
+      IF (ppm_debug .GT. 0) THEN
+          IF (.NOT. ppm_initialized) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_ppm_noinit,'ppm_comp_pp_cell',  &
+     &            'Please call ppm_init first!',__LINE__,info)
+              GOTO 9999
+          ENDIF
+          IF (Np .LT. 0) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_cell',  &
+     &            'Np must be >=0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+          IF (lda .LT. 1) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_cell',  &
+     &            'lda must be >0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+          IF (nsublist .LT. 0) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_cell',  &
+     &            'nsublist must be >=0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+          IF (cutoff2 .LT. 0.0_MK) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_cell',  &
+     &            'cutoff2 must be >=0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+#if   __KERNEL == __LOOKUP_TABLE
+          IF (kpar .LT. 0.0_MK) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_cell',  &
+     &            'kpar (dxtableinv) must be >=0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+#endif
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      !  Build interaction index lists
+      !-------------------------------------------------------------------------
+      CALL ppm_neighlist_MkNeighIdx(lsymm,inp,jnp,nnp,info)
+
+      !-------------------------------------------------------------------------
+      !  PARTICLE-PARTICLE INTERACTIONS using symmetry
+      !-------------------------------------------------------------------------
+      IF (lsymm) THEN
+          DO idom=1,nsublist
+              n1  = Nm(1,idom)
+              n2  = Nm(1,idom)*Nm(2,idom)
+              nz  = Nm(3,idom)
+              IF (ppm_dim .EQ. 2) THEN
+                  n2 = 0
+                  nz = 2
+              ENDIF
+              ! loop over all REAL cells (the -2 in the end does this)
+              DO k=0,nz-2
+                  DO j=0,Nm(2,idom)-2
+                      DO i=0,Nm(1,idom)-2
+                          ! index of the center box
+                          cbox = i + 1 + n1*j + n2*k
+                          ! loop over all box-box interactions
+                          DO iinter=1,nnp
+                              ! determine box indices for this interaction
+                              ibox = cbox+(inp(1,iinter)+n1*inp(2,iinter)+ &
+     &                               n2*inp(3,iinter))
+                              jbox = cbox+(jnp(1,iinter)+n1*jnp(2,iinter)+ &
+     &                               n2*jnp(3,iinter))
+                              !-------------------------------------------------
+                              !  Read indices and check if box is empty
+                              !-------------------------------------------------
+                              istart = clist(idom)%lhbx(ibox)
+                              iend   = clist(idom)%lhbx(ibox+1)-1
+                              IF (iend .LT. istart) CYCLE
+                              !-------------------------------------------------
+                              !  Within the box itself use symmetry and avoid
+                              !  adding the particle itself to its own list
+                              !-------------------------------------------------
+                              IF (ibox .EQ. jbox) THEN
+                                  DO ipart=istart,iend
+                                      ip = clist(idom)%lpdx(ipart)
+                                      IF (lda .EQ. 1) THEN
+                                          summ = 0.0_MK
+#ifdef __SXF90
+!CDIR NODEP
+#endif
+                                          DO jpart=(ipart+1),iend
+                                              jp = clist(idom)%lpdx(jpart)
+                                              dx  = xp(1,ip) - xp(1,jp)
+                                              dy  = xp(2,ip) - xp(2,jp)
+                                              IF (ppm_dim .GT. 2) THEN
+                                                  dz  = xp(3,ip) - xp(3,jp)
+                                                  dij = (dx*dx)+(dy*dy)+(dz*dz)
+                                              ELSE
+                                                  dz = 0.0_MK
+                                                  dij = (dx*dx)+(dy*dy)
+                                              ENDIF
+                                              IF (dij .GT. cutoff2) CYCLE
+                                              !---------------------------------
+                                              ! Particle ip interacts with
+                                              ! particle jp here... and
+                                              ! vice versa to use symmetry.
+                                              !---------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                                              dm   = eta*(pdata(1,jp) -   &
+     &                                            pdata(1,ip))
+                                              summ = summ + dm
+                                              dpd(1,jp) = dpd(1,jp) - dm
+                                          ENDDO
+                                          dpd(1,ip) = dpd(1,ip) + summ
+                                      ELSEIF (lda .EQ. 2) THEN
+                                          summ = 0.0_MK
+                                          summ2 = 0.0_MK
+#ifdef __SXF90
+!CDIR NODEP
+#endif
+                                          DO jpart=(ipart+1),iend
+                                              jp = clist(idom)%lpdx(jpart)
+                                              dx  = xp(1,ip) - xp(1,jp)
+                                              dy  = xp(2,ip) - xp(2,jp)
+                                              IF (ppm_dim .GT. 2) THEN
+                                                  dz  = xp(3,ip) - xp(3,jp)
+                                                  dij = (dx*dx)+(dy*dy)+(dz*dz)
+                                              ELSE
+                                                  dz = 0.0_MK
+                                                  dij = (dx*dx)+(dy*dy)
+                                              ENDIF
+                                              IF (dij .GT. cutoff2) CYCLE
+                                              !---------------------------------
+                                              ! Particle ip interacts with
+                                              ! particle jp here... and
+                                              ! vice versa to use symmetry.
+                                              !---------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                                              dm   = eta*(pdata(1,jp) -   &
+     &                                            pdata(1,ip))
+                                              summ = summ + dm
+                                              dpd(1,jp) = dpd(1,jp) - dm
+                                              dm   = eta*(pdata(2,jp) -   &
+     &                                            pdata(2,ip))
+                                              summ2 = summ2 + dm
+                                              dpd(2,jp) = dpd(2,jp) - dm
+                                          ENDDO
+                                          dpd(1,ip) = dpd(1,ip) + summ
+                                          dpd(2,ip) = dpd(2,ip) + summ2
+                                      ELSE
+                                          DO jpart=(ipart+1),iend
+                                              jp = clist(idom)%lpdx(jpart)
+                                              dx  = xp(1,ip) - xp(1,jp)
+                                              dy  = xp(2,ip) - xp(2,jp)
+                                              IF (ppm_dim .GT. 2) THEN
+                                                  dz  = xp(3,ip) - xp(3,jp)
+                                                  dij = (dx*dx)+(dy*dy)+(dz*dz)
+                                              ELSE
+                                                  dz = 0.0_MK
+                                                  dij = (dx*dx)+(dy*dy)
+                                              ENDIF
+                                              IF (dij .GT. cutoff2) CYCLE
+                                              !---------------------------------
+                                              ! Particle ip interacts with
+                                              ! particle jp here... and
+                                              ! vice versa to use symmetry.
+                                              !---------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                                              DO ispec=1,lda
+                                                  dm = eta*(pdata(ispec,jp)- &
+     &                                                pdata(ispec,ip))
+                                                  dpd(ispec,ip)=dpd(ispec,ip)+dm
+                                                  dpd(ispec,jp)=dpd(ispec,jp)-dm
+                                              ENDDO
+                                          ENDDO
+                                      ENDIF
+                                  ENDDO
+                              !-------------------------------------------------
+                              !  For the other boxes check all particles
+                              !-------------------------------------------------
+                              ELSE
+                                  ! get pointers to first and last particle
+                                  jstart = clist(idom)%lhbx(jbox)
+                                  jend   = clist(idom)%lhbx(jbox+1)-1
+                                  ! skip this iinter if other box is empty
+                                  IF (jend .LT. jstart) CYCLE
+                                  ! loop over all particles inside this cell
+                                  DO ipart=istart,iend
+                                      ip = clist(idom)%lpdx(ipart)
+                                      IF (lda .EQ. 1) THEN
+                                          summ = 0.0_MK
+                                          ! check against all particles
+                                          ! in the other cell
+#ifdef __SXF90
+!CDIR NODEP
+#endif
+                                          DO jpart=jstart,jend
+                                              jp = clist(idom)%lpdx(jpart)
+                                              dx  = xp(1,ip) - xp(1,jp)
+                                              dy  = xp(2,ip) - xp(2,jp)
+                                              IF (ppm_dim .GT. 2) THEN
+                                                  dz  = xp(3,ip) - xp(3,jp)
+                                                  dij = (dx*dx)+(dy*dy)+(dz*dz)
+                                              ELSE
+                                                  dz = 0.0_MK
+                                                  dij = (dx*dx)+(dy*dy)
+                                              ENDIF
+                                              IF (dij .GT. cutoff2) CYCLE
+                                              !---------------------------------
+                                              ! Particle ip interacts with
+                                              ! particle jp here... and
+                                              ! vice versa to use symmetry.
+                                              !---------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                                              dm   = eta*(pdata(1,jp) - &
+     &                                            pdata(1,ip))
+                                              summ = summ +dm
+                                              dpd(1,jp) = dpd(1,jp) - dm
+                                          ENDDO
+                                          dpd(1,ip) = dpd(1,ip) + summ
+                                      ELSEIF (lda .EQ. 2) THEN
+                                          summ = 0.0_MK
+                                          summ2 = 0.0_MK
+                                          ! check against all particles
+                                          ! in the other cell
+#ifdef __SXF90
+!CDIR NODEP
+#endif
+                                          DO jpart=jstart,jend
+                                              jp = clist(idom)%lpdx(jpart)
+                                              dx  = xp(1,ip) - xp(1,jp)
+                                              dy  = xp(2,ip) - xp(2,jp)
+                                              IF (ppm_dim .GT. 2) THEN
+                                                  dz  = xp(3,ip) - xp(3,jp)
+                                                  dij = (dx*dx)+(dy*dy)+(dz*dz)
+                                              ELSE
+                                                  dz = 0.0_MK
+                                                  dij = (dx*dx)+(dy*dy)
+                                              ENDIF
+                                              IF (dij .GT. cutoff2) CYCLE
+                                              !---------------------------------
+                                              ! Particle ip interacts with
+                                              ! particle jp here... and
+                                              ! vice versa to use symmetry.
+                                              !---------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                                              dm   = eta*(pdata(1,jp) - &
+     &                                            pdata(1,ip))
+                                              summ = summ + dm
+                                              dpd(1,jp) = dpd(1,jp) - dm
+                                              dm   = eta*(pdata(2,jp) - &
+     &                                            pdata(2,ip))
+                                              summ2 = summ2 + dm
+                                              dpd(2,jp) = dpd(2,jp) - dm
+                                          ENDDO
+                                          dpd(1,ip) = dpd(1,ip) + summ
+                                          dpd(2,ip) = dpd(2,ip) + summ2
+                                      ELSE
+                                          ! check against all particles
+                                          ! in the other cell
+                                          DO jpart=jstart,jend
+                                              jp = clist(idom)%lpdx(jpart)
+                                              dx  = xp(1,ip) - xp(1,jp)
+                                              dy  = xp(2,ip) - xp(2,jp)
+                                              IF (ppm_dim .GT. 2) THEN
+                                                  dz  = xp(3,ip) - xp(3,jp)
+                                                  dij = (dx*dx)+(dy*dy)+(dz*dz)
+                                              ELSE
+                                                  dz = 0.0_MK
+                                                  dij = (dx*dx)+(dy*dy)
+                                              ENDIF
+                                              IF (dij .GT. cutoff2) CYCLE
+                                              !---------------------------------
+                                              ! Particle ip interacts with
+                                              ! particle jp here... and
+                                              ! vice versa to use symmetry.
+                                              !---------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                                              DO ispec=1,lda
+                                                  dm = eta*(pdata(ispec,jp)- &
+     &                                                pdata(ispec,ip))
+                                                  dpd(ispec,ip)=dpd(ispec,ip)+dm
+                                                  dpd(ispec,jp)=dpd(ispec,jp)-dm
+                                              ENDDO
+                                          ENDDO
+                                      ENDIF
+                                  ENDDO
+                              ENDIF       ! ibox .EQ. jbox
+                          ENDDO           ! iinter
+                      ENDDO               ! i
+                  ENDDO                   ! j
+              ENDDO                       ! k
+          ENDDO                           ! idom
+
+      !-------------------------------------------------------------------------
+      !  PARTICLE-PARTICLE INTERACTIONS not using symmetry
+      !-------------------------------------------------------------------------
+      ELSE
+          DO idom=1,nsublist
+              n1  = Nm(1,idom)
+              n2  = Nm(1,idom)*Nm(2,idom)
+              nz  = Nm(3,idom)
+              IF (ppm_dim .EQ. 2) THEN
+                  n2 = 0
+                  nz = 2
+              ENDIF
+              ! loop over all REAL cells (the -2 in the end does this)
+              DO k=1,nz-2
+                  DO j=1,Nm(2,idom)-2
+                      DO i=1,Nm(1,idom)-2
+                          ! index of the center box
+                          cbox = i + 1 + n1*j + n2*k
+                          ! loop over all box-box interactions
+                          DO iinter=1,nnp
+                              ! determine box indices for this interaction
+                              ibox = cbox+(inp(1,iinter)+n1*inp(2,iinter)+ &
+     &                               n2*inp(3,iinter))
+                              jbox = cbox+(jnp(1,iinter)+n1*jnp(2,iinter)+ &
+     &                               n2*jnp(3,iinter))
+                              !-------------------------------------------------
+                              !  Read indices and check if box is empty
+                              !-------------------------------------------------
+                              istart = clist(idom)%lhbx(ibox)
+                              iend   = clist(idom)%lhbx(ibox+1)-1
+                              IF (iend .LT. istart) CYCLE
+                              !-------------------------------------------------
+                              !  Do all interactions within the box itself
+                              !-------------------------------------------------
+                              IF (ibox .EQ. jbox) THEN
+                                  DO ipart=istart,iend
+                                      ip = clist(idom)%lpdx(ipart)
+                                      IF (lda .EQ. 1) THEN
+                                          DO jpart=istart,iend
+                                              jp = clist(idom)%lpdx(jpart)
+                                              ! No particle interacts with
+                                              ! itself
+                                              IF (ip .EQ. jp) CYCLE
+                                              dx  = xp(1,ip) - xp(1,jp)
+                                              dy  = xp(2,ip) - xp(2,jp)
+                                              IF (ppm_dim .GT. 2) THEN
+                                                  dz  = xp(3,ip) - xp(3,jp)
+                                                  dij = (dx*dx)+(dy*dy)+(dz*dz)
+                                              ELSE
+                                                  dz = 0.0_MK
+                                                  dij = (dx*dx)+(dy*dy)
+                                              ENDIF
+                                              IF (dij .GT. cutoff2) CYCLE
+                                              !---------------------------------
+                                              ! Particle ip interacts with
+                                              ! particle jp.
+                                              !---------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                                              dm   = eta*(pdata(1,jp) -  &
+     &                                            pdata(1,ip))
+                                              dpd(1,ip) = dpd(1,ip) + dm
+                                          ENDDO
+                                      ELSEIF (lda .EQ. 2) THEN
+                                          DO jpart=istart,iend
+                                              jp = clist(idom)%lpdx(jpart)
+                                              ! No particle interacts with
+                                              ! itself
+                                              IF (ip .EQ. jp) CYCLE
+                                              dx  = xp(1,ip) - xp(1,jp)
+                                              dy  = xp(2,ip) - xp(2,jp)
+                                              IF (ppm_dim .GT. 2) THEN
+                                                  dz  = xp(3,ip) - xp(3,jp)
+                                                  dij = (dx*dx)+(dy*dy)+(dz*dz)
+                                              ELSE
+                                                  dz = 0.0_MK
+                                                  dij = (dx*dx)+(dy*dy)
+                                              ENDIF
+                                              IF (dij .GT. cutoff2) CYCLE
+                                              !---------------------------------
+                                              ! Particle ip interacts with
+                                              ! particle jp.
+                                              !---------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                                              dm   = eta*(pdata(1,jp) -  &
+     &                                            pdata(1,ip))
+                                              dpd(1,ip) = dpd(1,ip) + dm
+                                              dm   = eta*(pdata(2,jp) -  &
+     &                                            pdata(2,ip))
+                                              dpd(2,ip) = dpd(2,ip) + dm
+                                          ENDDO
+                                      ELSE
+                                          DO jpart=istart,iend
+                                              jp = clist(idom)%lpdx(jpart)
+                                              ! No particle interacts with
+                                              ! itself
+                                              IF (ip .EQ. jp) CYCLE
+                                              dx  = xp(1,ip) - xp(1,jp)
+                                              dy  = xp(2,ip) - xp(2,jp)
+                                              IF (ppm_dim .GT. 2) THEN
+                                                  dz  = xp(3,ip) - xp(3,jp)
+                                                  dij = (dx*dx)+(dy*dy)+(dz*dz)
+                                              ELSE
+                                                  dz = 0.0_MK
+                                                  dij = (dx*dx)+(dy*dy)
+                                              ENDIF
+                                              IF (dij .GT. cutoff2) CYCLE
+                                              !---------------------------------
+                                              ! Particle ip interacts with
+                                              ! particle jp.
+                                              !---------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                                              DO ispec=1,lda
+                                                  dm = eta*(pdata(ispec,jp)- &
+     &                                                pdata(ispec,ip))
+                                                  dpd(ispec,ip)=dpd(ispec,ip)+dm
+                                              ENDDO
+                                          ENDDO
+                                      ENDIF
+                                  ENDDO
+                              !-------------------------------------------------
+                              !  Do interactions with all neighboring boxes
+                              !-------------------------------------------------
+                              ELSE
+                                  ! get pointers to first and last particle
+                                  jstart = clist(idom)%lhbx(jbox)
+                                  jend   = clist(idom)%lhbx(jbox+1)-1
+                                  ! skip if empty
+                                  IF (jend .LT. jstart) CYCLE
+                                  ! loop over all particles inside this cell
+                                  DO ipart=istart,iend
+                                      ip = clist(idom)%lpdx(ipart)
+                                      IF (lda .EQ. 1) THEN
+                                          ! check against all particles
+                                          ! in the other cell
+                                          DO jpart=jstart,jend
+                                              jp = clist(idom)%lpdx(jpart)
+                                              dx  = xp(1,ip) - xp(1,jp)
+                                              dy  = xp(2,ip) - xp(2,jp)
+                                              IF (ppm_dim .GT. 2) THEN
+                                                  dz  = xp(3,ip) - xp(3,jp)
+                                                  dij = (dx*dx)+(dy*dy)+(dz*dz)
+                                              ELSE
+                                                  dz = 0.0_MK
+                                                  dij = (dx*dx)+(dy*dy)
+                                              ENDIF
+                                              IF (dij .GT. cutoff2) CYCLE
+                                              !---------------------------------
+                                              ! Particle ip interacts with
+                                              ! particle jp.
+                                              !---------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                                              dm   = eta*(pdata(1,jp) -  &
+     &                                            pdata(1,ip))
+                                              dpd(1,ip) = dpd(1,ip) + dm
+                                          ENDDO
+                                      ELSEIF (lda .EQ. 2) THEN
+                                          ! check against all particles
+                                          ! in the other cell
+                                          DO jpart=jstart,jend
+                                              jp = clist(idom)%lpdx(jpart)
+                                              dx  = xp(1,ip) - xp(1,jp)
+                                              dy  = xp(2,ip) - xp(2,jp)
+                                              IF (ppm_dim .GT. 2) THEN
+                                                  dz  = xp(3,ip) - xp(3,jp)
+                                                  dij = (dx*dx)+(dy*dy)+(dz*dz)
+                                              ELSE
+                                                  dz = 0.0_MK
+                                                  dij = (dx*dx)+(dy*dy)
+                                              ENDIF
+                                              IF (dij .GT. cutoff2) CYCLE
+                                              !---------------------------------
+                                              ! Particle ip interacts with
+                                              ! particle jp.
+                                              !---------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                                              dm   = eta*(pdata(1,jp) -  &
+     &                                            pdata(1,ip))
+                                              dpd(1,ip) = dpd(1,ip) + dm
+                                              dm   = eta*(pdata(2,jp) -  &
+     &                                            pdata(2,ip))
+                                              dpd(2,ip) = dpd(2,ip) + dm
+                                          ENDDO
+                                      ELSE
+                                          ! check against all particles
+                                          ! in the other cell
+                                          DO jpart=jstart,jend
+                                              jp = clist(idom)%lpdx(jpart)
+                                              dx  = xp(1,ip) - xp(1,jp)
+                                              dy  = xp(2,ip) - xp(2,jp)
+                                              IF (ppm_dim .GT. 2) THEN
+                                                  dz  = xp(3,ip) - xp(3,jp)
+                                                  dij = (dx*dx)+(dy*dy)+(dz*dz)
+                                              ELSE
+                                                  dz = 0.0_MK
+                                                  dij = (dx*dx)+(dy*dy)
+                                              ENDIF
+                                              IF (dij .GT. cutoff2) CYCLE
+                                              !---------------------------------
+                                              ! Particle ip interacts with
+                                              ! particle jp.
+                                              !---------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                                              DO ispec=1,lda
+                                                  dm = eta*(pdata(ispec,jp)-  &
+     &                                                pdata(ispec,ip))
+                                                  dpd(ispec,ip)=dpd(ispec,ip)+dm
+                                              ENDDO
+                                          ENDDO
+                                      ENDIF
+                                  ENDDO
+                              ENDIF       ! ibox .EQ. jbox
+                          ENDDO           ! iinter
+                      ENDDO               ! i
+                  ENDDO                   ! j
+              ENDDO                       ! k
+          ENDDO                           ! idom
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      !  Return
+      !-------------------------------------------------------------------------
+ 9999 CONTINUE
+      CALL substop('ppm_comp_pp_cell',t0,info)
+      RETURN
+#if   __KERNEL == __INTERNAL
+#if   __KIND == __SINGLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_cell_si
+#elif __KIND == __DOUBLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_cell_di
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_cell_sci
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_cell_dci
+#endif
+
+#elif __KERNEL == __USER_FUNCTION
+#if   __KIND == __SINGLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_cell_su
+#elif __KIND == __DOUBLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_cell_du
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_cell_scu
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_cell_dcu
+#endif
+
+#elif __KERNEL == __LOOKUP_TABLE
+#if   __KIND == __SINGLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_cell_st
+#elif __KIND == __DOUBLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_cell_dt
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_cell_sct
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_cell_dct
+#endif
+#endif
diff --git a/src/ppm_comp_pp_correct.f b/src/ppm_comp_pp_correct.f
new file mode 100644
index 0000000000000000000000000000000000000000..1c256fa5bbf94bb0b081b6fcd18929e84b5259aa
--- /dev/null
+++ b/src/ppm_comp_pp_correct.f
@@ -0,0 +1,343 @@
+      !-------------------------------------------------------------------------
+      !  Subroutine   :               ppm_comp_pp_correct
+      !-------------------------------------------------------------------------
+      !  Parallel Particle Mesh Library (PPM)
+      !  ETH Zurich
+      !  CH-8092 Zurich, Switzerland
+      !-------------------------------------------------------------------------
+
+#if   __KERNEL == __INTERNAL
+#if   __KIND == __SINGLE_PRECISION
+      SUBROUTINE ppm_comp_pp_correct_si(dh,cutoff,kernel,eps,kpar,targt,  &
+     &    kappa,info)
+#elif __KIND == __DOUBLE_PRECISION
+      SUBROUTINE ppm_comp_pp_correct_di(dh,cutoff,kernel,eps,kpar,targt,  &
+     &    kappa,info)
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_correct_sci(dh,cutoff,kernel,eps,kpar,targt,  &
+     &    kappa,info)
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_correct_dci(dh,cutoff,kernel,eps,kpar,targt,  &
+     &    kappa,info)
+#endif
+#elif __KERNEL == __USER_FUNCTION
+#if   __KIND == __SINGLE_PRECISION
+      SUBROUTINE ppm_comp_pp_correct_su(dh,cutoff,kernel,eps,kpar,targt,  &
+     &    kappa,info)
+#elif __KIND == __DOUBLE_PRECISION
+      SUBROUTINE ppm_comp_pp_correct_du(dh,cutoff,kernel,eps,kpar,targt,  &
+     &    kappa,info)
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_correct_scu(dh,cutoff,kernel,eps,kpar,targt,  &
+     &    kappa,info)
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_correct_dcu(dh,cutoff,kernel,eps,kpar,targt,  &
+     &    kappa,info)
+#endif
+#elif __KERNEL == __LOOKUP_TABLE
+#if   __KIND == __SINGLE_PRECISION
+      SUBROUTINE ppm_comp_pp_correct_st(dh,cutoff,kernel,eps,kpar,targt,  &
+     &    kappa,info)
+#elif __KIND == __DOUBLE_PRECISION
+      SUBROUTINE ppm_comp_pp_correct_dt(dh,cutoff,kernel,eps,kpar,targt,  &
+     &    kappa,info)
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_correct_sct(dh,cutoff,kernel,eps,kpar,targt,  &
+     &    kappa,info)
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_correct_dct(dh,cutoff,kernel,eps,kpar,targt,  &
+     &    kappa,info)
+#endif
+#endif
+      !!! Computes the discretisation correction factor
+      !!! needed to ensure that the discrete second-order
+      !!! moment of the kernel function is equal to some
+      !!! value. The kernel is evaluated on a regular mesh
+      !!! here, so this factor can only be used if the
+      !!! particles are on a regular grid (e.g. after
+      !!! remeshing).
+      !-------------------------------------------------------------------------
+      !  Modules
+      !-------------------------------------------------------------------------
+      USE ppm_module_data
+      USE ppm_module_substart
+      USE ppm_module_substop
+      USE ppm_module_error
+      USE ppm_module_write
+      IMPLICIT NONE
+#if   __KIND == __SINGLE_PRECISION | __KIND == __SINGLE_PRECISION_COMPLEX
+      INTEGER, PARAMETER :: MK = ppm_kind_single
+#elif __KIND == __DOUBLE_PRECISION | __KIND == __DOUBLE_PRECISION_COMPLEX
+      INTEGER, PARAMETER :: MK = ppm_kind_double
+#endif
+      !-------------------------------------------------------------------------
+      !  Includes
+      !-------------------------------------------------------------------------
+#include "ppm_define.h"
+      !-------------------------------------------------------------------------
+      !  Arguments
+      !-------------------------------------------------------------------------
+      REAL(MK), DIMENSION(:), INTENT(IN   ) :: dh
+      !!! grid spacings in all directions 1..ppm_dim
+      REAL(MK)              , INTENT(IN   ) :: cutoff
+      !!! PP interaction cutoff used. If no cutoff is used, pass a negative
+      !!! value here.
+      REAL(MK)              , INTENT(IN   ) :: eps
+      !!! Kernel size (width)
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)              , INTENT(IN   ) :: targt
+      !!! target value for the second order kernel moment. Overloaded types:
+      !!! single,double
+      REAL(MK)              , INTENT(  OUT) :: kappa
+      !!! computed discretisation correction factor. Every kernel evaluation has
+      !!! to be multiplied with this in order to correct for discretisation
+      !!! effects. Overloaded types: single,double
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK)           , INTENT(IN   ) :: targt
+      !!! target value for the second order kernel moment. Overloaded types:
+      !!! single complex, double complex
+      COMPLEX(MK)           , INTENT(  OUT) :: kappa
+      !!! computed discretisation correction factor. Every kernel evaluation has
+      !!! to be multiplied with this in order to correct for discretisation
+      !!! effects. Overloaded types: single complex, double complex
+#endif
+#if   __KERNEL == __INTERNAL
+      INTEGER               , INTENT(IN   ) :: kernel
+      !!! kernel for which to compute the correction. To use ppm-internal
+      !!! kernels, specify one of:
+      !!!
+      !!! ---------------------------------------
+      !!!    ppm_param_kerel_laplace2d_2p
+      !!!      (2nd order Laplacian,
+      !!!      polynomial in 2D)
+      !!!    ppm_param_kerel_laplace3d_2p
+      !!!      (2nd order Laplacian,
+      !!!      polynomial in 3D)
+      !!! ---------------------------------------
+      !!!
+      !!! To use your own kernel function, pass the function pointer here. Your
+      !!! function should take one argument and return one value.
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:), INTENT(IN   ) :: kpar
+      !!! Kernel parameters. See documentation or ppm_comp_pp_kernels.inc for
+      !!! description. Type can be single or complex.
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:), INTENT(IN   ) :: kpar
+      !!! Kernel parameters. See documentation or ppm_comp_pp_kernels.inc for
+      !!! description. Type can be single complex or double complex.
+#endif
+#elif __KERNEL == __LOOKUP_TABLE
+      REAL(MK)                   , INTENT(IN   ) :: kpar
+      !!! Kernel parameters. See documentation or ppm_comp_pp_kernels.inc for
+      !!! description. Pass dxtableinv (the inverse of the table spacing) as
+      !!! a scalar here.
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:  ), INTENT(IN   ) :: kernel
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:  ), INTENT(IN   ) :: kernel
+#endif
+      !!! Lookup table with tabulated kernel values.
+      !!! Such a table can be created using <<ppm_comp_pp_mk_table>>.
+#endif
+      INTEGER               , INTENT(  OUT) :: info
+      !!! Returns 0 upon success
+      !-------------------------------------------------------------------------
+      !  Local variables
+      !-------------------------------------------------------------------------
+      REAL(MK)                 :: t0,dij2,dij4,dij5
+      REAL(MK)                 :: hi,dx,dy,dz,dij,factor,factor2
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)                 :: eta,summ
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK)              :: eta,summ
+#endif
+      INTEGER                  :: lhx,lhy,lhz,i,j,k,idx
+      CHARACTER(LEN=ppm_char)  :: cbuf
+      !-------------------------------------------------------------------------
+      !  Externals
+      !-------------------------------------------------------------------------
+#if   __KERNEL == __USER_FUNCTION
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:), INTENT(IN   ) :: kpar
+      INTERFACE
+          FUNCTION kernel(x,kpar)
+              IMPLICIT NONE
+#if   __KIND == __SINGLE_PRECISION | __KIND == __SINGLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0E0)
+#elif __KIND == __DOUBLE_PRECISION | __KIND == __DOUBLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0D0)
+#endif
+              REAL(MK), INTENT(IN) :: x
+              REAL(MK), DIMENSION(:), INTENT(IN) :: kpar
+              REAL(MK) :: kernel
+          END FUNCTION kernel
+      END INTERFACE
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:), INTENT(IN   ) :: kpar
+      INTERFACE
+          FUNCTION kernel(x,kpar)
+              IMPLICIT NONE
+#if   __KIND == __SINGLE_PRECISION | __KIND == __SINGLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0E0)
+#elif __KIND == __DOUBLE_PRECISION | __KIND == __DOUBLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0D0)
+#endif
+              REAL(MK), INTENT(IN) :: x
+              COMPLEX(MK), DIMENSION(:), INTENT(IN) :: kpar
+              COMPLEX(MK) :: kernel
+          END FUNCTION kernel
+      END INTERFACE
+#endif
+#endif
+
+      !-------------------------------------------------------------------------
+      !  Initialise
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_comp_pp_correct',t0,info)
+      kappa = 1.0_MK
+
+      !-------------------------------------------------------------------------
+      !  Check arguments.
+      !-------------------------------------------------------------------------
+      IF (ppm_debug .GT. 0) THEN
+          IF (.NOT. ppm_initialized) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_ppm_noinit,'ppm_comp_pp_correct',  &
+     &            'Please call ppm_init first!',__LINE__,info)
+              GOTO 9999
+          ENDIF
+          IF (eps .LT. 0.0_MK) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_correct',  &
+     &            'eps must be > 0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+          IF (SIZE(dh,1) .LT. ppm_dim) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_correct',  &
+     &            'dh must be at least of length ppm_dim',__LINE__,info)
+              GOTO 9999
+          ENDIF
+          DO i=1,ppm_dim
+              IF (dh(i) .LE. 0.0_MK) THEN
+                  info = ppm_error_error
+                  CALL ppm_error(ppm_err_argument,'ppm_comp_pp_correct',  &
+     &                'dh must be >0 in all directions',__LINE__,info)
+                  GOTO 9999
+              ENDIF
+          ENDDO
+#if   __KERNEL == __LOOKUP_TABLE
+          IF (kpar .LT. 0.0_MK) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_correct',  &
+     &            'kpar (dxtableinv) must be >=0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+#endif
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      !  Integration bounds
+      !-------------------------------------------------------------------------
+      IF (cutoff .GE. 0.0_MK) THEN
+          hi  = cutoff
+      ELSE
+          hi  = 50.0_MK
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      !  Summation bounds
+      !-------------------------------------------------------------------------
+      lhx = INT(hi/dh(1))
+      lhy = INT(hi/dh(2))
+      IF (ppm_dim .GT. 2) lhz = INT(hi/dh(3))
+
+      !-------------------------------------------------------------------------
+      !  Discrete sum
+      !-------------------------------------------------------------------------
+      summ = 0.0_MK
+      IF (ppm_dim .GT. 2) THEN
+          DO i=-lhx,lhx
+              dx = REAL(i,MK)*dh(1)
+              DO j=-lhy,lhy
+                  dy = REAL(j,MK)*dh(2)
+                  DO k=-lhz,lhz
+                      dz = REAL(k,MK)*dh(3)
+                      dij  = dx*dx + dy*dy + dz*dz
+#include "ppm_comp_pp_kernels.inc"
+                      ! second order moment
+                      eta = dij*eta
+                      summ = summ + eta
+                  ENDDO
+              ENDDO
+          ENDDO
+          summ = summ*dh(1)*dh(2)*dh(3)
+      ELSE
+          DO i=-lhx,lhx
+              dx = REAL(i,MK)*dh(1)
+              DO j=-lhy,lhy
+                  dy = REAL(j,MK)*dh(2)
+                  dij  = dx*dx + dy*dy
+#include "ppm_comp_pp_kernels.inc"
+                  ! second order moment
+                  eta = dij*eta
+                  summ = summ + eta
+              ENDDO
+          ENDDO
+          summ = summ*dh(1)*dh(2)
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      !  Correction factor
+      !-------------------------------------------------------------------------
+#if __KERNEL != __LOOKUP_TABLE
+      kappa = (REAL(ppm_dim,MK)*targt*eps)/summ
+#endif
+
+      !-------------------------------------------------------------------------
+      !  Debug output
+      !-------------------------------------------------------------------------
+      IF (ppm_debug .GT. 1) THEN
+          WRITE(cbuf,'(A,F16.10)') 'Discretization correction factor: ',kappa
+          CALL ppm_write(ppm_rank,'ppm_comp_pp_correct',cbuf,info)
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      !  Return
+      !-------------------------------------------------------------------------
+ 9999 CONTINUE
+      CALL substop('ppm_comp_pp_correct',t0,info)
+      RETURN
+#if   __KERNEL == __INTERNAL
+#if   __KIND == __SINGLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_correct_si
+#elif __KIND == __DOUBLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_correct_di
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_correct_sci
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_correct_dci
+#endif
+
+#elif __KERNEL == __USER_FUNCTION
+#if   __KIND == __SINGLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_correct_su
+#elif __KIND == __DOUBLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_correct_du
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_correct_scu
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_correct_dcu
+#endif
+
+#elif __KERNEL == __LOOKUP_TABLE
+#if   __KIND == __SINGLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_correct_st
+#elif __KIND == __DOUBLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_correct_dt
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_correct_sct
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_correct_dct
+#endif
+#endif
diff --git a/src/ppm_comp_pp_doring.f b/src/ppm_comp_pp_doring.f
new file mode 100644
index 0000000000000000000000000000000000000000..a5b3bc05257ce7340c9a456e0087890d284ac1d1
--- /dev/null
+++ b/src/ppm_comp_pp_doring.f
@@ -0,0 +1,611 @@
+      !-------------------------------------------------------------------------
+      !  Subroutine   :                 ppm_comp_pp_doring
+      !-------------------------------------------------------------------------
+      !  Parallel Particle Mesh Library (PPM)
+      !  ETH Zurich
+      !  CH-8092 Zurich, Switzerland
+      !-------------------------------------------------------------------------
+
+#if   __KERNEL == __INTERNAL
+#if   __KIND == __SINGLE_PRECISION
+      SUBROUTINE ppm_comp_pp_doring_si(xp,pdata,dpd,Mpart,xp2,pdata2,dpd2, &
+     &    Lpart,lda,lsymm,kernel,kpar,mode,info)
+#elif __KIND == __DOUBLE_PRECISION
+      SUBROUTINE ppm_comp_pp_doring_di(xp,pdata,dpd,Mpart,xp2,pdata2,dpd2, &
+     &    Lpart,lda,lsymm,kernel,kpar,mode,info)
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_doring_sci(xp,pdata,dpd,Mpart,xp2,pdata2,dpd2, &
+     &    Lpart,lda,lsymm,kernel,kpar,mode,info)
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_doring_dci(xp,pdata,dpd,Mpart,xp2,pdata2,dpd2, &
+     &    Lpart,lda,lsymm,kernel,kpar,mode,info)
+#endif
+#elif __KERNEL == __USER_FUNCTION
+#if   __KIND == __SINGLE_PRECISION
+      SUBROUTINE ppm_comp_pp_doring_su(xp,pdata,dpd,Mpart,xp2,pdata2,dpd2, &
+     &    Lpart,lda,lsymm,kernel,kpar,mode,info)
+#elif __KIND == __DOUBLE_PRECISION
+      SUBROUTINE ppm_comp_pp_doring_du(xp,pdata,dpd,Mpart,xp2,pdata2,dpd2, &
+     &    Lpart,lda,lsymm,kernel,kpar,mode,info)
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_doring_scu(xp,pdata,dpd,Mpart,xp2,pdata2,dpd2, &
+     &    Lpart,lda,lsymm,kernel,kpar,mode,info)
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_doring_dcu(xp,pdata,dpd,Mpart,xp2,pdata2,dpd2, &
+     &    Lpart,lda,lsymm,kernel,kpar,mode,info)
+#endif
+#elif __KERNEL == __LOOKUP_TABLE
+#if   __KIND == __SINGLE_PRECISION
+      SUBROUTINE ppm_comp_pp_doring_st(xp,pdata,dpd,Mpart,xp2,pdata2,dpd2, &
+     &    Lpart,lda,lsymm,kernel,kpar,mode,info)
+#elif __KIND == __DOUBLE_PRECISION
+      SUBROUTINE ppm_comp_pp_doring_dt(xp,pdata,dpd,Mpart,xp2,pdata2,dpd2, &
+     &    Lpart,lda,lsymm,kernel,kpar,mode,info)
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_doring_sct(xp,pdata,dpd,Mpart,xp2,pdata2,dpd2, &
+     &    Lpart,lda,lsymm,kernel,kpar,mode,info)
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_doring_dct(xp,pdata,dpd,Mpart,xp2,pdata2,dpd2, &
+     &    Lpart,lda,lsymm,kernel,kpar,mode,info)
+#endif
+#endif
+      !!! Computes direct particle-particle interactions using the
+      !!! ring topology (N**2). This is called by ppm_comp_pp_ring and
+      !!! not by the user directly.
+      !!!
+      !!! [NOTE]
+      !!! The loops over lda are explicitly unrolled for the cases
+      !!! lda.EQ.1 and lda.EQ.2 in order to allow vectorization in these cases.
+      !-------------------------------------------------------------------------
+      !  Modules
+      !-------------------------------------------------------------------------
+      USE ppm_module_data
+      USE ppm_module_substart
+      USE ppm_module_substop
+      USE ppm_module_error
+      IMPLICIT NONE
+#if   __KIND == __SINGLE_PRECISION | __KIND == __SINGLE_PRECISION_COMPLEX
+      INTEGER, PARAMETER :: MK = ppm_kind_single
+#elif __KIND == __DOUBLE_PRECISION | __KIND == __DOUBLE_PRECISION_COMPLEX
+      INTEGER, PARAMETER :: MK = ppm_kind_double
+#endif
+      !-------------------------------------------------------------------------
+      !  Includes
+      !-------------------------------------------------------------------------
+#include "ppm_define.h"
+      !-------------------------------------------------------------------------
+      !  Arguments
+      !-------------------------------------------------------------------------
+      REAL(MK)   , DIMENSION(:,:), INTENT(IN   ) :: xp
+      !!! particle co-ordinates [Group 1]
+      REAL(MK)   , DIMENSION(:,:), INTENT(IN   ) :: xp2
+      !!! particle co-ordinates [Group 2]
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:,:), INTENT(IN   ) :: pdata
+      !!! particle data used for interaction (e.g. vorticity, strength,...)
+      !!! [Group 1]. Overloaded types: single,double
+      REAL(MK)   , DIMENSION(:,:), INTENT(IN   ) :: pdata2
+      !!! particle data used for interaction (e.g. vorticity, strength,...)
+      !!! [Group 2]. Overloaded types: single,double
+      REAL(MK)   , DIMENSION(:,:), INTENT(INOUT) :: dpd
+      !!! Change of particle data due to interaction [Group 1]
+      !!! Overloaded types: single,double
+      REAL(MK)   , DIMENSION(:,:), INTENT(INOUT) :: dpd2
+      !!! Change of particle data due to interaction [Group 2]
+      !!! Overloaded types: single,double
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:,:), INTENT(IN   ) :: pdata
+      !!! particle data used for interaction (e.g. vorticity, strength,...)
+      !!! [Group 1]. Overloaded types: single complex, double complex.
+      COMPLEX(MK), DIMENSION(:,:), INTENT(IN   ) :: pdata2
+      !!! particle data used for interaction (e.g. vorticity, strength,...)
+      !!! [Group 2]. Overloaded types: single complex, double complex.
+      COMPLEX(MK), DIMENSION(:,:), INTENT(INOUT) :: dpd
+      !!! Change of particle data due to interaction [Group 1]
+      !!! Overloaded types: single complex,double complex.
+      COMPLEX(MK), DIMENSION(:,:), INTENT(INOUT) :: dpd2
+      !!! Change of particle data due to interaction [Group 2]
+      !!! Overloaded types: single complex,double complex.
+#endif
+      INTEGER                    , INTENT(IN   ) :: Mpart
+      !!! number of particles [Group 1]
+      INTEGER                    , INTENT(IN   ) :: Lpart
+      !!! number of particles [Group 2]
+      INTEGER                    , INTENT(IN   ) :: mode
+      !!! Whether the two groups are the same or not:
+      !!!
+      !!! * 0 not the same group
+      !!! * 1 the same group
+      INTEGER                    , INTENT(IN   ) :: lda
+      !!! leading dimension of pdata,pdata2.
+#if   __KERNEL == __INTERNAL
+      INTEGER                    , INTENT(IN   ) :: kernel
+      !!! kernel for which to compute the correction. To use ppm-internal
+      !!! kernels, specify one of:
+      !!!
+      !!! ---------------------------------------
+      !!!    ppm_param_kerel_laplace2d_2p
+      !!!      (2nd order Laplacian,
+      !!!      polynomial in 2D)
+      !!!    ppm_param_kerel_laplace3d_2p
+      !!!      (2nd order Laplacian,
+      !!!      polynomial in 3D)
+      !!! ---------------------------------------
+      !!!
+      !!! To use your own kernel function, pass the function pointer here. Your
+      !!! function should take one argument and return one value.
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:)  , INTENT(IN   ) :: kpar
+      !!! Kernel parameters. See documentation or ppm_comp_pp_kernels.inc for
+      !!! description. Type can be single or complex.
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:)  , INTENT(IN   ) :: kpar
+      !!! Kernel parameters. See documentation or ppm_comp_pp_kernels.inc for
+      !!! description. Type can be single complex or double complex.
+#endif
+#elif __KERNEL == __LOOKUP_TABLE
+      REAL(MK)                   , INTENT(IN   ) :: kpar
+      !!! Kernel parameters. See documentation or ppm_comp_pp_kernels.inc for
+      !!! description. Pass dxtableinv (the inverse of the table spacing) as
+      !!! a scalar here.
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:  ), INTENT(IN   ) :: kernel
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:  ), INTENT(IN   ) :: kernel
+#endif
+      !!! Lookup table with tabulated kernel values.
+      !!! Such a table can be created using <<ppm_comp_pp_mk_table>>.
+#endif
+      LOGICAL                    , INTENT(IN   ) :: lsymm
+      !!! Whether to use symmetry or not
+      INTEGER                    , INTENT(  OUT) :: info
+      !!! Returns status, 0 upon success
+      !-------------------------------------------------------------------------
+      !  Local variables
+      !-------------------------------------------------------------------------
+      ! counters
+      INTEGER                                    :: i,j,ispec,idx
+      ! coordinate differences
+      REAL(MK)                                   :: dx,dy,dz
+      REAL(MK)                                   :: factor,factor2
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)                                   :: summ,summ2
+      REAL(MK)                                   :: eta,dm
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK)                                :: summ,summ2
+      COMPLEX(MK)                                :: eta,dm
+#endif
+      ! square of inter particle distance
+      REAL(MK)                                   :: dij,dij2,dij4,dij5
+      REAL(MK)                                   :: t0
+      !-------------------------------------------------------------------------
+      !  Externals
+      !-------------------------------------------------------------------------
+#if   __KERNEL == __USER_FUNCTION
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:)  , INTENT(IN   ) :: kpar
+      INTERFACE
+          FUNCTION kernel(x,kpar)
+              IMPLICIT NONE
+#if   __KIND == __SINGLE_PRECISION | __KIND == __SINGLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0E0)
+#elif __KIND == __DOUBLE_PRECISION | __KIND == __DOUBLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0D0)
+#endif
+              REAL(MK), INTENT(IN) :: x
+              REAL(MK), DIMENSION(:), INTENT(IN) :: kpar
+              REAL(MK) :: kernel
+          END FUNCTION kernel
+      END INTERFACE
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:)  , INTENT(IN   ) :: kpar
+      INTERFACE
+          FUNCTION kernel(x,kpar)
+              IMPLICIT NONE
+#if   __KIND == __SINGLE_PRECISION | __KIND == __SINGLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0E0)
+#elif __KIND == __DOUBLE_PRECISION | __KIND == __DOUBLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0D0)
+#endif
+              REAL(MK), INTENT(IN) :: x
+              COMPLEX(MK), DIMENSION(:), INTENT(IN) :: kpar
+              COMPLEX(MK) :: kernel
+          END FUNCTION kernel
+      END INTERFACE
+#endif
+#endif
+
+      !-------------------------------------------------------------------------
+      !  Initialise
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_comp_pp_doring',t0,info)
+
+      !-------------------------------------------------------------------------
+      !  Check arguments
+      !-------------------------------------------------------------------------
+      IF (ppm_debug .GT. 0) THEN
+          IF (Mpart .LT. 0) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_doring',  &
+     &            'Np must be >=0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+          IF (Lpart .LT. 0) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_doring',  &
+     &            'Np must be >=0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+          IF (lda .LT. 1) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_doring',  &
+     &            'lda must be >0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+          IF ((mode .NE. 0) .AND. (mode .NE. 1)) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_doring',  &
+     &            'mode must be either 0 or 1',__LINE__,info)
+              GOTO 9999
+          ENDIF
+#if   __KERNEL == __LOOKUP_TABLE
+          IF (kpar .LT. 0.0_MK) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_doring',  &
+     &            'kpar (dxtableinv) must be >=0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+#endif
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      !  Check if we are computing the selfinteraction (i.e. Group1 .EQ. Group2)
+      !-------------------------------------------------------------------------
+      IF (mode .EQ. 1) THEN
+          IF (lsymm) THEN
+              !-----------------------------------------------------------------
+              !  SYMMETRY
+              !-----------------------------------------------------------------
+              IF (lda .EQ. 1) THEN
+                 DO i = 1,Mpart
+                    summ = 0.0_MK
+                    DO j = i+1,Lpart
+                       dx  = xp(1,i) - xp2(1,j)
+                       dy  = xp(2,i) - xp2(2,j)
+                       IF (ppm_dim .GT. 2) THEN
+                           dz  = xp(3,i) - xp2(3,j)
+                           dij = (dx*dx) + (dy*dy) + (dz*dz)
+                       ELSE
+                           dz = 0.0_MK
+                           dij = (dx*dx) + (dy*dy)
+                       ENDIF
+                       !--------------------------------------------------------
+                       !  Particle i interacts with j and vice versa
+                       !--------------------------------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                       dm   = eta*(pdata2(1,j) - pdata(1,i))
+                       summ = summ + dm
+                       dpd2(1,j) = dpd2(1,j) - dm
+                    ENDDO
+                    dpd(1,i) = dpd(1,i) + summ
+                 ENDDO
+              ELSEIF (lda .EQ. 2) THEN
+                 DO i = 1,Mpart
+                    summ = 0.0_MK
+                    summ2 = 0.0_MK
+                    DO j = i+1,Lpart
+                       dx  = xp(1,i) - xp2(1,j)
+                       dy  = xp(2,i) - xp2(2,j)
+                       IF (ppm_dim .GT. 2) THEN
+                           dz  = xp(3,i) - xp2(3,j)
+                           dij = (dx*dx) + (dy*dy) + (dz*dz)
+                       ELSE
+                           dz = 0.0_MK
+                           dij = (dx*dx) + (dy*dy)
+                       ENDIF
+                       !--------------------------------------------------------
+                       !  Particle i interacts with j and vice versa
+                       !--------------------------------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                       dm   = eta*(pdata2(1,j) - pdata(1,i))
+                       summ = summ + dm
+                       dpd2(1,j) = dpd2(1,j) - dm
+                       dm   = eta*(pdata2(2,j) - pdata(2,i))
+                       summ2 = summ2 + dm
+                       dpd2(2,j) = dpd2(2,j) - dm
+                    ENDDO
+                    dpd(1,i) = dpd(1,i) + summ
+                    dpd(2,i) = dpd(2,i) + summ2
+                 ENDDO
+              ELSE
+                 DO i = 1,Mpart
+                    DO j = i+1,Lpart
+                       dx  = xp(1,i) - xp2(1,j)
+                       dy  = xp(2,i) - xp2(2,j)
+                       IF (ppm_dim .GT. 2) THEN
+                           dz  = xp(3,i) - xp2(3,j)
+                           dij = (dx*dx) + (dy*dy) + (dz*dz)
+                       ELSE
+                           dz = 0.0_MK
+                           dij = (dx*dx) + (dy*dy)
+                       ENDIF
+                       !--------------------------------------------------------
+                       !  Particle i interacts with j and vice versa
+                       !--------------------------------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                       DO ispec=1,lda
+                          dm   = eta*(pdata2(ispec,j) - pdata(ispec,i))
+                          dpd(ispec,i) = dpd(ispec,i) + dm
+                          dpd2(ispec,j) = dpd2(ispec,j) - dm
+                       ENDDO
+                    ENDDO
+                 ENDDO
+              ENDIF
+          ELSE
+              !-----------------------------------------------------------------
+              !  NO SYMMETRY
+              !-----------------------------------------------------------------
+              IF (lda .EQ. 1) THEN
+                 DO i = 1,Mpart
+                    DO j = 1,Lpart
+                       IF (i .EQ. j) CYCLE
+                       dx  = xp(1,i) - xp2(1,j)
+                       dy  = xp(2,i) - xp2(2,j)
+                       IF (ppm_dim .GT. 2) THEN
+                           dz  = xp(3,i) - xp2(3,j)
+                           dij = (dx*dx) + (dy*dy) + (dz*dz)
+                       ELSE
+                           dz = 0.0_MK
+                           dij = (dx*dx) + (dy*dy)
+                       ENDIF
+                       !--------------------------------------------------------
+                       !  Particle i interacts with j
+                       !--------------------------------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                       dm   = eta*(pdata2(1,j) - pdata(1,i))
+                       dpd(1,i) = dpd(1,i) + dm
+                    ENDDO
+                 ENDDO
+              ELSEIF (lda .EQ. 2) THEN
+                 DO i = 1,Mpart
+                    DO j = 1,Lpart
+                       IF (i .EQ. j) CYCLE
+                       dx  = xp(1,i) - xp2(1,j)
+                       dy  = xp(2,i) - xp2(2,j)
+                       IF (ppm_dim .GT. 2) THEN
+                           dz  = xp(3,i) - xp2(3,j)
+                           dij = (dx*dx) + (dy*dy) + (dz*dz)
+                       ELSE
+                           dz = 0.0_MK
+                           dij = (dx*dx) + (dy*dy)
+                       ENDIF
+                       !--------------------------------------------------------
+                       !  Particle i interacts with j
+                       !--------------------------------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                       dm   = eta*(pdata2(1,j) - pdata(1,i))
+                       dpd(1,i) = dpd(1,i) + dm
+                       dm   = eta*(pdata2(2,j) - pdata(2,i))
+                       dpd(2,i) = dpd(2,i) + dm
+                    ENDDO
+                 ENDDO
+              ELSE
+                 DO i = 1,Mpart
+                    DO j = 1,Lpart
+                       IF (i .EQ. j) CYCLE
+                       dx  = xp(1,i) - xp2(1,j)
+                       dy  = xp(2,i) - xp2(2,j)
+                       IF (ppm_dim .GT. 2) THEN
+                           dz  = xp(3,i) - xp2(3,j)
+                           dij = (dx*dx) + (dy*dy) + (dz*dz)
+                       ELSE
+                           dz = 0.0_MK
+                           dij = (dx*dx) + (dy*dy)
+                       ENDIF
+                       !--------------------------------------------------------
+                       !  Particle i interacts with j
+                       !--------------------------------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                       DO ispec=1,lda
+                          dm   = eta*(pdata2(ispec,j) - pdata(ispec,i))
+                          dpd(ispec,i) = dpd(ispec,i) + dm
+                       ENDDO
+                    ENDDO
+                 ENDDO
+              ENDIF
+          ENDIF
+
+      !-------------------------------------------------------------------------
+      !  non-self interaction (i.e. Group1 .NE. Group2)
+      !-------------------------------------------------------------------------
+      ELSE
+          IF (lsymm) THEN
+              !-----------------------------------------------------------------
+              !  SYMMETRY
+              !-----------------------------------------------------------------
+              IF (lda .EQ. 1) THEN
+                 DO i = 1,Mpart
+                    summ = 0.0_MK
+                    DO j = 1,Lpart
+                       dx  = xp(1,i) - xp2(1,j)
+                       dy  = xp(2,i) - xp2(2,j)
+                       IF (ppm_dim .GT. 2) THEN
+                           dz  = xp(3,i) - xp2(3,j)
+                           dij = (dx*dx) + (dy*dy) + (dz*dz)
+                       ELSE
+                           dz = 0.0_MK
+                           dij = (dx*dx) + (dy*dy)
+                       ENDIF
+                       !--------------------------------------------------------
+                       !  Particle i interacts with j and vice versa
+                       !--------------------------------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                       dm   = eta*(pdata2(1,j) - pdata(1,i))
+                       summ = summ + dm
+                       dpd2(1,j) = dpd2(1,j) - dm
+                    ENDDO
+                    dpd(1,i) = dpd(1,i) + summ
+                 ENDDO
+              ELSEIF (lda .EQ. 2) THEN
+                 DO i = 1,Mpart
+                    summ = 0.0_MK
+                    summ2 = 0.0_MK
+                    DO j = 1,Lpart
+                       dx  = xp(1,i) - xp2(1,j)
+                       dy  = xp(2,i) - xp2(2,j)
+                       IF (ppm_dim .GT. 2) THEN
+                           dz  = xp(3,i) - xp2(3,j)
+                           dij = (dx*dx) + (dy*dy) + (dz*dz)
+                       ELSE
+                           dz = 0.0_MK
+                           dij = (dx*dx) + (dy*dy)
+                       ENDIF
+                       !--------------------------------------------------------
+                       !  Particle i interacts with j and vice versa
+                       !--------------------------------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                       dm   = eta*(pdata2(1,j) - pdata(1,i))
+                       summ = summ + dm
+                       dpd2(1,j) = dpd2(1,j) - dm
+                       dm   = eta*(pdata2(2,j) - pdata(2,i))
+                       summ2 = summ2 + dm
+                       dpd2(2,j) = dpd2(2,j) - dm
+                    ENDDO
+                    dpd(1,i) = dpd(1,i) + summ
+                    dpd(2,i) = dpd(2,i) + summ2
+                 ENDDO
+              ELSE
+                 DO i = 1,Mpart
+                    DO j = 1,Lpart
+                       dx  = xp(1,i) - xp2(1,j)
+                       dy  = xp(2,i) - xp2(2,j)
+                       IF (ppm_dim .GT. 2) THEN
+                           dz  = xp(3,i) - xp2(3,j)
+                           dij = (dx*dx) + (dy*dy) + (dz*dz)
+                       ELSE
+                           dz = 0.0_MK
+                           dij = (dx*dx) + (dy*dy)
+                       ENDIF
+                       !--------------------------------------------------------
+                       !  Particle i interacts with j and vice versa
+                       !--------------------------------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                       DO ispec=1,lda
+                          dm   = eta*(pdata2(ispec,j) - pdata(ispec,i))
+                          dpd(ispec,i) = dpd(ispec,i) + dm
+                          dpd2(ispec,j) = dpd2(ispec,j) - dm
+                       ENDDO
+                    ENDDO
+                 ENDDO
+              ENDIF
+          ELSE
+              !-----------------------------------------------------------------
+              !  NO SYMMETRY
+              !-----------------------------------------------------------------
+              IF (lda .EQ. 1) THEN
+                 DO i = 1,Mpart
+                    DO j = 1,Lpart
+                       dx  = xp(1,i) - xp2(1,j)
+                       dy  = xp(2,i) - xp2(2,j)
+                       IF (ppm_dim .GT. 2) THEN
+                           dz  = xp(3,i) - xp2(3,j)
+                           dij = (dx*dx) + (dy*dy) + (dz*dz)
+                       ELSE
+                           dz = 0.0_MK
+                           dij = (dx*dx) + (dy*dy)
+                       ENDIF
+                       !--------------------------------------------------------
+                       !  Particle i interacts with j
+                       !--------------------------------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                       dm   = eta*(pdata2(1,j) - pdata(1,i))
+                       dpd(1,i) = dpd(1,i) + dm
+                    ENDDO
+                 ENDDO
+              ELSEIF (lda .EQ. 2) THEN
+                 DO i = 1,Mpart
+                    DO j = 1,Lpart
+                       dx  = xp(1,i) - xp2(1,j)
+                       dy  = xp(2,i) - xp2(2,j)
+                       IF (ppm_dim .GT. 2) THEN
+                           dz  = xp(3,i) - xp2(3,j)
+                           dij = (dx*dx) + (dy*dy) + (dz*dz)
+                       ELSE
+                           dz = 0.0_MK
+                           dij = (dx*dx) + (dy*dy)
+                       ENDIF
+                       !--------------------------------------------------------
+                       !  Particle i interacts with j
+                       !--------------------------------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                       dm   = eta*(pdata2(1,j) - pdata(1,i))
+                       dpd(1,i) = dpd(1,i) + dm
+                       dm   = eta*(pdata2(2,j) - pdata(2,i))
+                       dpd(2,i) = dpd(2,i) + dm
+                    ENDDO
+                 ENDDO
+              ELSE
+                 DO i = 1,Mpart
+                    DO j = 1,Lpart
+                       dx  = xp(1,i) - xp2(1,j)
+                       dy  = xp(2,i) - xp2(2,j)
+                       IF (ppm_dim .GT. 2) THEN
+                           dz  = xp(3,i) - xp2(3,j)
+                           dij = (dx*dx) + (dy*dy) + (dz*dz)
+                       ELSE
+                           dz = 0.0_MK
+                           dij = (dx*dx) + (dy*dy)
+                       ENDIF
+                       !--------------------------------------------------------
+                       !  Particle i interacts with j
+                       !--------------------------------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                       DO ispec=1,lda
+                          dm   = eta*(pdata2(ispec,j) - pdata(ispec,i))
+                          dpd(ispec,i) = dpd(ispec,i) + dm
+                       ENDDO
+                    ENDDO
+                 ENDDO
+              ENDIF
+          ENDIF
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      !  Return
+      !-------------------------------------------------------------------------
+ 9999 CONTINUE
+      CALL substop('ppm_comp_pp_doring',t0,info)
+      RETURN
+#if   __KERNEL == __INTERNAL
+#if   __KIND == __SINGLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_doring_si
+#elif __KIND == __DOUBLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_doring_di
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_doring_sci
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_doring_dci
+#endif
+
+#elif __KERNEL == __USER_FUNCTION
+#if   __KIND == __SINGLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_doring_su
+#elif __KIND == __DOUBLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_doring_du
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_doring_scu
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_doring_dcu
+#endif
+
+#elif __KERNEL == __LOOKUP_TABLE
+#if   __KIND == __SINGLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_doring_st
+#elif __KIND == __DOUBLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_doring_dt
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_doring_sct
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_doring_dct
+#endif
+#endif
diff --git a/src/ppm_comp_pp_mk_table.f b/src/ppm_comp_pp_mk_table.f
new file mode 100644
index 0000000000000000000000000000000000000000..b4963cbbe2897889020880053f2286c6ffa06bb9
--- /dev/null
+++ b/src/ppm_comp_pp_mk_table.f
@@ -0,0 +1,247 @@
+      !-------------------------------------------------------------------------
+      !  Subroutine   :               ppm_comp_pp_mk_table
+      !-------------------------------------------------------------------------
+      !  Parallel Particle Mesh Library (PPM)
+      !  ETH Zurich
+      !  CH-8092 Zurich, Switzerland
+      !-------------------------------------------------------------------------
+
+#if   __KERNEL == __INTERNAL
+#if   __KIND == __SINGLE_PRECISION
+      SUBROUTINE ppm_comp_pp_mk_table_si(kernel,kpar,ntable,cutoff2,   &
+     &    ktab,dxtableinv,info)
+#elif __KIND == __DOUBLE_PRECISION
+      SUBROUTINE ppm_comp_pp_mk_table_di(kernel,kpar,ntable,cutoff2,   &
+     &    ktab,dxtableinv,info)
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_mk_table_sci(kernel,kpar,ntable,cutoff2,   &
+     &    ktab,dxtableinv,info)
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_mk_table_dci(kernel,kpar,ntable,cutoff2,   &
+     &    ktab,dxtableinv,info)
+#endif
+#elif __KERNEL == __USER_FUNCTION
+#if   __KIND == __SINGLE_PRECISION
+      SUBROUTINE ppm_comp_pp_mk_table_su(kernel,kpar,ntable,cutoff2,   &
+     &    ktab,dxtableinv,info)
+#elif __KIND == __DOUBLE_PRECISION
+      SUBROUTINE ppm_comp_pp_mk_table_du(kernel,kpar,ntable,cutoff2,   &
+     &    ktab,dxtableinv,info)
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_mk_table_scu(kernel,kpar,ntable,cutoff2,   &
+     &    ktab,dxtableinv,info)
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_mk_table_dcu(kernel,kpar,ntable,cutoff2,   &
+     &    ktab,dxtableinv,info)
+#endif
+#endif
+      !!! Creates a lookup table for a PP interaction kernel.
+      !!! The result is returned in the variables ktab with
+      !!! indices running from 0 to ntable-1. The table
+      !!! contains kernel values eta as a function of the
+      !!! _squared_ distance x**2.
+      !-------------------------------------------------------------------------
+      !  Modules
+      !-------------------------------------------------------------------------
+      USE ppm_module_data
+      USE ppm_module_substart
+      USE ppm_module_substop
+      USE ppm_module_error
+      USE ppm_module_alloc
+      IMPLICIT NONE
+#if   __KIND == __SINGLE_PRECISION | __KIND == __SINGLE_PRECISION_COMPLEX
+      INTEGER, PARAMETER :: MK = ppm_kind_single
+#elif __KIND == __DOUBLE_PRECISION | __KIND == __DOUBLE_PRECISION_COMPLEX
+      INTEGER, PARAMETER :: MK = ppm_kind_double
+#endif
+      !-------------------------------------------------------------------------
+      !  Includes
+      !-------------------------------------------------------------------------
+#include "ppm_define.h"
+      !-------------------------------------------------------------------------
+      !  Arguments
+      !-------------------------------------------------------------------------
+      INTEGER                    , INTENT(IN   ) :: ntable
+      !!! Number of table entries to be created.
+      REAL(MK)                   , INTENT(IN   ) :: cutoff2
+      !!! Square of the cutoff used for PP interactions. The kernel will be
+      !!! tabulated up to this value.
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)     , DIMENSION(:), POINTER       :: ktab
+      !!! Tabulated kernel values 0...ntable-1.
+      !!! Overloaded types: single,double.
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK)  , DIMENSION(:), POINTER       :: ktab
+      !!! Tabulated kernel values 0...ntable-1.
+      !!! Overloaded types: single complex,double complex.
+#endif
+#if   __KERNEL == __INTERNAL
+      INTEGER                    , INTENT(IN   ) :: kernel
+      !!! kernel for which to compute the correction. To use ppm-internal
+      !!! kernels, specify one of:
+      !!!
+      !!! ---------------------------------------
+      !!!    ppm_param_kerel_laplace2d_2p
+      !!!      (2nd order Laplacian,
+      !!!      polynomial in 2D)
+      !!!    ppm_param_kerel_laplace3d_2p
+      !!!      (2nd order Laplacian,
+      !!!      polynomial in 3D)
+      !!! ---------------------------------------
+      !!!
+      !!! To use your own kernel function, pass the function pointer here. Your
+      !!! function should take one argument and return one value.
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:)  , INTENT(IN   ) :: kpar
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:)  , INTENT(IN   ) :: kpar
+#endif
+      !!! Kernel parameters. See documentation or ppm_comp_pp_kernels.inc for
+      !!! description. Type can be single, double, single complex or double
+      !!! complex. Omit this argument when using a lookup table.
+#endif
+      REAL(MK)                   , INTENT(  OUT) :: dxtableinv
+      !!! inverse of the dx (kernel evaluation locations) used to create
+      !!! the table. To use the table, look up the value
+      !!! `ktab(INT(dxtableinv*x))`.
+      INTEGER                    , INTENT(  OUT) :: info
+      !!! Returns status, 0 upon success
+      !-------------------------------------------------------------------------
+      !  Local variables
+      !-------------------------------------------------------------------------
+      INTEGER                  :: i,atable,iopt,idx
+      INTEGER, DIMENSION(1)    :: ldl,ldu
+      REAL(MK), PARAMETER      :: Rmin = 0.0_MK
+      REAL(MK)                 :: dxtable,Rmax,factor,factor2
+      REAL(MK)                 :: t0,dij,dij2,dij4,dij5,dx,dy,dz
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)                 :: eta
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK)              :: eta
+#endif
+      !-------------------------------------------------------------------------
+      !  Externals
+      !-------------------------------------------------------------------------
+#if   __KERNEL == __USER_FUNCTION
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:)  , INTENT(IN   ) :: kpar
+      INTERFACE
+          FUNCTION kernel(x,kpar)
+              IMPLICIT NONE
+#if   __KIND == __SINGLE_PRECISION | __KIND == __SINGLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0E0)
+#elif __KIND == __DOUBLE_PRECISION | __KIND == __DOUBLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0D0)
+#endif
+              REAL(MK), INTENT(IN) :: x
+              REAL(MK), DIMENSION(:), INTENT(IN) :: kpar
+              REAL(MK) :: kernel
+          END FUNCTION kernel
+      END INTERFACE
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:)  , INTENT(IN   ) :: kpar
+      INTERFACE
+          FUNCTION kernel(x,kpar)
+              IMPLICIT NONE
+#if   __KIND == __SINGLE_PRECISION | __KIND == __SINGLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0E0)
+#elif __KIND == __DOUBLE_PRECISION | __KIND == __DOUBLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0D0)
+#endif
+              REAL(MK), INTENT(IN) :: x
+              COMPLEX(MK), DIMENSION(:), INTENT(IN) :: kpar
+              COMPLEX(MK) :: kernel
+          END FUNCTION kernel
+      END INTERFACE
+#endif
+#endif
+
+      !-------------------------------------------------------------------------
+      !  Initialise
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_comp_pp_mk_table',t0,info)
+
+      !-------------------------------------------------------------------------
+      !  Check arguments.
+      !-------------------------------------------------------------------------
+      IF (ppm_debug .GT. 0) THEN
+          IF (ntable .LT. 1) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_mk_table',  &
+     &            'ntable must be >0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+          IF (cutoff2 .LT. 0.0_MK) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_mk_table',  &
+     &            'cutoff2 must be >=0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      !  Compute Rmax
+      !-------------------------------------------------------------------------
+      Rmax = cutoff2
+
+      !-------------------------------------------------------------------------
+      !  Allocate memory for table lookup
+      !-------------------------------------------------------------------------
+      atable = ntable-1
+
+      iopt = ppm_param_alloc_fit
+      ldl(1) = 0
+      ldu(1) = atable
+      CALL ppm_alloc(ktab,ldl,ldu,iopt,info)
+      IF (info .NE. ppm_param_success) THEN
+          info = ppm_error_fatal
+          CALL ppm_error(ppm_err_alloc,'ppm_comp_pp_mk_table',     &
+     &        'kernel lookup table KTAB',__LINE__,info)
+          GOTO 9999
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      !  Compute values
+      !-------------------------------------------------------------------------
+      dxtable    = (Rmax - Rmin)/REAL(atable,MK)
+      dxtableinv = 1.0_MK/dxtable
+
+      ! This hack is needed since some kernels use dx,dy,dz explicitly. DO
+      ! NOT MAKE TABLES FOR THOSE KERNELS!
+      dx = 0.0_MK
+      dy = 0.0_MK
+      dz = 0.0_MK
+      DO i=0,atable
+         dij = Rmin + REAL(i,MK)*dxtable
+#include "ppm_comp_pp_kernels.inc"
+         ktab(i) = eta
+      ENDDO
+
+      !-------------------------------------------------------------------------
+      !  Return
+      !-------------------------------------------------------------------------
+ 9999 CONTINUE
+      CALL substop('ppm_comp_pp_mk_table',t0,info)
+      RETURN
+#if   __KERNEL == __INTERNAL
+#if   __KIND == __SINGLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_mk_table_si
+#elif __KIND == __DOUBLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_mk_table_di
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_mk_table_sci
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_mk_table_dci
+#endif
+
+#elif __KERNEL == __USER_FUNCTION
+#if   __KIND == __SINGLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_mk_table_su
+#elif __KIND == __DOUBLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_mk_table_du
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_mk_table_scu
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_mk_table_dcu
+#endif
+#endif
diff --git a/src/ppm_comp_pp_ring.f b/src/ppm_comp_pp_ring.f
new file mode 100644
index 0000000000000000000000000000000000000000..fcf8017e1248bcd7eae2eea7517e3ccbb4f101b9
--- /dev/null
+++ b/src/ppm_comp_pp_ring.f
@@ -0,0 +1,503 @@
+      !-------------------------------------------------------------------------
+      !  Subroutine   :                 ppm_comp_pp_ring
+      !-------------------------------------------------------------------------
+      !  Parallel Particle Mesh Library (PPM)
+      !  ETH Zurich
+      !  CH-8092 Zurich, Switzerland
+      !-------------------------------------------------------------------------
+
+#if   __KERNEL == __INTERNAL
+#if   __KIND == __SINGLE_PRECISION
+      SUBROUTINE ppm_comp_pp_ring_si(xp,Np,pdata,lda,lsymm,kernel,kpar,   &
+     &    dpd,info)
+#elif __KIND == __DOUBLE_PRECISION
+      SUBROUTINE ppm_comp_pp_ring_di(xp,Np,pdata,lda,lsymm,kernel,kpar,   &
+     &    dpd,info)
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_ring_sci(xp,Np,pdata,lda,lsymm,kernel,kpar,  &
+     &    dpd,info)
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_ring_dci(xp,Np,pdata,lda,lsymm,kernel,kpar,  &
+     &    dpd,info)
+#endif
+#elif __KERNEL == __USER_FUNCTION
+#if   __KIND == __SINGLE_PRECISION
+      SUBROUTINE ppm_comp_pp_ring_su(xp,Np,pdata,lda,lsymm,kernel,kpar,   &
+     &    dpd,info)
+#elif __KIND == __DOUBLE_PRECISION
+      SUBROUTINE ppm_comp_pp_ring_du(xp,Np,pdata,lda,lsymm,kernel,kpar,   &
+     &    dpd,info)
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_ring_scu(xp,Np,pdata,lda,lsymm,kernel,kpar,  &
+     &    dpd,info)
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_ring_dcu(xp,Np,pdata,lda,lsymm,kernel,kpar,  &
+     &    dpd,info)
+#endif
+#elif __KERNEL == __LOOKUP_TABLE
+#if   __KIND == __SINGLE_PRECISION
+      SUBROUTINE ppm_comp_pp_ring_st(xp,Np,pdata,lda,lsymm,kernel,kpar,   &
+     &    dpd,info)
+#elif __KIND == __DOUBLE_PRECISION
+      SUBROUTINE ppm_comp_pp_ring_dt(xp,Np,pdata,lda,lsymm,kernel,kpar,   &
+     &    dpd,info)
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_ring_sct(xp,Np,pdata,lda,lsymm,kernel,kpar,   &
+     &    dpd,info)
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_ring_dct(xp,Np,pdata,lda,lsymm,kernel,kpar,   &
+     &    dpd,info)
+#endif
+#endif
+      !!! Subroutine which computes kernel interactions by
+      !!! direct global (N**2) particle-particle
+      !!! interactions using the ring topology.
+      !!!
+      !!! [NOTE]
+      !!! dpd needs to be allocated to proper size before
+      !!! calling this routine. Also, this routine is not
+      !!! resetting dpd to zero before doing the PP interactions.
+      !!! This allows contributions from different kernels to be
+      !!! accumulated. If needed, set it to zero before calling this
+      !!! routine the first time.
+      !-------------------------------------------------------------------------
+      !  Modules
+      !-------------------------------------------------------------------------
+      USE ppm_module_data
+      USE ppm_module_substart
+      USE ppm_module_substop
+      USE ppm_module_error
+      USE ppm_module_alloc
+      USE ppm_module_map_part
+      USE ppm_module_map_part_ring_shift
+      USE ppm_module_comp_pp_doring
+      IMPLICIT NONE
+#if   __KIND == __SINGLE_PRECISION | __KIND == __SINGLE_PRECISION_COMPLEX
+      INTEGER, PARAMETER :: MK = ppm_kind_single
+#elif __KIND == __DOUBLE_PRECISION | __KIND == __DOUBLE_PRECISION_COMPLEX
+      INTEGER, PARAMETER :: MK = ppm_kind_double
+#endif
+      !-------------------------------------------------------------------------
+      !  Includes
+      !-------------------------------------------------------------------------
+#include "ppm_define.h"
+      !-------------------------------------------------------------------------
+      !  Arguments
+      !-------------------------------------------------------------------------
+      REAL(MK)   , DIMENSION(:,:), INTENT(IN   ) :: xp
+      !!! particle positions
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:,:), INTENT(IN   ) :: pdata
+      !!! particle data (e.g. strengths).
+      !!! Overloaded types: single,double
+      REAL(MK)   , DIMENSION(:,:), INTENT(  OUT) :: dpd
+      !!! Change of particle data (pdata) due to interaction.
+      !!! Overloaded types: single,double.
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:,:), INTENT(IN   ) :: pdata
+      !!! particle data (e.g. strengths).
+      !!! Overloaded types: single complex,double complex.
+      COMPLEX(MK), DIMENSION(:,:), INTENT(  OUT) :: dpd
+      !!! Change of particle data (pdata) due to interaction.
+      !!! Overloaded types: single complex,double complex.
+#endif
+      LOGICAL                    , INTENT(IN   ) :: lsymm
+      !!! Whether to use symmetry or not:
+      !!!
+      !!! * `.FALSE.`  PP interaction w/o symmetry
+      !!! * `.TRUE.`  PP interaction w/  symmetry
+      INTEGER                    , INTENT(IN   ) :: Np
+      !!! number of particles on local proc.
+      INTEGER                    , INTENT(IN   ) :: lda
+      !!! leading dimension of pdata.
+#if   __KERNEL == __INTERNAL
+      INTEGER                    , INTENT(IN   ) :: kernel
+      !!! kernel for which to compute the correction. To use ppm-internal
+      !!! kernels, specify one of:
+      !!!
+      !!! ---------------------------------------
+      !!!    ppm_param_kerel_laplace2d_2p
+      !!!      (2nd order Laplacian,
+      !!!      polynomial in 2D)
+      !!!    ppm_param_kerel_laplace3d_2p
+      !!!      (2nd order Laplacian,
+      !!!      polynomial in 3D)
+      !!! ---------------------------------------
+      !!!
+      !!! To use your own kernel function, pass the function pointer here. Your
+      !!! function should take one argument and return one value.
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:)  , INTENT(IN   ) :: kpar
+      !!! Kernel parameters. See documentation or ppm_comp_pp_kernels.inc for
+      !!! description. Type can be single or complex.
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:)  , INTENT(IN   ) :: kpar
+      !!! Kernel parameters. See documentation or ppm_comp_pp_kernels.inc for
+      !!! description. Type can be single complex or double complex.
+#endif
+#elif __KERNEL == __LOOKUP_TABLE
+      REAL(MK)                   , INTENT(IN   ) :: kpar
+      !!! Kernel parameters. See documentation or ppm_comp_pp_kernels.inc for
+      !!! description. Pass dxtableinv (the inverse of the table spacing) as
+      !!! a scalar here.
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:  ), INTENT(IN   ) :: kernel
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:  ), INTENT(IN   ) :: kernel
+#endif
+      !!! Lookup table with tabulated kernel values.
+      !!! Such a table can be created using <<ppm_comp_pp_mk_table>>.
+#endif
+      INTEGER                    , INTENT(  OUT) :: info
+      !!! Returns status, 0 upon success
+      !-------------------------------------------------------------------------
+      !  Local variables
+      !-------------------------------------------------------------------------
+      INTEGER                              :: i,j
+      INTEGER                              :: hops,isource,itarget
+      INTEGER                              :: ll,lu,rl,ru
+      INTEGER                              :: Lpart,iopt
+      INTEGER    , DIMENSION(2)            :: ldu
+      REAL(MK)   , DIMENSION(:,:), POINTER :: xp2
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:,:), POINTER :: pdata2,dpd2
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:,:), POINTER :: pdata2,dpd2
+#endif
+      REAL(MK)                             :: t0
+      !-------------------------------------------------------------------------
+      !  Externals
+      !-------------------------------------------------------------------------
+#if   __KERNEL == __USER_FUNCTION
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:)  , INTENT(IN   ) :: kpar
+      INTERFACE
+          FUNCTION kernel(x,kpar)
+              IMPLICIT NONE
+#if   __KIND == __SINGLE_PRECISION | __KIND == __SINGLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0E0)
+#elif __KIND == __DOUBLE_PRECISION | __KIND == __DOUBLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0D0)
+#endif
+              REAL(MK), INTENT(IN) :: x
+              REAL(MK), DIMENSION(:), INTENT(IN) :: kpar
+              REAL(MK) :: kernel
+          END FUNCTION kernel
+      END INTERFACE
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:)  , INTENT(IN   ) :: kpar
+      INTERFACE
+          FUNCTION kernel(x,kpar)
+              IMPLICIT NONE
+#if   __KIND == __SINGLE_PRECISION | __KIND == __SINGLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0E0)
+#elif __KIND == __DOUBLE_PRECISION | __KIND == __DOUBLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0D0)
+#endif
+              REAL(MK), INTENT(IN) :: x
+              COMPLEX(MK), DIMENSION(:), INTENT(IN) :: kpar
+              COMPLEX(MK) :: kernel
+          END FUNCTION kernel
+      END INTERFACE
+#endif
+#endif
+
+      !-------------------------------------------------------------------------
+      !  Initialise
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_comp_pp_ring',t0,info)
+
+      !-------------------------------------------------------------------------
+      !  Check arguments.
+      !-------------------------------------------------------------------------
+      IF (ppm_debug .GT. 0) THEN
+          IF (.NOT. ppm_initialized) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_ppm_noinit,'ppm_comp_pp_ring',  &
+     &            'Please call ppm_init first!',__LINE__,info)
+              GOTO 9999
+          ENDIF
+          IF (Np .LT. 0) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_ring',  &
+     &            'Np must be >=0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+          IF (lda .LT. 1) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_ring',  &
+     &            'lda must be >0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+#if   __KERNEL == __LOOKUP_TABLE
+          IF (kpar .LT. 0.0_MK) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_ring',  &
+     &            'kpar (dxtableinv) must be >=0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+#endif
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      !  Allocate memory for the copy of the local particles
+      !-------------------------------------------------------------------------
+      iopt = ppm_param_alloc_fit
+      ldu(1) = ppm_dim
+      ldu(2) = Np
+      CALL ppm_alloc(xp2,ldu,iopt,info)
+      IF (info .NE. ppm_param_success) THEN
+          info = ppm_error_fatal
+          CALL ppm_error(ppm_err_alloc,'ppm_comp_pp_ring',     &
+     &        'local copy of xp XP2',__LINE__,info)
+          GOTO 9999
+      ENDIF
+      ldu(1) = lda
+      ldu(2) = Np
+      CALL ppm_alloc(pdata2,ldu,iopt,info)
+      IF (info .NE. ppm_param_success) THEN
+          info = ppm_error_fatal
+          CALL ppm_error(ppm_err_alloc,'ppm_comp_pp_ring',     &
+     &        'local copy of pdata PDATA2',__LINE__,info)
+          GOTO 9999
+      ENDIF
+      CALL ppm_alloc(dpd2,ldu,iopt,info)
+      IF (info .NE. ppm_param_success) THEN
+          info = ppm_error_fatal
+          CALL ppm_error(ppm_err_alloc,'ppm_comp_pp_ring',     &
+     &        'local copy of dpd DPD2',__LINE__,info)
+          GOTO 9999
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      !  Make a copy of all local particles including all additional info
+      !  that they carry
+      !-------------------------------------------------------------------------
+      Lpart = Np
+      xp2(1:ppm_dim,1:Np) = xp(1:ppm_dim,1:Np)
+      pdata2(1:lda,1:Np) = pdata(1:lda,1:Np)
+      dpd2(1:lda,1:Np) = dpd(1:lda,1:Np)
+
+      !-------------------------------------------------------------------------
+      !  Calculate the interactions of the local particles with themselves.
+      !-------------------------------------------------------------------------
+      CALL ppm_comp_pp_doring(xp,pdata,dpd,Np,xp2,pdata2,dpd2,Lpart,lda, &
+     &    lsymm,kernel,kpar,1,info)
+      IF (info .NE. ppm_param_success) THEN
+          info = ppm_error_error
+          CALL ppm_error(ppm_err_sub_failed,'ppm_comp_pp_ring',     &
+     &        'Interaction calculation failed.',__LINE__,info)
+          GOTO 9999
+      ENDIF
+
+#ifdef __MPI
+      !-------------------------------------------------------------------------
+      !  Compute whom to send the copy and who to receive the copy from
+      !-------------------------------------------------------------------------
+      itarget = MOD(ppm_nproc+ppm_rank-1,ppm_nproc)
+      isource = MOD(ppm_rank+1,ppm_nproc)
+
+      !-------------------------------------------------------------------------
+      !  Compute how often we have to shift a copy of the particles to the
+      !  neighbour processor
+      !-------------------------------------------------------------------------
+      IF (lsymm) THEN
+          IF (MOD(ppm_nproc,2) .EQ. 0) THEN
+              hops = (ppm_nproc/2)-1
+          ELSE
+              hops = ((ppm_nproc+1)/2)-1
+          ENDIF
+      ELSE
+          hops = ppm_nproc-1
+      ENDIF
+
+      DO i = 1,hops
+         !TODO: check the argument quantity accuracy
+         CALL ppm_map_part_ring_shift(xp2,ppm_dim,Lpart,itarget,isource,info)
+         CALL ppm_map_part(ppm_param_topo_undefined,ppm_param_topo_undefined, &
+     &                     pdata2,lda,Lpart,Lpart,ppm_param_map_push,info)
+         CALL ppm_map_part(ppm_param_topo_undefined,ppm_param_topo_undefined, &
+     &                     dpd2,lda,Lpart,Lpart,ppm_param_map_push,info)
+         CALL ppm_map_part(ppm_param_topo_undefined,ppm_param_topo_undefined, &
+     &                     xp2,ppm_dim,Lpart,Lpart,ppm_param_map_send,info)
+         CALL ppm_map_part(ppm_param_topo_undefined,ppm_param_topo_undefined, &
+     &                     dpd2,lda,Lpart,Lpart,ppm_param_map_pop,info)
+         CALL ppm_map_part(ppm_param_topo_undefined,ppm_param_topo_undefined, &
+     &                     pdata2,lda,Lpart,Lpart,ppm_param_map_pop,info)
+         CALL ppm_map_part(ppm_param_topo_undefined,ppm_param_topo_undefined, &
+     &                     xp2,ppm_dim,Lpart,Lpart,ppm_param_map_pop,info)
+
+         CALL ppm_comp_pp_doring(xp,pdata,dpd,Np,xp2,pdata2,dpd2,Lpart,  &
+     &       lda,lsymm,kernel,kpar,0,info)
+         IF (info .NE. ppm_param_success) THEN
+            info = ppm_error_error
+            CALL ppm_error(ppm_err_sub_failed,'ppm_comp_pp_ring',     &
+     &          'Interaction calculation failed.',__LINE__,info)
+            GOTO 9999
+         ENDIF
+      ENDDO
+
+      !-------------------------------------------------------------------------
+      !  If we have symmetry we only have send the particles half the round,
+      !  so we have to check the case of an even number of processors
+      !-------------------------------------------------------------------------
+      IF (lsymm .AND. (MOD(ppm_nproc,2) .EQ. 0)) THEN
+          !TODO: check the argument quantity accuracy
+          CALL ppm_map_part_ring_shift(xp2,ppm_dim,Lpart,itarget,isource,info)
+          CALL ppm_map_part(ppm_param_topo_undefined,ppm_param_topo_undefined, &
+     &                     pdata2,lda,Lpart,Lpart,ppm_param_map_push,info)
+          CALL ppm_map_part(ppm_param_topo_undefined,ppm_param_topo_undefined, &
+     &                     dpd2,lda,Lpart,Lpart,ppm_param_map_push,info)
+          CALL ppm_map_part(ppm_param_topo_undefined,ppm_param_topo_undefined, &
+     &                     xp2,ppm_dim,Lpart,Lpart,ppm_param_map_send,info)
+          CALL ppm_map_part(ppm_param_topo_undefined,ppm_param_topo_undefined, &
+     &                     dpd2,lda,Lpart,Lpart,ppm_param_map_pop,info)
+          CALL ppm_map_part(ppm_param_topo_undefined,ppm_param_topo_undefined, &
+     &                     pdata2,lda,Lpart,Lpart,ppm_param_map_pop,info)
+          CALL ppm_map_part(ppm_param_topo_undefined,ppm_param_topo_undefined, &
+     &                     xp2,ppm_dim,Lpart,Lpart,ppm_param_map_pop,info)
+
+          !---------------------------------------------------------------------
+          !  The processor with the higher ppm_rank computes the upper half of
+          !  the particles and the opposite processor the lower half
+          !---------------------------------------------------------------------
+          IF (ppm_rank .GT. hops) THEN
+              ll = (Np / 2) + 1
+              lu = Np
+              rl = 1
+              ru = Lpart
+          ELSE
+              ll = 1
+              lu = Np
+              rl = 1
+              ru = Lpart / 2
+          ENDIF
+
+          CALL ppm_comp_pp_doring(xp(:,ll:lu),pdata(:,ll:lu),dpd(:,ll:lu),&
+     &                          lu-ll+1,xp2(:,rl:ru),pdata2(:,rl:ru),     &
+     &                          dpd2(:,rl:ru),ru-rl+1,lda,lsymm,kernel,kpar, &
+     &                          0,info)
+          IF (info .NE. ppm_param_success) THEN
+             info = ppm_error_error
+             CALL ppm_error(ppm_err_sub_failed,'ppm_comp_pp_ring',     &
+     &           'Interaction calculation failed.',__LINE__,info)
+             GOTO 9999
+          ENDIF
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      !  Send the particles where they belong to
+      !-------------------------------------------------------------------------
+      IF (lsymm) THEN
+          itarget = MOD(ppm_rank+(ppm_nproc/2),ppm_nproc)
+          isource = MOD(ppm_nproc+ppm_rank-(ppm_nproc/2),ppm_nproc)
+      ENDIF
+
+      IF (itarget .NE. ppm_rank) THEN
+          !TODO: check the argument quantity accuracy
+          CALL ppm_map_part_ring_shift(xp2,ppm_dim,Lpart,itarget,isource,info)
+          CALL ppm_map_part(ppm_param_topo_undefined,ppm_param_topo_undefined, &
+     &                     pdata2,lda,Lpart,Lpart,ppm_param_map_push,info)
+          CALL ppm_map_part(ppm_param_topo_undefined,ppm_param_topo_undefined, &
+     &                     dpd2,lda,Lpart,Lpart,ppm_param_map_push,info)
+          CALL ppm_map_part(ppm_param_topo_undefined,ppm_param_topo_undefined, &
+     &                     xp2,ppm_dim,Lpart,Lpart,ppm_param_map_send,info)
+          CALL ppm_map_part(ppm_param_topo_undefined,ppm_param_topo_undefined, &
+     &                     dpd2,lda,Lpart,Lpart,ppm_param_map_pop,info)
+          CALL ppm_map_part(ppm_param_topo_undefined,ppm_param_topo_undefined, &
+     &                     pdata2,lda,Lpart,Lpart,ppm_param_map_pop,info)
+          CALL ppm_map_part(ppm_param_topo_undefined,ppm_param_topo_undefined, &
+     &                     xp2,ppm_dim,Lpart,Lpart,ppm_param_map_pop,info)
+
+          IF (Lpart .NE. Np) THEN
+             info = ppm_error_error
+             CALL ppm_error(ppm_err_part_lost,'ppm_comp_pp_ring',     &
+     &           'Not all particles came back!',__LINE__,info)
+             GOTO 9999
+          ENDIF
+      ENDIF
+#endif
+
+      !-------------------------------------------------------------------------
+      !  Add the particle changes of the local and the long traveled copy
+      !-------------------------------------------------------------------------
+      IF (lda .EQ. 1) THEN
+         DO i = 1,Np
+            dpd(1,i) = dpd(1,i) + dpd2(1,i)
+         ENDDO
+      ELSEIF (lda .EQ. 2) THEN
+         DO i = 1,Np
+            dpd(1,i) = dpd(1,i) + dpd2(1,i)
+            dpd(2,i) = dpd(2,i) + dpd2(2,i)
+         ENDDO
+      ELSE
+         DO i = 1,Np
+            DO j = 1,lda
+               dpd(j,i) = dpd(j,i) + dpd2(j,i)
+            ENDDO
+         ENDDO
+      ENDIF
+
+ 9999 CONTINUE
+
+      !-------------------------------------------------------------------------
+      !  Deallocate memory of copies
+      !-------------------------------------------------------------------------
+      iopt = ppm_param_dealloc
+      CALL ppm_alloc(dpd2,ldu,iopt,info)
+      IF (info .NE. 0) THEN
+          info = ppm_error_error
+          CALL ppm_error(ppm_err_dealloc,'ppm_comp_pp_ring',     &
+     &        'local copy of dpd DPD2',__LINE__,info)
+      ENDIF
+      CALL ppm_alloc(pdata2,ldu,iopt,info)
+      IF (info .NE. 0) THEN
+          info = ppm_error_error
+          CALL ppm_error(ppm_err_dealloc,'ppm_comp_pp_ring',     &
+     &        'local copy of pdata PDATA2',__LINE__,info)
+      ENDIF
+      CALL ppm_alloc(xp2,ldu,iopt,info)
+      IF (info .NE. 0) THEN
+          info = ppm_error_error
+          CALL ppm_error(ppm_err_dealloc,'ppm_comp_pp_ring',     &
+     &        'local copy of xp XP2',__LINE__,info)
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      !  Return
+      !-------------------------------------------------------------------------
+      CALL substop('ppm_comp_pp_ring',t0,info)
+      RETURN
+#if   __KERNEL == __INTERNAL
+#if   __KIND == __SINGLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_ring_si
+#elif __KIND == __DOUBLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_ring_di
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_ring_sci
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_ring_dci
+#endif
+
+#elif __KERNEL == __USER_FUNCTION
+#if   __KIND == __SINGLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_ring_su
+#elif __KIND == __DOUBLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_ring_du
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_ring_scu
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_ring_dcu
+#endif
+
+#elif __KERNEL == __LOOKUP_TABLE
+#if   __KIND == __SINGLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_ring_st
+#elif __KIND == __DOUBLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_ring_dt
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_ring_sct
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_ring_dct
+#endif
+#endif
diff --git a/src/ppm_comp_pp_verlet.f b/src/ppm_comp_pp_verlet.f
new file mode 100644
index 0000000000000000000000000000000000000000..b611e4498547d772d1a234ecd1683e650a2dcb33
--- /dev/null
+++ b/src/ppm_comp_pp_verlet.f
@@ -0,0 +1,493 @@
+      !-------------------------------------------------------------------------
+      !  Subroutine   :                 ppm_comp_pp_verlet
+      !-------------------------------------------------------------------------
+      !  Parallel Particle Mesh Library (PPM)
+      !  ETH Zurich
+      !  CH-8092 Zurich, Switzerland
+      !-------------------------------------------------------------------------
+
+#if   __KERNEL == __INTERNAL
+#if   __KIND == __SINGLE_PRECISION
+      SUBROUTINE ppm_comp_pp_verlet_si(xp,Np,pdata,lda,lsymm,kernel,kpar,  &
+     &    nvlist,vlist,dpd,info)
+#elif __KIND == __DOUBLE_PRECISION
+      SUBROUTINE ppm_comp_pp_verlet_di(xp,Np,pdata,lda,lsymm,kernel,kpar,  &
+     &    nvlist,vlist,dpd,info)
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_verlet_sci(xp,Np,pdata,lda,lsymm,kernel,kpar, &
+     &    nvlist,vlist,dpd,info)
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_verlet_dci(xp,Np,pdata,lda,lsymm,kernel,kpar, &
+     &    nvlist,vlist,dpd,info)
+#endif
+#elif __KERNEL == __USER_FUNCTION
+#if   __KIND == __SINGLE_PRECISION
+      SUBROUTINE ppm_comp_pp_verlet_su(xp,Np,pdata,lda,lsymm,kernel,kpar,  &
+     &    nvlist,vlist,dpd,info)
+#elif __KIND == __DOUBLE_PRECISION
+      SUBROUTINE ppm_comp_pp_verlet_du(xp,Np,pdata,lda,lsymm,kernel,kpar,  &
+     &    nvlist,vlist,dpd,info)
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_verlet_scu(xp,Np,pdata,lda,lsymm,kernel,kpar, &
+     &    nvlist,vlist,dpd,info)
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_verlet_dcu(xp,Np,pdata,lda,lsymm,kernel,kpar, &
+     &    nvlist,vlist,dpd,info)
+#endif
+#elif __KERNEL == __LOOKUP_TABLE
+#if   __KIND == __SINGLE_PRECISION
+      SUBROUTINE ppm_comp_pp_verlet_st(xp,Np,pdata,lda,lsymm,kernel,kpar,  &
+     &    nvlist,vlist,dpd,info)
+#elif __KIND == __DOUBLE_PRECISION
+      SUBROUTINE ppm_comp_pp_verlet_dt(xp,Np,pdata,lda,lsymm,kernel,kpar,  &
+     &    nvlist,vlist,dpd,info)
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_verlet_sct(xp,Np,pdata,lda,lsymm,kernel,kpar, &
+     &    nvlist,vlist,dpd,info)
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      SUBROUTINE ppm_comp_pp_verlet_dct(xp,Np,pdata,lda,lsymm,kernel,kpar, &
+     &    nvlist,vlist,dpd,info)
+#endif
+#endif
+      !!! Subroutine which computes kernel interactions by direct
+      !!! particle-particle interactions using Verlet lists.
+      !!!
+      !!! [NOTE]
+      !!! ======================================================================
+      !!! The loops for lda.EQ.1 and lda.EQ.2 are explicitly
+      !!! unfolded to allow vectorization in those cases. For
+      !!! lda.GT.2 this routine will not vectorize.
+      !!!
+      !!! Both nvlist and vlist can be created using
+      !!! ppm_neighlist_vlist. This should be done by the
+      !!! user program since there could be several sets of
+      !!! Verlet lists. This routine can then be called with
+      !!! the appropriate one. Do not forget to DEALLOCATE
+      !!! nvlist and vlist when they are not needed any more.
+      !!!
+      !!! dpd needs to be allocated to proper size before
+      !!! calling this routine. Also, this routine is not
+      !!! resetting dpd to zero before doing the PP
+      !!! interactions. This allows contributions from
+      !!! different kernels to be accumulated. If needed,
+      !!! set it to zero before calling this routine the
+      !!! first time.
+      !!! ======================================================================
+      !!!
+      !-------------------------------------------------------------------------
+      !  Modules
+      !-------------------------------------------------------------------------
+      USE ppm_module_data
+      USE ppm_module_substart
+      USE ppm_module_substop
+      USE ppm_module_error
+      IMPLICIT NONE
+#if   __KIND == __SINGLE_PRECISION | __KIND == __SINGLE_PRECISION_COMPLEX
+      INTEGER, PARAMETER :: MK = ppm_kind_single
+#elif __KIND == __DOUBLE_PRECISION | __KIND == __DOUBLE_PRECISION_COMPLEX
+      INTEGER, PARAMETER :: MK = ppm_kind_double
+#endif
+      !-------------------------------------------------------------------------
+      !  Includes
+      !-------------------------------------------------------------------------
+#include "ppm_define.h"
+      !-------------------------------------------------------------------------
+      !  Arguments     
+      !-------------------------------------------------------------------------
+      REAL(MK)   , DIMENSION(:,:), INTENT(IN   ) :: xp
+      !!! particle coordinates
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:,:), INTENT(IN   ) :: pdata
+      !!! particle data (strengths).
+      !!! Overloaded types: single,double
+      REAL(MK)   , DIMENSION(:,:), INTENT(  OUT) :: dpd
+      !!! Change of particle data (strengths).
+      !!! Overloaded types: single,double
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:,:), INTENT(IN   ) :: pdata
+      !!! particle data (strengths).
+      !!! Overloaded types: single complex,double complex
+      COMPLEX(MK), DIMENSION(:,:), INTENT(  OUT) :: dpd
+      !!! Change of particle data (strengths).
+      !!! Overloaded types: single complex,double complex.
+#endif
+      LOGICAL                    , INTENT(IN   ) :: lsymm
+      !!! using symmetry or not?
+      INTEGER                    , INTENT(IN   ) :: Np
+      !!! number of particles on local proc.
+      INTEGER                    , INTENT(IN   ) :: lda
+      !!! leading dimension of pdata.
+#if   __KERNEL == __INTERNAL
+      INTEGER                    , INTENT(IN   ) :: kernel
+      !!! kernel for which to compute the correction. To use ppm-internal
+      !!! kernels, specify one of:
+      !!!
+      !!! ---------------------------------------
+      !!!    ppm_param_kerel_laplace2d_2p
+      !!!      (2nd order Laplacian,
+      !!!      polynomial in 2D)
+      !!!    ppm_param_kerel_laplace3d_2p
+      !!!      (2nd order Laplacian,
+      !!!      polynomial in 3D)
+      !!! ---------------------------------------
+      !!!
+      !!! To use your own kernel function, pass the function pointer here. Your
+      !!! function should take one argument and return one value.
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:)  , INTENT(IN   ) :: kpar
+      !!! Kernel parameters. See documentation or ppm_comp_pp_kernels.inc for
+      !!! description. Type can be single or complex.
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:)  , INTENT(IN   ) :: kpar
+      !!! Kernel parameters. See documentation or ppm_comp_pp_kernels.inc for
+      !!! description. Type can be single complex or double complex.
+#endif
+#elif __KERNEL == __LOOKUP_TABLE
+      REAL(MK)                   , INTENT(IN   ) :: kpar
+      !!! Kernel parameters. See documentation or ppm_comp_pp_kernels.inc for
+      !!! description. Pass dxtableinv (the inverse of the table spacing) as
+      !!! a scalar here.
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:  ), INTENT(IN   ) :: kernel
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:  ), INTENT(IN   ) :: kernel
+#endif
+      !!! Lookup table with tabulated kernel values.
+      !!! Such a table can be created using <<ppm_comp_pp_mk_table>>.
+#endif
+      INTEGER    , DIMENSION(:,:), INTENT(IN   ) :: vlist
+      !!! Verlet lists of all particles. 1st index: particles to interact with
+      !!! (1..nvlist), 2nd: particle (1..Np).
+      INTEGER    , DIMENSION(  :), INTENT(IN   ) :: nvlist
+      !!! length of the Verlet lists of all particles
+      INTEGER                    , INTENT(  OUT) :: info
+      !!! Returns status, 0 upon success
+      !-------------------------------------------------------------------------
+      !  Local variables 
+      !-------------------------------------------------------------------------
+      INTEGER                                    :: jpart,ip,jp,ispec,idx
+      REAL(MK)                                   :: dx,dy,dz
+      REAL(MK)                                   :: factor,factor2
+      REAL(MK)                                   :: dij,dij2,dij4,dij5
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)                                   :: summ,summ2
+      REAL(MK)                                   :: eta,dm
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK)                                :: summ,summ2
+      COMPLEX(MK)                                :: eta,dm
+#endif
+      ! timer 
+      REAL(MK)                                   :: t0
+      CHARACTER(LEN=ppm_char)                    :: mesg
+      !-------------------------------------------------------------------------
+      !  Externals 
+      !-------------------------------------------------------------------------
+#if   __KERNEL == __USER_FUNCTION
+#if   __KIND == __SINGLE_PRECISION | __KIND == __DOUBLE_PRECISION
+      REAL(MK)   , DIMENSION(:)  , INTENT(IN   ) :: kpar
+      INTERFACE
+          FUNCTION kernel(x,kpar)
+              IMPLICIT NONE
+#if   __KIND == __SINGLE_PRECISION | __KIND == __SINGLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0E0)
+#elif __KIND == __DOUBLE_PRECISION | __KIND == __DOUBLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0D0)
+#endif
+              REAL(MK), INTENT(IN) :: x
+              REAL(MK), DIMENSION(:), INTENT(IN) :: kpar
+              REAL(MK) :: kernel
+          END FUNCTION kernel
+      END INTERFACE
+#elif __KIND == __SINGLE_PRECISION_COMPLEX | __KIND == __DOUBLE_PRECISION_COMPLEX
+      COMPLEX(MK), DIMENSION(:)  , INTENT(IN   ) :: kpar
+      INTERFACE
+          FUNCTION kernel(x,kpar)
+              IMPLICIT NONE
+#if   __KIND == __SINGLE_PRECISION | __KIND == __SINGLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0E0)
+#elif __KIND == __DOUBLE_PRECISION | __KIND == __DOUBLE_PRECISION_COMPLEX
+              INTEGER, PARAMETER :: MK = KIND(1.0D0)
+#endif
+              REAL(MK), INTENT(IN) :: x
+              COMPLEX(MK), DIMENSION(:), INTENT(IN) :: kpar
+              COMPLEX(MK) :: kernel
+          END FUNCTION kernel
+      END INTERFACE
+#endif
+#endif
+
+      !-------------------------------------------------------------------------
+      !  Initialise
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_comp_pp_verlet',t0,info)
+
+      !-------------------------------------------------------------------------
+      !  Check arguments.
+      !-------------------------------------------------------------------------
+      IF (ppm_debug .GT. 0) THEN
+          IF (.NOT. ppm_initialized) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_ppm_noinit,'ppm_comp_pp_verlet',  &
+     &            'Please call ppm_init first!',__LINE__,info)
+              GOTO 9999
+          ENDIF
+          IF (Np .LT. 0) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_verlet',  &
+     &            'Np must be >=0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+          IF (lda .LT. 1) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_verlet',  &
+     &            'lda must be >0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+#if   __KERNEL == __LOOKUP_TABLE
+          IF (kpar .LT. 0.0_MK) THEN
+              info = ppm_error_error
+              CALL ppm_error(ppm_err_argument,'ppm_comp_pp_verlet',  &
+     &            'kpar (dxtableinv) must be >=0',__LINE__,info)
+              GOTO 9999
+          ENDIF
+#endif
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      !  PARTICLE-PARTICLE INTERACTIONS using symmetry
+      !-------------------------------------------------------------------------
+      IF (lsymm) THEN
+          IF (lda .EQ. 1) THEN
+              DO ip=1,Np
+                  summ = 0.0_MK
+#ifdef __SXF90
+!CDIR NODEP
+#endif
+                  DO jpart=1,nvlist(ip)
+                      jp = vlist(jpart,ip)
+                      !---------------------------------------------------------
+                      !  Calculate the square of the distance between the two 
+                      !  particles. It will always be .LE. (cutoff+skin)**2 by 
+                      !  construction of the Verlet list.
+                      !---------------------------------------------------------
+                      dx  = xp(1,ip) - xp(1,jp)
+                      dy  = xp(2,ip) - xp(2,jp)
+                      IF (ppm_dim .GT. 2) THEN
+                          dz  = xp(3,ip) - xp(3,jp)
+                          dij = (dx*dx) + (dy*dy) + (dz*dz)
+                      ELSE
+                          dz = 0.0_MK
+                          dij = (dx*dx) + (dy*dy)
+                      ENDIF
+                      !---------------------------------------------------------
+                      !  Particle ip interacts with jp and vice versa
+                      !---------------------------------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                      dm        = eta*(pdata(1,jp) - pdata(1,ip))
+                      summ      = summ      + dm
+                      dpd(1,jp) = dpd(1,jp) - dm
+                  ENDDO
+                  dpd(1,ip) = dpd(1,ip) + summ
+              ENDDO
+          ELSEIF (lda .EQ. 2) THEN
+              DO ip=1,Np
+                  summ = 0.0_MK
+                  summ2 = 0.0_MK
+#ifdef __SXF90
+!CDIR NODEP
+#endif
+                  DO jpart=1,nvlist(ip)
+                      jp = vlist(jpart,ip)
+                      !---------------------------------------------------------
+                      !  Calculate the square of the distance between the two 
+                      !  particles. It will always be .LE. (cutoff+skin)**2 by 
+                      !  construction of the Verlet list.
+                      !---------------------------------------------------------
+                      dx  = xp(1,ip) - xp(1,jp)
+                      dy  = xp(2,ip) - xp(2,jp)
+                      IF (ppm_dim .GT. 2) THEN
+                          dz  = xp(3,ip) - xp(3,jp)
+                          dij = (dx*dx) + (dy*dy) + (dz*dz)
+                      ELSE
+                          dz = 0.0_MK
+                          dij = (dx*dx) + (dy*dy)
+                      ENDIF
+                      !---------------------------------------------------------
+                      !  Particle ip interacts with jp and vice versa
+                      !---------------------------------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                      dm        = eta*(pdata(1,jp) - pdata(1,ip))
+                      summ      = summ      + dm
+                      dpd(1,jp) = dpd(1,jp) - dm
+                      dm        = eta*(pdata(2,jp) - pdata(2,ip))
+                      summ2     = summ2     + dm
+                      dpd(2,jp) = dpd(2,jp) - dm
+                  ENDDO
+                  dpd(1,ip) = dpd(1,ip) + summ
+                  dpd(2,ip) = dpd(2,ip) + summ2
+              ENDDO
+          ELSE
+              DO ip=1,Np
+                  DO jpart=1,nvlist(ip)
+                      jp = vlist(jpart,ip)
+                      !---------------------------------------------------------
+                      !  Calculate the square of the distance between the two 
+                      !  particles. It will always be .LE. (cutoff+skin)**2 by 
+                      !  construction of the Verlet list.
+                      !---------------------------------------------------------
+                      dx  = xp(1,ip) - xp(1,jp)
+                      dy  = xp(2,ip) - xp(2,jp)
+                      IF (ppm_dim .GT. 2) THEN
+                          dz  = xp(3,ip) - xp(3,jp)
+                          dij = (dx*dx) + (dy*dy) + (dz*dz)
+                      ELSE
+                          dz = 0.0_MK
+                          dij = (dx*dx) + (dy*dy)
+                      ENDIF
+                      !---------------------------------------------------------
+                      !  Particle ip interacts with jp and vice versa
+                      !---------------------------------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                      DO ispec=1,lda
+                          dm   = eta*(pdata(ispec,jp) - pdata(ispec,ip))
+                          dpd(ispec,ip) = dpd(ispec,ip) + dm
+                          dpd(ispec,jp) = dpd(ispec,jp) - dm
+                      ENDDO
+                  ENDDO
+              ENDDO
+          ENDIF
+
+      !-------------------------------------------------------------------------
+      !  PARTICLE-PARTICLE INTERACTIONS not using symmetry
+      !-------------------------------------------------------------------------
+      ELSE
+          IF (lda .EQ. 1) THEN
+              DO ip=1,Np
+#ifdef __SXF90
+!CDIR NODEP
+#endif
+                  DO jpart=1,nvlist(ip)
+                      jp = vlist(jpart,ip)
+                      !---------------------------------------------------------
+                      !  Calculate the square of the distance between the two 
+                      !  particles. It will always be .LE. (cutoff+skin)**2 by 
+                      !  construction of the Verlet list.
+                      !---------------------------------------------------------
+                      dx  = xp(1,ip) - xp(1,jp)
+                      dy  = xp(2,ip) - xp(2,jp)
+                      IF (ppm_dim .GT. 2) THEN
+                          dz  = xp(3,ip) - xp(3,jp)
+                          dij = (dx*dx) + (dy*dy) + (dz*dz)
+                      ELSE
+                          dz = 0.0_MK
+                          dij = (dx*dx) + (dy*dy)
+                      ENDIF
+                      !---------------------------------------------------------
+                      !  Particle ip interacts with jp
+                      !---------------------------------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                      dm = eta*(pdata(1,jp) - pdata(1,ip))
+                      dpd(1,ip) = dpd(1,ip) + dm
+                  ENDDO
+              ENDDO
+          ELSEIF (lda .EQ. 2) THEN
+              DO ip=1,Np
+#ifdef __SXF90
+!CDIR NODEP
+#endif
+                  DO jpart=1,nvlist(ip)
+                      jp = vlist(jpart,ip)
+                      !---------------------------------------------------------
+                      !  Calculate the square of the distance between the two 
+                      !  particles. It will always be .LE. (cutoff+skin)**2 by 
+                      !  construction of the Verlet list.
+                      !---------------------------------------------------------
+                      dx  = xp(1,ip) - xp(1,jp)
+                      dy  = xp(2,ip) - xp(2,jp)
+                      IF (ppm_dim .GT. 2) THEN
+                          dz  = xp(3,ip) - xp(3,jp)
+                          dij = (dx*dx) + (dy*dy) + (dz*dz)
+                      ELSE
+                          dz = 0.0_MK
+                          dij = (dx*dx) + (dy*dy)
+                      ENDIF
+                      !---------------------------------------------------------
+                      !  Particle ip interacts with jp
+                      !---------------------------------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                      dm = eta*(pdata(1,jp) - pdata(1,ip))
+                      dpd(1,ip) = dpd(1,ip) + dm
+                      dm = eta*(pdata(2,jp) - pdata(2,ip))
+                      dpd(2,ip) = dpd(2,ip) + dm
+                  ENDDO
+              ENDDO
+          ELSE
+              DO ip=1,Np
+                  DO jpart=1,nvlist(ip)
+                      jp = vlist(jpart,ip)
+                      !---------------------------------------------------------
+                      !  Calculate the square of the distance between the two 
+                      !  particles. It will always be .LE. (cutoff+skin)**2 by 
+                      !  construction of the Verlet list.
+                      !---------------------------------------------------------
+                      dx  = xp(1,ip) - xp(1,jp)
+                      dy  = xp(2,ip) - xp(2,jp)
+                      IF (ppm_dim .GT. 2) THEN
+                          dz  = xp(3,ip) - xp(3,jp)
+                          dij = (dx*dx) + (dy*dy) + (dz*dz)
+                      ELSE
+                          dz = 0.0_MK
+                          dij = (dx*dx) + (dy*dy)
+                      ENDIF
+                      !---------------------------------------------------------
+                      !  Particle ip interacts with jp
+                      !---------------------------------------------------------
+#include "ppm_comp_pp_kernels.inc"
+                      DO ispec=1,lda
+                          dm = eta*(pdata(ispec,jp) - pdata(ispec,ip))
+                          dpd(ispec,ip) = dpd(ispec,ip) + dm
+                      ENDDO
+                  ENDDO
+              ENDDO
+          ENDIF
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      !  Return
+      !-------------------------------------------------------------------------
+ 9999 CONTINUE
+      CALL substop('ppm_comp_pp_verlet',t0,info)
+      RETURN
+#if   __KERNEL == __INTERNAL
+#if   __KIND == __SINGLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_verlet_si
+#elif __KIND == __DOUBLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_verlet_di
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_verlet_sci
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_verlet_dci
+#endif
+
+#elif __KERNEL == __USER_FUNCTION
+#if   __KIND == __SINGLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_verlet_su
+#elif __KIND == __DOUBLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_verlet_du
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_verlet_scu
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_verlet_dcu
+#endif
+
+#elif __KERNEL == __LOOKUP_TABLE
+#if   __KIND == __SINGLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_verlet_st
+#elif __KIND == __DOUBLE_PRECISION
+      END SUBROUTINE ppm_comp_pp_verlet_dt
+#elif __KIND == __SINGLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_verlet_sct
+#elif __KIND == __DOUBLE_PRECISION_COMPLEX
+      END SUBROUTINE ppm_comp_pp_verlet_dct
+#endif
+#endif
diff --git a/src/ppm_module_comp_part.f b/src/ppm_module_comp_part.f
new file mode 100644
index 0000000000000000000000000000000000000000..cc39a2698d4294f027bc78490e74e57e2ac146c7
--- /dev/null
+++ b/src/ppm_module_comp_part.f
@@ -0,0 +1,21 @@
+      !-------------------------------------------------------------------------
+      !  Module       :                ppm_module_comp_part
+      !-------------------------------------------------------------------------
+      !  Parallel Particle Mesh Library (PPM)
+      !  ETH Zurich
+      !  CH-8092 Zurich, Switzerland
+      !-------------------------------------------------------------------------
+
+      MODULE ppm_module_comp_part
+      !!! This module contains all user-callable routines to
+      !!! compute kernel-PP interactions on a set of particles.
+         !----------------------------------------------------------------------
+         !  PPM modules
+         !----------------------------------------------------------------------
+         USE ppm_module_comp_pp_verlet
+         USE ppm_module_comp_pp_cell
+         USE ppm_module_comp_pp_ring
+         USE ppm_module_comp_pp_correct
+         USE ppm_module_comp_pp_mk_table
+         
+      END MODULE ppm_module_comp_part
diff --git a/src/ppm_module_comp_pp_cell.f b/src/ppm_module_comp_pp_cell.f
new file mode 100644
index 0000000000000000000000000000000000000000..32a540fa25f6000a27994b7a7f88a5833cd12c7b
--- /dev/null
+++ b/src/ppm_module_comp_pp_cell.f
@@ -0,0 +1,101 @@
+      !-------------------------------------------------------------------------
+      !  Module       :              ppm_module_comp_pp_cell
+      !-------------------------------------------------------------------------
+      !  Parallel Particle Mesh Library (PPM)
+      !  ETH Zurich
+      !  CH-8092 Zurich, Switzerland
+      !-------------------------------------------------------------------------
+     
+      !-------------------------------------------------------------------------
+      !  Define types
+      !-------------------------------------------------------------------------
+#define __SINGLE_PRECISION         1
+#define __DOUBLE_PRECISION         2
+#define __SINGLE_PRECISION_COMPLEX 3
+#define __DOUBLE_PRECISION_COMPLEX 4
+
+#define __INTERNAL                 5
+#define __USER_FUNCTION            6
+#define __LOOKUP_TABLE             7
+
+      MODULE ppm_module_comp_pp_cell
+      !!! This module provides the routines concerned
+      !!! with computing kernel interactions within a set of particles.
+         !----------------------------------------------------------------------
+         !  Define interfaces to the cell list versions
+         !----------------------------------------------------------------------
+         INTERFACE ppm_comp_pp_cell
+            MODULE PROCEDURE ppm_comp_pp_cell_si
+            MODULE PROCEDURE ppm_comp_pp_cell_di
+            MODULE PROCEDURE ppm_comp_pp_cell_sci
+            MODULE PROCEDURE ppm_comp_pp_cell_dci
+            MODULE PROCEDURE ppm_comp_pp_cell_su
+            MODULE PROCEDURE ppm_comp_pp_cell_du
+            MODULE PROCEDURE ppm_comp_pp_cell_scu
+            MODULE PROCEDURE ppm_comp_pp_cell_dcu
+            MODULE PROCEDURE ppm_comp_pp_cell_st
+            MODULE PROCEDURE ppm_comp_pp_cell_dt
+            MODULE PROCEDURE ppm_comp_pp_cell_sct
+            MODULE PROCEDURE ppm_comp_pp_cell_dct
+         END INTERFACE
+
+         !----------------------------------------------------------------------
+         !  include the source 
+         !----------------------------------------------------------------------
+         CONTAINS
+
+#define __KERNEL __INTERNAL
+#define __KIND __SINGLE_PRECISION
+#include "ppm_comp_pp_cell.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION
+#include "ppm_comp_pp_cell.f"
+#undef __KIND
+
+#define __KIND __SINGLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_cell.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_cell.f"
+#undef __KIND
+#undef __KERNEL
+
+#define __KERNEL __USER_FUNCTION
+#define __KIND __SINGLE_PRECISION
+#include "ppm_comp_pp_cell.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION
+#include "ppm_comp_pp_cell.f"
+#undef __KIND
+
+#define __KIND __SINGLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_cell.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_cell.f"
+#undef __KIND
+#undef __KERNEL
+
+#define __KERNEL __LOOKUP_TABLE
+#define __KIND __SINGLE_PRECISION
+#include "ppm_comp_pp_cell.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION
+#include "ppm_comp_pp_cell.f"
+#undef __KIND
+
+#define __KIND __SINGLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_cell.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_cell.f"
+#undef __KIND
+#undef __KERNEL
+
+      END MODULE ppm_module_comp_pp_cell
diff --git a/src/ppm_module_comp_pp_correct.f b/src/ppm_module_comp_pp_correct.f
new file mode 100644
index 0000000000000000000000000000000000000000..04b2772293259a834fa3bad4e4eadeb9c29a0d51
--- /dev/null
+++ b/src/ppm_module_comp_pp_correct.f
@@ -0,0 +1,101 @@
+      !-------------------------------------------------------------------------
+      !  Module       :             ppm_module_comp_pp_correct
+      !-------------------------------------------------------------------------
+      !  Parallel Particle Mesh Library (PPM)
+      !  ETH Zurich
+      !  CH-8092 Zurich, Switzerland
+      !-------------------------------------------------------------------------
+     
+      !-------------------------------------------------------------------------
+      !  Define types
+      !-------------------------------------------------------------------------
+#define __SINGLE_PRECISION         1
+#define __DOUBLE_PRECISION         2
+#define __SINGLE_PRECISION_COMPLEX 3
+#define __DOUBLE_PRECISION_COMPLEX 4
+
+#define __INTERNAL                 5
+#define __USER_FUNCTION            6
+#define __LOOKUP_TABLE             7
+
+      MODULE ppm_module_comp_pp_correct
+      !!! This module provides the routines concerned
+      !!! with computing kernel interactions within a set of particles.
+         !----------------------------------------------------------------------
+         !  Define interfaces to the discretisation correction routine
+         !----------------------------------------------------------------------
+         INTERFACE ppm_comp_pp_correct
+            MODULE PROCEDURE ppm_comp_pp_correct_si
+            MODULE PROCEDURE ppm_comp_pp_correct_di
+            MODULE PROCEDURE ppm_comp_pp_correct_sci
+            MODULE PROCEDURE ppm_comp_pp_correct_dci
+            MODULE PROCEDURE ppm_comp_pp_correct_su
+            MODULE PROCEDURE ppm_comp_pp_correct_du
+            MODULE PROCEDURE ppm_comp_pp_correct_scu
+            MODULE PROCEDURE ppm_comp_pp_correct_dcu
+            MODULE PROCEDURE ppm_comp_pp_correct_st
+            MODULE PROCEDURE ppm_comp_pp_correct_dt
+            MODULE PROCEDURE ppm_comp_pp_correct_sct
+            MODULE PROCEDURE ppm_comp_pp_correct_dct
+         END INTERFACE
+
+         !----------------------------------------------------------------------
+         !  include the source 
+         !----------------------------------------------------------------------
+         CONTAINS
+
+#define __KERNEL __INTERNAL
+#define __KIND __SINGLE_PRECISION
+#include "ppm_comp_pp_correct.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION
+#include "ppm_comp_pp_correct.f"
+#undef __KIND
+
+#define __KIND __SINGLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_correct.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_correct.f"
+#undef __KIND
+#undef __KERNEL
+
+#define __KERNEL __USER_FUNCTION
+#define __KIND __SINGLE_PRECISION
+#include "ppm_comp_pp_correct.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION
+#include "ppm_comp_pp_correct.f"
+#undef __KIND
+
+#define __KIND __SINGLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_correct.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_correct.f"
+#undef __KIND
+#undef __KERNEL
+
+#define __KERNEL __LOOKUP_TABLE
+#define __KIND __SINGLE_PRECISION
+#include "ppm_comp_pp_correct.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION
+#include "ppm_comp_pp_correct.f"
+#undef __KIND
+
+#define __KIND __SINGLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_correct.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_correct.f"
+#undef __KIND
+#undef __KERNEL
+
+      END MODULE ppm_module_comp_pp_correct
diff --git a/src/ppm_module_comp_pp_doring.f b/src/ppm_module_comp_pp_doring.f
new file mode 100644
index 0000000000000000000000000000000000000000..946f59166dfe1427567ebb3e1691a4c56b3af6e5
--- /dev/null
+++ b/src/ppm_module_comp_pp_doring.f
@@ -0,0 +1,101 @@
+      !-------------------------------------------------------------------------
+      !  Module       :             ppm_module_comp_pp_doring
+      !-------------------------------------------------------------------------
+      !  Parallel Particle Mesh Library (PPM)
+      !  ETH Zurich
+      !  CH-8092 Zurich, Switzerland
+      !-------------------------------------------------------------------------
+     
+      !-------------------------------------------------------------------------
+      !  Define types
+      !-------------------------------------------------------------------------
+#define __SINGLE_PRECISION         1
+#define __DOUBLE_PRECISION         2
+#define __SINGLE_PRECISION_COMPLEX 3
+#define __DOUBLE_PRECISION_COMPLEX 4
+
+#define __INTERNAL                 5
+#define __USER_FUNCTION            6
+#define __LOOKUP_TABLE             7
+
+      MODULE ppm_module_comp_pp_doring
+      !!! This module provides the routines concerned
+      !!! with computing kernel interactions within a set of particles.
+         !----------------------------------------------------------------------
+         !  Define interfaces to the ring interaction subroutine
+         !----------------------------------------------------------------------
+         INTERFACE ppm_comp_pp_doring
+            MODULE PROCEDURE ppm_comp_pp_doring_si
+            MODULE PROCEDURE ppm_comp_pp_doring_di
+            MODULE PROCEDURE ppm_comp_pp_doring_sci
+            MODULE PROCEDURE ppm_comp_pp_doring_dci
+            MODULE PROCEDURE ppm_comp_pp_doring_su
+            MODULE PROCEDURE ppm_comp_pp_doring_du
+            MODULE PROCEDURE ppm_comp_pp_doring_scu
+            MODULE PROCEDURE ppm_comp_pp_doring_dcu
+            MODULE PROCEDURE ppm_comp_pp_doring_st
+            MODULE PROCEDURE ppm_comp_pp_doring_dt
+            MODULE PROCEDURE ppm_comp_pp_doring_sct
+            MODULE PROCEDURE ppm_comp_pp_doring_dct
+         END INTERFACE
+
+         !----------------------------------------------------------------------
+         !  include the source 
+         !----------------------------------------------------------------------
+         CONTAINS
+
+#define __KERNEL __INTERNAL
+#define __KIND __SINGLE_PRECISION
+#include "ppm_comp_pp_doring.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION
+#include "ppm_comp_pp_doring.f"
+#undef __KIND
+
+#define __KIND __SINGLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_doring.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_doring.f"
+#undef __KIND
+#undef __KERNEL
+
+#define __KERNEL __USER_FUNCTION
+#define __KIND __SINGLE_PRECISION
+#include "ppm_comp_pp_doring.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION
+#include "ppm_comp_pp_doring.f"
+#undef __KIND
+
+#define __KIND __SINGLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_doring.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_doring.f"
+#undef __KIND
+#undef __KERNEL
+
+#define __KERNEL __LOOKUP_TABLE
+#define __KIND __SINGLE_PRECISION
+#include "ppm_comp_pp_doring.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION
+#include "ppm_comp_pp_doring.f"
+#undef __KIND
+
+#define __KIND __SINGLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_doring.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_doring.f"
+#undef __KIND
+#undef __KERNEL
+
+      END MODULE ppm_module_comp_pp_doring
diff --git a/src/ppm_module_comp_pp_mk_table.f b/src/ppm_module_comp_pp_mk_table.f
new file mode 100644
index 0000000000000000000000000000000000000000..b777d4b0fad861741bd2dfcbbd8ce5d5a638d1f1
--- /dev/null
+++ b/src/ppm_module_comp_pp_mk_table.f
@@ -0,0 +1,79 @@
+      !-------------------------------------------------------------------------
+      !  Module       :             ppm_module_comp_pp_mk_table
+      !-------------------------------------------------------------------------
+      !  Parallel Particle Mesh Library (PPM)
+      !  ETH Zurich
+      !  CH-8092 Zurich, Switzerland
+      !-------------------------------------------------------------------------
+     
+      !-------------------------------------------------------------------------
+      !  Define types
+      !-------------------------------------------------------------------------
+#define __SINGLE_PRECISION         1
+#define __DOUBLE_PRECISION         2
+#define __SINGLE_PRECISION_COMPLEX 3
+#define __DOUBLE_PRECISION_COMPLEX 4
+
+#define __INTERNAL                 5
+#define __USER_FUNCTION            6
+
+      MODULE ppm_module_comp_pp_mk_table
+      !!! [[ppm_comp_pp_mk_table]]
+      !!! This module provides the routines concerned
+      !!! with computing kernel interactions within a set of particles.
+         !----------------------------------------------------------------------
+         !  Define interfaces to the lookup table creation routine
+         !----------------------------------------------------------------------
+         INTERFACE ppm_comp_pp_mk_table
+            MODULE PROCEDURE ppm_comp_pp_mk_table_si
+            MODULE PROCEDURE ppm_comp_pp_mk_table_di
+            MODULE PROCEDURE ppm_comp_pp_mk_table_sci
+            MODULE PROCEDURE ppm_comp_pp_mk_table_dci
+            MODULE PROCEDURE ppm_comp_pp_mk_table_su
+            MODULE PROCEDURE ppm_comp_pp_mk_table_du
+            MODULE PROCEDURE ppm_comp_pp_mk_table_scu
+            MODULE PROCEDURE ppm_comp_pp_mk_table_dcu
+         END INTERFACE
+
+         !----------------------------------------------------------------------
+         !  include the source 
+         !----------------------------------------------------------------------
+         CONTAINS
+
+#define __KERNEL __INTERNAL
+#define __KIND __SINGLE_PRECISION
+#include "ppm_comp_pp_mk_table.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION
+#include "ppm_comp_pp_mk_table.f"
+#undef __KIND
+
+#define __KIND __SINGLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_mk_table.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_mk_table.f"
+#undef __KIND
+#undef __KERNEL
+
+#define __KERNEL __USER_FUNCTION
+#define __KIND __SINGLE_PRECISION
+#include "ppm_comp_pp_mk_table.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION
+#include "ppm_comp_pp_mk_table.f"
+#undef __KIND
+
+#define __KIND __SINGLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_mk_table.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_mk_table.f"
+#undef __KIND
+#undef __KERNEL
+
+      END MODULE ppm_module_comp_pp_mk_table
diff --git a/src/ppm_module_comp_pp_ring.f b/src/ppm_module_comp_pp_ring.f
new file mode 100644
index 0000000000000000000000000000000000000000..61e0e27b2be9871393a7223d5f459305385f8580
--- /dev/null
+++ b/src/ppm_module_comp_pp_ring.f
@@ -0,0 +1,101 @@
+      !-------------------------------------------------------------------------
+      !  Module       :              ppm_module_comp_pp_ring
+      !-------------------------------------------------------------------------
+      !  Parallel Particle Mesh Library (PPM)
+      !  ETH Zurich
+      !  CH-8092 Zurich, Switzerland
+      !-------------------------------------------------------------------------
+     
+      !-------------------------------------------------------------------------
+      !  Define types
+      !-------------------------------------------------------------------------
+#define __SINGLE_PRECISION         1
+#define __DOUBLE_PRECISION         2
+#define __SINGLE_PRECISION_COMPLEX 3
+#define __DOUBLE_PRECISION_COMPLEX 4
+
+#define __INTERNAL                 5
+#define __USER_FUNCTION            6
+#define __LOOKUP_TABLE             7
+
+      MODULE ppm_module_comp_pp_ring
+      !!! This module provides the routines concerned
+      !!! with computing kernel interactions within a set of particles.
+         !----------------------------------------------------------------------
+         !  Define interfaces to the ring versions
+         !----------------------------------------------------------------------
+         INTERFACE ppm_comp_pp_ring
+            MODULE PROCEDURE ppm_comp_pp_ring_si
+            MODULE PROCEDURE ppm_comp_pp_ring_di
+            MODULE PROCEDURE ppm_comp_pp_ring_sci
+            MODULE PROCEDURE ppm_comp_pp_ring_dci
+            MODULE PROCEDURE ppm_comp_pp_ring_su
+            MODULE PROCEDURE ppm_comp_pp_ring_du
+            MODULE PROCEDURE ppm_comp_pp_ring_scu
+            MODULE PROCEDURE ppm_comp_pp_ring_dcu
+            MODULE PROCEDURE ppm_comp_pp_ring_st
+            MODULE PROCEDURE ppm_comp_pp_ring_dt
+            MODULE PROCEDURE ppm_comp_pp_ring_sct
+            MODULE PROCEDURE ppm_comp_pp_ring_dct
+         END INTERFACE
+
+         !----------------------------------------------------------------------
+         !  include the source 
+         !----------------------------------------------------------------------
+         CONTAINS
+
+#define __KERNEL __INTERNAL
+#define __KIND __SINGLE_PRECISION
+#include "ppm_comp_pp_ring.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION
+#include "ppm_comp_pp_ring.f"
+#undef __KIND
+
+#define __KIND __SINGLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_ring.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_ring.f"
+#undef __KIND
+#undef __KERNEL
+
+#define __KERNEL __USER_FUNCTION
+#define __KIND __SINGLE_PRECISION
+#include "ppm_comp_pp_ring.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION
+#include "ppm_comp_pp_ring.f"
+#undef __KIND
+
+#define __KIND __SINGLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_ring.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_ring.f"
+#undef __KIND
+#undef __KERNEL
+
+#define __KERNEL __LOOKUP_TABLE
+#define __KIND __SINGLE_PRECISION
+#include "ppm_comp_pp_ring.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION
+#include "ppm_comp_pp_ring.f"
+#undef __KIND
+
+#define __KIND __SINGLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_ring.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_ring.f"
+#undef __KIND
+#undef __KERNEL
+
+      END MODULE ppm_module_comp_pp_ring
diff --git a/src/ppm_module_comp_pp_verlet.f b/src/ppm_module_comp_pp_verlet.f
new file mode 100644
index 0000000000000000000000000000000000000000..88a57e06f2483216ce29baeb5ebbad7dc4298111
--- /dev/null
+++ b/src/ppm_module_comp_pp_verlet.f
@@ -0,0 +1,101 @@
+      !-------------------------------------------------------------------------
+      !  Module       :              ppm_module_comp_pp_verlet
+      !-------------------------------------------------------------------------
+      !  Parallel Particle Mesh Library (PPM)
+      !  ETH Zurich
+      !  CH-8092 Zurich, Switzerland
+      !-------------------------------------------------------------------------
+     
+      !-------------------------------------------------------------------------
+      !  Define types
+      !-------------------------------------------------------------------------
+#define __SINGLE_PRECISION         1
+#define __DOUBLE_PRECISION         2
+#define __SINGLE_PRECISION_COMPLEX 3
+#define __DOUBLE_PRECISION_COMPLEX 4
+
+#define __INTERNAL                 5
+#define __USER_FUNCTION            6
+#define __LOOKUP_TABLE             7
+
+      MODULE ppm_module_comp_pp_verlet
+      !!! This module provides the routines concerned
+      !!! with computing kernel interactions within a set of particles.
+         !----------------------------------------------------------------------
+         !  Define interfaces to the Verlet list versions
+         !----------------------------------------------------------------------
+         INTERFACE ppm_comp_pp_verlet
+            MODULE PROCEDURE ppm_comp_pp_verlet_si
+            MODULE PROCEDURE ppm_comp_pp_verlet_di
+            MODULE PROCEDURE ppm_comp_pp_verlet_sci
+            MODULE PROCEDURE ppm_comp_pp_verlet_dci
+            MODULE PROCEDURE ppm_comp_pp_verlet_su
+            MODULE PROCEDURE ppm_comp_pp_verlet_du
+            MODULE PROCEDURE ppm_comp_pp_verlet_scu
+            MODULE PROCEDURE ppm_comp_pp_verlet_dcu
+            MODULE PROCEDURE ppm_comp_pp_verlet_st
+            MODULE PROCEDURE ppm_comp_pp_verlet_dt
+            MODULE PROCEDURE ppm_comp_pp_verlet_sct
+            MODULE PROCEDURE ppm_comp_pp_verlet_dct
+         END INTERFACE
+
+         !----------------------------------------------------------------------
+         !  include the source 
+         !----------------------------------------------------------------------
+         CONTAINS
+
+#define __KERNEL __INTERNAL
+#define __KIND __SINGLE_PRECISION
+#include "ppm_comp_pp_verlet.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION
+#include "ppm_comp_pp_verlet.f"
+#undef __KIND
+
+#define __KIND __SINGLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_verlet.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_verlet.f"
+#undef __KIND
+#undef __KERNEL
+
+#define __KERNEL __USER_FUNCTION
+#define __KIND __SINGLE_PRECISION
+#include "ppm_comp_pp_verlet.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION
+#include "ppm_comp_pp_verlet.f"
+#undef __KIND
+
+#define __KIND __SINGLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_verlet.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_verlet.f"
+#undef __KIND
+#undef __KERNEL
+
+#define __KERNEL __LOOKUP_TABLE
+#define __KIND __SINGLE_PRECISION
+#include "ppm_comp_pp_verlet.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION
+#include "ppm_comp_pp_verlet.f"
+#undef __KIND
+
+#define __KIND __SINGLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_verlet.f"
+#undef __KIND
+
+#define __KIND __DOUBLE_PRECISION_COMPLEX
+#include "ppm_comp_pp_verlet.f"
+#undef __KIND
+#undef __KERNEL
+
+      END MODULE ppm_module_comp_pp_verlet