From 84c9c96c49be4d78ad34dda5feed83467ae983e6 Mon Sep 17 00:00:00 2001
From: jtra <jtra@7c7fe9aa-52eb-4d9e-b0a8-ba7d787348e9>
Date: Wed, 1 Jun 2011 07:49:45 +0000
Subject: [PATCH] working

git-svn-id: https://ppm.inf.ethz.ch/svn/ppmnumerics/branches/ngtopo/libppmnumerics@884 7c7fe9aa-52eb-4d9e-b0a8-ba7d787348e9
---
 src/fft/ppm_fft_exec_3d_vec_bc2r_xy.f      | 119 +++
 src/fft/ppm_fft_exec_3d_vec_c2c_z.f        | 124 +++
 src/fft/ppm_fft_exec_3d_vec_fr2c_xy.f      | 103 +++
 src/fft/ppm_fft_normalize_c.f              | 127 ++++
 src/fft/ppm_fft_normalize_r.f              | 128 ++++
 src/fft/ppm_fft_plan_3d_vec_bc2c_z.f       | 149 ++++
 src/fft/ppm_fft_plan_3d_vec_bc2r_xy.f      | 154 ++++
 src/fft/ppm_fft_plan_3d_vec_fc2c_z.f       | 149 ++++
 src/fft/ppm_fft_plan_3d_vec_fr2c_xy.f      | 153 ++++
 src/poisson/ppm_poisson_extrapolateghost.f | 257 +++++++
 src/poisson/ppm_poisson_fd.f               | 147 ++++
 src/poisson/ppm_poisson_init_predef.f      | 637 ++++++++++++++++
 src/poisson/ppm_poisson_solve.f            | 837 +++++++++++++++++++++
 13 files changed, 3084 insertions(+)
 create mode 100644 src/fft/ppm_fft_exec_3d_vec_bc2r_xy.f
 create mode 100644 src/fft/ppm_fft_exec_3d_vec_c2c_z.f
 create mode 100644 src/fft/ppm_fft_exec_3d_vec_fr2c_xy.f
 create mode 100644 src/fft/ppm_fft_normalize_c.f
 create mode 100644 src/fft/ppm_fft_normalize_r.f
 create mode 100644 src/fft/ppm_fft_plan_3d_vec_bc2c_z.f
 create mode 100644 src/fft/ppm_fft_plan_3d_vec_bc2r_xy.f
 create mode 100644 src/fft/ppm_fft_plan_3d_vec_fc2c_z.f
 create mode 100644 src/fft/ppm_fft_plan_3d_vec_fr2c_xy.f
 create mode 100644 src/poisson/ppm_poisson_extrapolateghost.f
 create mode 100644 src/poisson/ppm_poisson_fd.f
 create mode 100644 src/poisson/ppm_poisson_init_predef.f
 create mode 100644 src/poisson/ppm_poisson_solve.f

diff --git a/src/fft/ppm_fft_exec_3d_vec_bc2r_xy.f b/src/fft/ppm_fft_exec_3d_vec_bc2r_xy.f
new file mode 100644
index 0000000..de26a49
--- /dev/null
+++ b/src/fft/ppm_fft_exec_3d_vec_bc2r_xy.f
@@ -0,0 +1,119 @@
+      !-------------------------------------------------------------------------
+      !  Subroutine   : ppm_fft_exec_3d_vec_bc2r_xy
+      !-------------------------------------------------------------------------
+      ! Copyright (c) 2010 CSE Lab (ETH Zurich), MOSAIC Group (ETH Zurich),
+      !                    Center for Fluid Dynamics (DTU)
+      !
+      ! FFTW execute wrapper for 3d arrays, 2d complex to real
+      ! (backward) FFT in the xy directions
+      ! The routine does not work with fields that include ghost layers
+      !-------------------------------------------------------------------------
+#if __KIND == __SINGLE
+#define __ROUTINE ppm_fft_exec_3d_vec_bc2r_xy_s
+#define __PREC ppm_kind_single
+#elif __KIND == __DOUBLE
+#define __ROUTINE ppm_fft_exec_3d_vec_bc2r_xy_d
+#define __PREC ppm_kind_double
+#endif
+      SUBROUTINE __ROUTINE(topoid,meshid,ppmplan,infield,outfield,info)
+      !!! FFTW execute wrapper for 3d arrays, 2d complex to real
+      !!! (backward) FFT in the xy directions
+      !!! Before calling this routine a ppm_fft_plan_ routine must be called
+      !!! The routine does not work with fields that include ghost layers
+      USE ppm_module_substart
+      USE ppm_module_substop
+      USE ppm_module_typedef
+      USE ppm_module_topo_get
+      USE ppm_module_write
+      USE ppm_module_data,ONLY:ppm_rank,ppm_kind_single,ppm_kind_double
+
+      IMPLICIT NONE
+
+      INCLUDE 'fftw3.f'
+
+      ! if debug check if dimensions are 2a 3b 5c 7d 11e 13f
+      !-------------------------------------------------------------------------
+      ! Arguments
+      !-------------------------------------------------------------------------
+      !!!topology identifier of target
+      INTEGER,INTENT(IN)                                             :: topoid
+      !!!id of the mesh
+      INTEGER,INTENT(IN)                                             :: meshid
+      !!!ppm fft plan type
+      TYPE(ppm_fft_plan),INTENT(INOUT)                               :: ppmplan
+      !!!input field to fourier transform
+      !COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER,INTENT(INOUT)     :: infield
+      COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: infield
+      !!!output field for the result of the fourier transform
+      !REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER,INTENT(INOUT)        :: outfield
+      REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER                      :: outfield
+      !!!Returns status, 0 upon success
+      INTEGER,INTENT(OUT)                                            :: info
+      !in time perhaps an argument for alternate directions
+
+      !-------------------------------------------------------------------------
+      ! Local variables
+      !-------------------------------------------------------------------------
+      REAL(__PREC)                  :: t0
+      INTEGER                       :: i,k
+      INTEGER                       :: isub,isubl
+      INTEGER                       :: nsubs
+      INTEGER,DIMENSION(:),POINTER  :: isublist
+      TYPE(ppm_t_topo),POINTER      :: topology
+      TYPE(ppm_t_equi_mesh)         :: mesh
+
+      !-------------------------------------------------------------------------
+      ! Initialise routine
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_fft_exec',t0,info)
+
+      !-------------------------------------------------------------------------
+      ! Get topology and mesh values
+      !-------------------------------------------------------------------------
+      CALL ppm_topo_get(topoid,topology,info)
+      IF (info .NE. 0) THEN
+         CALL ppm_write(ppm_rank,'ppm_fft_exec','Failed to get topology.',isub)
+         GOTO 9999
+      ENDIF
+      nsubs = topology%nsublist
+      ALLOCATE(isublist(nsubs))
+      DO isub=1,nsubs
+        isublist(isub) = topology%isublist(isub)
+      ENDDO
+      mesh  = topology%mesh(meshid)
+
+      !-------------------------------------------------------------------------
+      ! Execute plan
+      !-------------------------------------------------------------------------
+      DO isub=1,nsubs
+         isubl=isublist(isub)
+         DO k=1,mesh%nnodes(3,isubl) !@ add '-1' to exclude n+1 slabs
+            CALL dfftw_execute_dft_c2r(ppmplan%plan(isub),&
+            & infield(1,1,1,k,isub),outfield(1,1,1,k,isub))
+            IF (topology%bcdef(1) .EQ. ppm_param_bcdef_periodic) THEN !vertex
+               !-------------------------------------------------------------------
+               ! Copy periodic layer back - only for periodic 'N' vertex points
+               !-------------------------------------------------------------------
+               DO i=1,mesh%nnodes(1,isubl)
+                  outfield(1,i,mesh%nnodes(2,isubl),k,isub) = outfield(1,i,1,k,isub)
+                  outfield(2,i,mesh%nnodes(2,isubl),k,isub) = outfield(2,i,1,k,isub)
+                  outfield(3,i,mesh%nnodes(2,isubl),k,isub) = outfield(3,i,1,k,isub)
+               END DO
+               DO i=1,mesh%nnodes(2,isubl)
+                  outfield(1,mesh%nnodes(1,isubl),i,k,isub) = outfield(1,1,i,k,isub)
+                  outfield(2,mesh%nnodes(1,isubl),i,k,isub) = outfield(2,1,i,k,isub)
+                  outfield(3,mesh%nnodes(1,isubl),i,k,isub) = outfield(3,1,i,k,isub)
+               END DO
+            END IF
+         END DO
+      END DO
+
+
+      !-------------------------------------------------------------------------
+      ! Return
+      !-------------------------------------------------------------------------
+ 9999 CONTINUE
+      CALL substop('ppm_fft_exec',t0,info)
+      RETURN
+
+      END SUBROUTINE __ROUTINE
diff --git a/src/fft/ppm_fft_exec_3d_vec_c2c_z.f b/src/fft/ppm_fft_exec_3d_vec_c2c_z.f
new file mode 100644
index 0000000..ca01f76
--- /dev/null
+++ b/src/fft/ppm_fft_exec_3d_vec_c2c_z.f
@@ -0,0 +1,124 @@
+      !-------------------------------------------------------------------------
+      !  Subroutine   : ppm_fft_exec_3d_vec_c2c_z
+      !-------------------------------------------------------------------------
+      ! Copyright (c) 2010 CSE Lab (ETH Zurich), MOSAIC Group (ETH Zurich),
+      !                    Center for Fluid Dynamics (DTU)
+      !
+      ! FFTW execute wrapper for 3d arrays, 1d complex to complex 
+      ! (forward and backward) FFT in the z direction
+      ! The routine does not work with fields that include ghost layers
+      !-------------------------------------------------------------------------
+#if __KIND == __SINGLE
+#define __ROUTINE ppm_fft_exec_3d_vec_c2c_z_s
+#define __PREC ppm_kind_single
+#elif __KIND == __DOUBLE
+#define __ROUTINE ppm_fft_exec_3d_vec_c2c_z_d
+#define __PREC ppm_kind_double
+#endif
+      SUBROUTINE __ROUTINE(topoid,meshid,ppmplan,infield,outfield,info)
+      !!! FFTW execute wrapper for 3d arrays, 1d complex to complex 
+      !!! (forward and backward) FFT in the z direction
+      !!! Before calling this routine a ppm_fft_plan_ routine must be called
+      !!! The routine does not work with fields that include ghost layers
+      USE ppm_module_substart
+      USE ppm_module_substop
+      USE ppm_module_typedef
+      USE ppm_module_topo_get
+      USE ppm_module_write
+      USE ppm_module_data,ONLY:ppm_rank,ppm_kind_single,ppm_kind_double
+
+      IMPLICIT NONE
+
+      INCLUDE 'fftw3.f'
+
+      ! if debug check if dimensions are 2a 3b 5c 7d 11e 13f
+      !-------------------------------------------------------------------------
+      ! Arguments
+      !-------------------------------------------------------------------------
+      !!!topology identifier of target
+      INTEGER,INTENT(IN)                                             :: topoid
+      !!!id of the mesh
+      INTEGER,INTENT(IN)                                             :: meshid
+      !!!ppm fft plan type
+      TYPE(ppm_fft_plan),INTENT(INOUT)                               :: ppmplan
+      !!!input field to fourier transform
+      !COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER,INTENT(INOUT)     :: infield
+      COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: infield
+      !!!output field for the result of the fourier transform
+      !COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER,INTENT(INOUT)     :: outfield
+      COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: outfield
+      !!!Returns status, 0 upon success
+      INTEGER,INTENT(OUT)                                            :: info
+      !in time perhaps an argument for alternate directions
+
+      !-------------------------------------------------------------------------
+      ! Local variables
+      !-------------------------------------------------------------------------
+      REAL(__PREC)                  :: t0
+      INTEGER                       :: i,j
+      INTEGER                       :: isub,isubl
+      INTEGER                       :: nsubs
+      INTEGER,DIMENSION(:),POINTER  :: isublist
+      TYPE(ppm_t_topo),POINTER      :: topology
+      TYPE(ppm_t_equi_mesh)         :: mesh
+
+      !-------------------------------------------------------------------------
+      ! Initialise routine
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_fft_exec',t0,info)
+
+      !-------------------------------------------------------------------------
+      ! Get topology and mesh values
+      !-------------------------------------------------------------------------
+      CALL ppm_topo_get(topoid,topology,info)
+      IF (info .NE. 0) THEN
+         CALL ppm_write(ppm_rank,'ppm_fft_exec','Failed to get topology.',isub)
+         GOTO 9999
+      ENDIF
+      nsubs = topology%nsublist
+      ALLOCATE(isublist(nsubs))
+      DO isub=1,nsubs
+        isublist(isub) = topology%isublist(isub)
+      ENDDO
+      mesh  = topology%mesh(meshid)
+
+      !outfield = 0.0_ppm_kind_double !@
+      !-------------------------------------------------------------------------
+      ! Execute plan
+      !-------------------------------------------------------------------------
+      DO isub=1,nsubs
+         isubl=isublist(isub)
+         DO j=1,mesh%nnodes(2,isubl) !@ add '-1' to exclude n+1 points
+            DO i=1,mesh%nnodes(1,isubl) !@ add '-1' to exclude n+1 points
+               CALL dfftw_execute_dft(ppmplan%plan(isub),&
+               & infield(1,i,j,1,isub),outfield(1,i,j,1,isub))
+            END DO
+         END DO
+      END DO
+
+      !-------------------------------------------------------------------------
+      ! Copy periodic - this is only for the periodic 'N+1' vertex points
+      !-------------------------------------------------------------------------
+      IF (topology%bcdef(3) .EQ. ppm_param_bcdef_periodic) THEN !vertex
+         IF (ppmplan%sign .EQ. FFTW_BACKWARD) THEN
+            DO isub=1,nsubs
+               isubl=isublist(isub)
+               DO j=1,mesh%nnodes(2,isubl) !@ add '-1' to exclude n+1 points
+                  DO i=1,mesh%nnodes(1,isubl) !@ add '-1' to exclude n+1 points
+                     outfield(1,i,j,mesh%nnodes(3,isubl),isub) = outfield(1,i,j,1,isub)
+                     outfield(2,i,j,mesh%nnodes(3,isubl),isub) = outfield(2,i,j,1,isub)
+                     outfield(3,i,j,mesh%nnodes(3,isubl),isub) = outfield(3,i,j,1,isub)
+                  END DO
+               END DO
+            END DO
+         ENDIF
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      ! Return
+      !-------------------------------------------------------------------------
+ 9999 CONTINUE
+      CALL substop('ppm_fft_exec',t0,info)
+      RETURN
+
+      END SUBROUTINE __ROUTINE
diff --git a/src/fft/ppm_fft_exec_3d_vec_fr2c_xy.f b/src/fft/ppm_fft_exec_3d_vec_fr2c_xy.f
new file mode 100644
index 0000000..82ea0e3
--- /dev/null
+++ b/src/fft/ppm_fft_exec_3d_vec_fr2c_xy.f
@@ -0,0 +1,103 @@
+      !-------------------------------------------------------------------------
+      !  Subroutine   : ppm_fft_exec_3d_vec_fr2c_xy
+      !-------------------------------------------------------------------------
+      ! Copyright (c) 2010 CSE Lab (ETH Zurich), MOSAIC Group (ETH Zurich),
+      !                    Center for Fluid Dynamics (DTU)
+      !
+      ! FFTW execute wrapper for 3d arrays, 2d real to complex 
+      ! (forward) FFT in the xy directions
+      ! The routine does not work with fields that include ghost layers
+      !-------------------------------------------------------------------------
+#if __KIND == __SINGLE
+#define __ROUTINE ppm_fft_exec_3d_vec_fr2c_xy_s
+#define __PREC ppm_kind_single
+#elif __KIND == __DOUBLE
+#define __ROUTINE ppm_fft_exec_3d_vec_fr2c_xy_d
+#define __PREC ppm_kind_double
+#endif
+      SUBROUTINE __ROUTINE(topoid,meshid,ppmplan,infield,outfield,info)
+      !!! FFTW execute wrapper for 3d arrays, 2d real to complex 
+      !!! (forward) FFT in the xy directions
+      !!! Before calling this routine a ppm_fft_plan_ routine must be called
+      !!! The routine does not work with fields that include ghost layers
+      USE ppm_module_substart
+      USE ppm_module_substop
+      USE ppm_module_typedef
+      USE ppm_module_topo_get
+      USE ppm_module_write
+      USE ppm_module_data,ONLY:ppm_rank,ppm_kind_single,ppm_kind_double
+
+      IMPLICIT NONE
+
+      INCLUDE 'fftw3.f'
+
+      ! if debug check if dimensions are 2a 3b 5c 7d 11e 13f
+      !-------------------------------------------------------------------------
+      ! Arguments
+      !-------------------------------------------------------------------------
+      !!!topology identifier of target
+      INTEGER,INTENT(IN)                                             :: topoid
+      !!!id of the mesh
+      INTEGER,INTENT(IN)                                             :: meshid
+      !!!ppm fft plan type
+      TYPE(ppm_fft_plan),INTENT(INOUT)                               :: ppmplan
+      !!!input field to fourier transform
+      !REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER,INTENT(INOUT)        :: infield
+      REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER                      :: infield
+      !!!output field for the result of the fourier transform
+      !COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER,INTENT(INOUT)     :: outfield
+      COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: outfield
+      !!!Returns status, 0 upon success
+      INTEGER,INTENT(OUT)                                            :: info
+      !in time perhaps an argument for alternate directions
+
+      !-------------------------------------------------------------------------
+      ! Local variables
+      !-------------------------------------------------------------------------
+      REAL(__PREC)                  :: t0
+      INTEGER                       :: k
+      INTEGER                       :: isub,isubl
+      INTEGER                       :: nsubs
+      INTEGER,DIMENSION(:),POINTER  :: isublist
+      TYPE(ppm_t_topo),POINTER      :: topology
+      TYPE(ppm_t_equi_mesh)         :: mesh
+
+      !-------------------------------------------------------------------------
+      ! Initialise routine
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_fft_exec',t0,info)
+
+      !-------------------------------------------------------------------------
+      ! Get topology and mesh values
+      !-------------------------------------------------------------------------
+      CALL ppm_topo_get(topoid,topology,info)
+      IF (info .NE. 0) THEN
+         CALL ppm_write(ppm_rank,'ppm_fft_exec','Failed to get topology.',isub)
+         GOTO 9999
+      ENDIF
+      nsubs    = topology%nsublist
+      ALLOCATE(isublist(nsubs))
+      DO isub=1,nsubs
+        isublist(isub) = topology%isublist(isub)
+      ENDDO
+      mesh     = topology%mesh(meshid)
+
+      !-------------------------------------------------------------------------
+      ! Execute plan
+      !-------------------------------------------------------------------------
+      DO isub=1,nsubs
+         isubl=isublist(isub)
+         DO k=1,mesh%nnodes(3,isubl) !@ add '-1' to exclude n+1 slabs
+            CALL dfftw_execute_dft_r2c(ppmplan%plan(isub),&
+            & infield(1,1,1,k,isub),outfield(1,1,1,k,isub))
+         END DO
+      END DO
+
+      !-------------------------------------------------------------------------
+      ! Return
+      !-------------------------------------------------------------------------
+ 9999 CONTINUE
+      CALL substop('ppm_fft_exec',t0,info)
+      RETURN
+
+      END SUBROUTINE __ROUTINE
diff --git a/src/fft/ppm_fft_normalize_c.f b/src/fft/ppm_fft_normalize_c.f
new file mode 100644
index 0000000..d8f228f
--- /dev/null
+++ b/src/fft/ppm_fft_normalize_c.f
@@ -0,0 +1,127 @@
+      !-------------------------------------------------------------------------
+      !  Subroutine   : ppm_fft_normalize_c
+      !-------------------------------------------------------------------------
+      ! Copyright (c) 2010 CSE Lab (ETH Zurich), MOSAIC Group (ETH Zurich),
+      !                    Center for Fluid Dynamics (DTU)
+      !
+      ! The routine does not work with fields that include ghost layers.
+      ! Fields are noralized in the 1/N - fashion that scales fields to the
+      ! proper level after being FFTed and iFFTed
+      ! The routines are not meant for production code as the normalization can
+      ! be done for all dimensions in one pass - which may and should be done
+      ! in a routine (looping through the data anyway) following the FFTs.
+      !-------------------------------------------------------------------------
+#if __KIND == __SINGLE
+#define __ROUTINE ppm_fft_normalize_cs
+#define __PREC ppm_kind_single
+#elif __KIND == __DOUBLE
+#define __ROUTINE ppm_fft_normalize_cd
+#define __PREC ppm_kind_double
+#endif
+      SUBROUTINE __ROUTINE(topoid,meshid,ppmplan,infield,info)
+      !!! The routine does not work with fields that include ghost layers.
+      !!! Fields are noralized in the 1/N - fashion that scales fields to the
+      !!! proper level after being FFTed and iFFTed
+      !!! The routines are not meant for production code as the normalization 
+      !!! can be done for all dimensions in one pass - which may and should be 
+      !!! done in a routine (looping through the data anyway) following the FFTs
+      USE ppm_module_substart
+      USE ppm_module_substop
+      USE ppm_module_typedef
+      USE ppm_module_topo_get
+      USE ppm_module_write
+      USE ppm_module_data,ONLY:ppm_rank,ppm_kind_single,ppm_kind_double
+
+      IMPLICIT NONE
+
+      INCLUDE 'fftw3.f'
+
+      ! if debug check if dimensions are 2a 3b 5c 7d 11e 13f
+      !-------------------------------------------------------------------------
+      ! Arguments
+      !-------------------------------------------------------------------------
+      !!!topology identifier of target
+      INTEGER,INTENT(IN)                                             :: topoid
+      !!!id of the mesh
+      INTEGER,INTENT(IN)                                             :: meshid
+      !!!ppm fft plan type
+      TYPE(ppm_fft_plan),INTENT(INOUT)                               :: ppmplan
+      !!!input field to normalize
+      COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: infield
+      !!!Returns status, 0 upon success
+      INTEGER,INTENT(OUT)                                            :: info
+      !in time perhaps an argument for alternate directions
+
+      !-------------------------------------------------------------------------
+      ! Local variables
+      !-------------------------------------------------------------------------
+      !timer
+      INTEGER,PARAMETER             :: MK = ppm_kind_double
+      REAL(__PREC)                  :: t0
+      !normalization factor
+      REAL(MK)                      :: fac
+      INTEGER                       :: i,j,k
+      INTEGER                       :: isub,isubl
+      INTEGER                       :: nsubs
+      INTEGER,DIMENSION(:),POINTER  :: isublist
+      TYPE(ppm_t_topo),POINTER      :: topology
+      TYPE(ppm_t_equi_mesh)         :: mesh
+
+      !-------------------------------------------------------------------------
+      ! Initialise routine
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_fft_normalize',t0,info)
+
+      !-------------------------------------------------------------------------
+      ! Get topology and mesh values
+      !-------------------------------------------------------------------------
+      CALL ppm_topo_get(topoid,topology,info)
+      IF (info .NE. 0) THEN
+         CALL ppm_write(ppm_rank,'ppm_fft_plan','Failed to get topology.',isub)
+         GOTO 9999
+      ENDIF
+      nsubs = topology%nsublist
+      ALLOCATE(isublist(nsubs))
+      DO isub=1,nsubs
+        isublist(isub) = topology%isublist(isub)
+      ENDDO
+      mesh  = topology%mesh(meshid)
+
+      DO isub=1,nsubs
+         isubl=isublist(isub)
+         !determine normalization factor
+         IF (ppmplan%rank .EQ. 1) THEN
+            IF (topology%bcdef(3) .EQ. ppm_param_bcdef_periodic) THEN !vertex
+               fac = 1.0_MK/REAL((mesh%nm(3)-1),MK)
+            ELSE
+               fac = 1.0_MK/REAL((mesh%nm(3)),MK)
+            ENDIF
+         ELSE IF (ppmplan%rank .EQ. 2) THEN
+            IF (topology%bcdef(1) .EQ. ppm_param_bcdef_periodic) THEN !vertex
+               fac = 1.0_MK/REAL((mesh%nm(1)-1)*(mesh%nm(2)-1),MK)
+            ELSE
+               fac = 1.0_MK/REAL((mesh%nm(1)  )*(mesh%nm(2)  ),MK)
+            ENDIF
+         ENDIF
+
+         DO k=1,mesh%nnodes(3,isubl)
+            DO j=1,mesh%nnodes(2,isubl)
+               DO i=1,mesh%nnodes(1,isubl)
+                  infield(1,i,j,k,isub) = fac*infield(1,i,j,k,isub)
+                  infield(2,i,j,k,isub) = fac*infield(2,i,j,k,isub)
+                  infield(3,i,j,k,isub) = fac*infield(3,i,j,k,isub)
+               END DO
+            END DO
+         END DO
+      END DO
+
+
+      !-------------------------------------------------------------------------
+      ! Return
+      !-------------------------------------------------------------------------
+ 9999 CONTINUE
+      CALL substop('ppm_fft_normalize',t0,info)
+      RETURN
+
+      END SUBROUTINE __ROUTINE
+
diff --git a/src/fft/ppm_fft_normalize_r.f b/src/fft/ppm_fft_normalize_r.f
new file mode 100644
index 0000000..425ec12
--- /dev/null
+++ b/src/fft/ppm_fft_normalize_r.f
@@ -0,0 +1,128 @@
+      !-------------------------------------------------------------------------
+      !  Subroutine   : ppm_fft_normalize_r
+      !-------------------------------------------------------------------------
+      ! Copyright (c) 2010 CSE Lab (ETH Zurich), MOSAIC Group (ETH Zurich),
+      !                    Center for Fluid Dynamics (DTU)
+      !
+      ! The routine does not work with fields that include ghost layers.
+      ! Fields are noralized in the 1/N - fashion that scales fields to the
+      ! proper level after being FFTed and iFFTed
+      ! The routines are not meant for production code as the normalization can
+      ! be done for all dimensions in one pass - which may and should be done
+      ! in a routine (looping through the data anyway) following the FFTs.
+      !-------------------------------------------------------------------------
+#if __KIND == __SINGLE
+#define __ROUTINE ppm_fft_normalize_rs
+#define __PREC ppm_kind_single
+#elif __KIND == __DOUBLE
+#define __ROUTINE ppm_fft_normalize_rd
+#define __PREC ppm_kind_double
+#endif
+      SUBROUTINE __ROUTINE(topoid,meshid,ppmplan,infield,info)
+      !!! The routine does not work with fields that include ghost layers.
+      !!! Fields are noralized in the 1/N - fashion that scales fields to the
+      !!! proper level after being FFTed and iFFTed
+      !!! The routines are not meant for production code as the normalization
+      !!! can be done for all dimensions in one pass - which may and should be
+      !!! done in a routine (looping through the data anyway) following the FFTs
+      USE ppm_module_substart
+      USE ppm_module_substop
+      USE ppm_module_typedef
+      USE ppm_module_topo_get
+      USE ppm_module_write
+      USE ppm_module_data,ONLY:ppm_rank,ppm_kind_single,ppm_kind_double
+
+      IMPLICIT NONE
+
+      INCLUDE 'fftw3.f'
+
+      ! if debug check if dimensions are 2a 3b 5c 7d 11e 13f
+      !-------------------------------------------------------------------------
+      ! Arguments
+      !-------------------------------------------------------------------------
+      !!!topology identifier of target
+      INTEGER,INTENT(IN)                                             :: topoid
+      !!!id of the mesh
+      INTEGER,INTENT(IN)                                             :: meshid
+      !!!ppm fft plan type
+      TYPE(ppm_fft_plan),INTENT(INOUT)                               :: ppmplan
+      !!!input field to normalize
+      !REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER,INTENT(INOUT)        :: infield
+      REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER                      :: infield
+      !!!Returns status, 0 upon success
+      INTEGER,INTENT(OUT)                                            :: info
+      !in time perhaps an argument for alternate directions
+
+      !-------------------------------------------------------------------------
+      ! Local variables
+      !-------------------------------------------------------------------------
+      !timer
+      INTEGER,PARAMETER             :: MK = ppm_kind_double
+      REAL(__PREC)                  :: t0
+      !normalization factor
+      REAL(MK)                      :: fac
+      INTEGER                       :: i,j,k
+      INTEGER                       :: isub,isubl
+      INTEGER                       :: nsubs
+      INTEGER,DIMENSION(:),POINTER  :: isublist
+      TYPE(ppm_t_topo),POINTER      :: topology
+      TYPE(ppm_t_equi_mesh)         :: mesh
+
+      !-------------------------------------------------------------------------
+      ! Initialise routine
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_fft_normalize',t0,info)
+
+      !-------------------------------------------------------------------------
+      ! Get topology and mesh values
+      !-------------------------------------------------------------------------
+      CALL ppm_topo_get(topoid,topology,info)
+      IF (info .NE. 0) THEN
+         CALL ppm_write(ppm_rank,'ppm_fft_plan','Failed to get topology.',isub)
+         GOTO 9999
+      ENDIF
+      nsubs = topology%nsublist
+      ALLOCATE(isublist(nsubs))
+      DO isub=1,nsubs
+        isublist(isub) = topology%isublist(isub)
+      ENDDO
+      mesh  = topology%mesh(meshid)
+
+      DO isub=1,nsubs
+         isubl=isublist(isub)
+         !determine normalization factor
+         IF (ppmplan%rank .EQ. 1) THEN
+            IF (topology%bcdef(3) .EQ. ppm_param_bcdef_periodic) THEN !vertex
+               fac = 1.0_MK/REAL((mesh%nm(3)-1),MK)
+            ELSE
+               fac = 1.0_MK/REAL((mesh%nm(3)),MK)
+            ENDIF
+         ELSE IF (ppmplan%rank .EQ. 2) THEN
+            IF (topology%bcdef(1) .EQ. ppm_param_bcdef_periodic) THEN !vertex
+               fac = 1.0_MK/REAL((mesh%nm(1)-1)*(mesh%nm(2)-1),MK)
+            ELSE
+               fac = 1.0_MK/REAL((mesh%nm(1)  )*(mesh%nm(2)  ),MK)
+            ENDIF
+         ENDIF
+
+         DO k=1,mesh%nnodes(3,isubl)
+            DO j=1,mesh%nnodes(2,isubl)
+               DO i=1,mesh%nnodes(1,isubl)
+                  infield(1,i,j,k,isub) = fac*infield(1,i,j,k,isub)
+                  infield(2,i,j,k,isub) = fac*infield(2,i,j,k,isub)
+                  infield(3,i,j,k,isub) = fac*infield(3,i,j,k,isub)
+               END DO
+            END DO
+         END DO
+      END DO
+
+
+      !-------------------------------------------------------------------------
+      ! Return
+      !-------------------------------------------------------------------------
+ 9999 CONTINUE
+      CALL substop('ppm_fft_normalize',t0,info)
+      RETURN
+
+      END SUBROUTINE __ROUTINE
+
diff --git a/src/fft/ppm_fft_plan_3d_vec_bc2c_z.f b/src/fft/ppm_fft_plan_3d_vec_bc2c_z.f
new file mode 100644
index 0000000..9dd2ba2
--- /dev/null
+++ b/src/fft/ppm_fft_plan_3d_vec_bc2c_z.f
@@ -0,0 +1,149 @@
+      !-------------------------------------------------------------------------
+      !  Subroutine   : ppm_fft_plan_3d_vec_bc2c_z
+      !-------------------------------------------------------------------------
+      ! Copyright (c) 2010 CSE Lab (ETH Zurich), MOSAIC Group (ETH Zurich),
+      !                    Center for Fluid Dynamics (DTU)
+      !
+      ! FFTW plan wrapper for 3d arrays, 1d complex to complex
+      ! (backward) FFT in the z direction
+      ! The routine does not work with fields that include ghost layers
+      !-------------------------------------------------------------------------
+#if __KIND == __SINGLE
+#define __ROUTINE ppm_fft_plan_3d_vec_bc2c_z_s
+#define __PREC ppm_kind_single
+#elif __KIND == __DOUBLE
+#define __ROUTINE ppm_fft_plan_3d_vec_bc2c_z_d
+#define __PREC ppm_kind_double
+#endif
+      SUBROUTINE __ROUTINE(topoid,meshid,ppmplan,infield,outfield,info)
+      !!! FFTW plan wrapper for 3d arrays, 1d complex to complex
+      !!! (backward) FFT in the z direction
+      !!! The routine does not work with fields that include ghost layers
+      USE ppm_module_substart
+      USE ppm_module_substop
+      USE ppm_module_typedef
+      USE ppm_module_topo_get
+      USE ppm_module_write
+      USE ppm_module_data,ONLY:ppm_rank,ppm_kind_single,ppm_kind_double
+
+      IMPLICIT NONE
+
+      INCLUDE 'fftw3.f'
+
+      ! if debug check if dimensions are 2a 3b 5c 7d 11e 13f
+      !-------------------------------------------------------------------------
+      ! Arguments
+      !-------------------------------------------------------------------------
+      !!!topology identifier of target
+      INTEGER,INTENT(IN)                                             :: topoid
+      !!!id of the mesh
+      INTEGER,INTENT(IN)                                             :: meshid
+      !!!ppm fft plan type
+      TYPE(ppm_fft_plan),INTENT(INOUT)                               :: ppmplan
+      !!!input field to fourier transform
+      !COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER,INTENT(INOUT)     :: infield
+      COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: infield
+      !!!output field for the result of the fourier transform
+      !COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER,INTENT(INOUT)     :: outfield
+      COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: outfield
+      !!!Returns status, 0 upon success
+      INTEGER,INTENT(OUT)                                            :: info
+      !in time perhaps an argument for alternate directions
+
+      !-------------------------------------------------------------------------
+      ! Local variables
+      !-------------------------------------------------------------------------
+      REAL(__PREC)                  :: t0
+      INTEGER                       :: isub,isubl
+      INTEGER                       :: nsubs
+      INTEGER,DIMENSION(:),POINTER  :: isublist
+      TYPE(ppm_t_topo),POINTER      :: topology
+      TYPE(ppm_t_equi_mesh)         :: mesh
+
+      !-------------------------------------------------------------------------
+      ! Initialise routine
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_fft_plan',t0,info)
+
+      !-------------------------------------------------------------------------
+      ! Get topology and mesh values
+      !-------------------------------------------------------------------------
+      CALL ppm_topo_get(topoid,topology,info)
+      IF (info .NE. 0) THEN
+         CALL ppm_write(ppm_rank,'ppm_fft_plan','Failed to get topology.',isub)
+         GOTO 9999
+      ENDIF
+      nsubs = topology%nsublist
+      ALLOCATE(isublist(nsubs))
+      DO isub=1,nsubs
+        isublist(isub) = topology%isublist(isub)
+      ENDDO
+      mesh  = topology%mesh(meshid)
+
+      !-------------------------------------------------------------------------
+      ! Setup parameters for this particular routine
+      !-------------------------------------------------------------------------
+      !the dimension of the FFT (1D/2D/3D)
+      ppmplan%rank=1
+      !the number of points along each direction of the piece to be transformed
+      ALLOCATE(ppmplan%nx(ppmplan%rank,nsubs))
+      !the direction of the transform
+      ppmplan%sign=FFTW_BACKWARD
+      !the method to setup the optimal plan
+      ppmplan%flag=FFTW_MEASURE
+      !the number of components to transform - 3 component vector
+      ppmplan%howmany=3
+      !the size of the input array - full size (assuming LBOUND=1 thus UBOUND)
+      ALLOCATE(ppmplan%inembed(ppmplan%rank))
+      ppmplan%inembed(1) = UBOUND(infield,4)
+      !the size of the output array - full size (assuming LBOUND=1 thus UBOUND)
+      ALLOCATE(ppmplan%onembed(ppmplan%rank))
+      ppmplan%onembed(1) = UBOUND(outfield,4)
+      !istride tells how the same componenet data points are spaced in memory
+      !e.g. z values recur every x-dim*y-dim*component values
+      ppmplan%istride = UBOUND(infield,2) *UBOUND(infield,3)*3
+      ppmplan%ostride = UBOUND(outfield,2)*UBOUND(outfield,3)*3
+      !idist tells how multiple arrays are spaced in memory. I.e. a memory 
+      !offset. e.g. vector components (idist=1) or scalar 2D arrays in 
+      !3D array(idist=NxNy)
+      ppmplan%idist = 1
+      ppmplan%odist = 1
+
+      !-------------------------------------------------------------------------
+      ! Allocate plan array
+      !-------------------------------------------------------------------------
+      IF(ASSOCIATED(ppmplan%plan)) THEN
+         DEALLOCATE(ppmplan%plan,stat=info)
+         IF (info .NE. 0) THEN
+            CALL ppm_write(ppm_rank,'ppm_fft_plan','Failed to deallocate plan-array.',isub)
+            GOTO 9999
+         ENDIF
+      END IF
+      ALLOCATE(ppmplan%plan(nsubs))
+
+      DO isub=1,nsubs
+         isubl=isublist(isub)
+         !@ maybe the -1 needs to be removed when doing cell data
+         !we subtract the -1 to avoid the periodic vertex point
+         IF (topology%bcdef(3) .EQ. ppm_param_bcdef_periodic) THEN !vertex
+            ppmplan%nx(1,isub) = mesh%nnodes(3,isubl)-1
+         ELSE
+            ppmplan%nx(1,isub) = mesh%nnodes(3,isubl)
+         ENDIF
+
+         CALL dfftw_plan_many_dft(ppmplan%plan(isub),ppmplan%rank,&
+         & ppmplan%nx(:,isub),ppmplan%howmany,infield(1,1,1,1,isub),&
+         & ppmplan%inembed(1),ppmplan%istride,ppmplan%idist,&
+         & outfield(1,1,1,1,isub),ppmplan%onembed(1),ppmplan%ostride,&
+         & ppmplan%odist,ppmplan%sign,ppmplan%flag)
+      END DO
+
+
+      !-------------------------------------------------------------------------
+      ! Return
+      !-------------------------------------------------------------------------
+ 9999 CONTINUE
+      CALL substop('ppm_fft_plan',t0,info)
+      RETURN
+
+      END SUBROUTINE __ROUTINE 
diff --git a/src/fft/ppm_fft_plan_3d_vec_bc2r_xy.f b/src/fft/ppm_fft_plan_3d_vec_bc2r_xy.f
new file mode 100644
index 0000000..f83a32e
--- /dev/null
+++ b/src/fft/ppm_fft_plan_3d_vec_bc2r_xy.f
@@ -0,0 +1,154 @@
+      !-------------------------------------------------------------------------
+      !  Subroutine   : ppm_fft_plan_3d_vec_bc2r_xy
+      !-------------------------------------------------------------------------
+      ! Copyright (c) 2010 CSE Lab (ETH Zurich), MOSAIC Group (ETH Zurich),
+      !                    Center for Fluid Dynamics (DTU)
+      !
+      ! FFTW plan wrapper for 3d arrays, 2d complex to real
+      ! (backward) FFT in the xy directions
+      ! The routine does not work with fields that include ghost layers
+      !
+      ! For the C2R inverse transform FFTW always destroys the input data
+      !-------------------------------------------------------------------------
+#if __KIND == __SINGLE
+#define __ROUTINE ppm_fft_plan_3d_vec_bc2r_xy_s
+#define __PREC ppm_kind_single
+#elif __KIND == __DOUBLE
+#define __ROUTINE ppm_fft_plan_3d_vec_bc2r_xy_d
+#define __PREC ppm_kind_double
+#endif
+      SUBROUTINE __ROUTINE(topoid,meshid,ppmplan,infield,outfield,info)
+      !!! FFTW plan wrapper for 3d arrays, 2d complex to real
+      !!! (backward) FFT in the xy directions
+      !!! The routine does not work with fields that include ghost layers
+      USE ppm_module_substart
+      USE ppm_module_substop
+      USE ppm_module_typedef
+      USE ppm_module_topo_get
+      USE ppm_module_write
+      USE ppm_module_data,ONLY:ppm_rank,ppm_kind_single,ppm_kind_double
+
+      IMPLICIT NONE
+
+      INCLUDE 'fftw3.f'
+
+      ! if debug check if dimensions are 2a 3b 5c 7d 11e 13f
+      !-------------------------------------------------------------------------
+      ! Arguments
+      !-------------------------------------------------------------------------
+      !!!topology identifier of target
+      INTEGER,INTENT(IN)                                             :: topoid
+      !!!id of the mesh
+      INTEGER,INTENT(IN)                                             :: meshid
+      !!!ppm fft plan type
+      TYPE(ppm_fft_plan),INTENT(INOUT)                               :: ppmplan
+      !!!input field to fourier transform
+      !COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER,INTENT(INOUT)     :: infield
+      COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: infield
+      !!!output field for the result of the fourier transform
+      !REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER,INTENT(INOUT)        :: outfield
+      REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER                      :: outfield
+      !!!Returns status, 0 upon success
+      INTEGER,INTENT(OUT)                                            :: info
+      !in time perhaps an argument for alternate directions
+
+      !-------------------------------------------------------------------------
+      ! Local variables
+      !-------------------------------------------------------------------------
+      REAL(__PREC)                  :: t0
+      INTEGER                       :: isub,isubl
+      INTEGER                       :: nsubs
+      INTEGER,DIMENSION(:),POINTER  :: isublist
+      TYPE(ppm_t_topo),POINTER      :: topology
+      TYPE(ppm_t_equi_mesh)         :: mesh
+
+      !-------------------------------------------------------------------------
+      ! Initialise routine
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_fft_plan',t0,info)
+
+      !-------------------------------------------------------------------------
+      ! Get topology and mesh values
+      !-------------------------------------------------------------------------
+      CALL ppm_topo_get(topoid,topology,info)
+      IF (info .NE. 0) THEN
+         CALL ppm_write(ppm_rank,'ppm_fft_plan','Failed to get topology.',isub)
+         GOTO 9999
+      ENDIF
+      nsubs = topology%nsublist
+      ALLOCATE(isublist(nsubs))
+      DO isub=1,nsubs
+        isublist(isub) = topology%isublist(isub)
+      ENDDO
+      mesh  = topology%mesh(meshid)
+
+      !-------------------------------------------------------------------------
+      ! Setup parameters for this particular routine
+      !-------------------------------------------------------------------------
+      !the dimension of the FFT (1D/2D/3D)
+      ppmplan%rank=2
+      !the number of points along each direction of the piece to be transformed
+      ALLOCATE(ppmplan%nx(ppmplan%rank,nsubs))
+      !the direction of the transform
+      ppmplan%sign=FFTW_BACKWARD
+      !the method to setup the optimal plan
+      ppmplan%flag=FFTW_MEASURE
+      !the number of components to transform - 3 component vector
+      ppmplan%howmany=3
+      !the size of the input array - full size (assuming LBOUND=1 thus UBOUND)
+      ALLOCATE(ppmplan%inembed(ppmplan%rank))
+      ppmplan%inembed(1) = UBOUND(infield,2)
+      ppmplan%inembed(2) = UBOUND(infield,3)
+      !the size of the output array - full size (assuming LBOUND=1 thus UBOUND)
+      ALLOCATE(ppmplan%onembed(ppmplan%rank))
+      ppmplan%onembed(1) = UBOUND(outfield,2)
+      ppmplan%onembed(2) = UBOUND(outfield,3)
+      !istride tells how the same componenet data points are spaced in memory
+      !e.g. for 2/3 component vector istride = 2/3 or for scalar istride = 1
+      ppmplan%istride = 3
+      ppmplan%ostride = 3
+      !idist tells how multiple arrays are spaced in memory. I.e. a memory 
+      !offset. e.g. vector components (idist=1) or scalar 2D arrays 
+      !in 3D array(idist=NxNy)
+      ppmplan%idist = 1
+      ppmplan%odist = 1
+
+      !-------------------------------------------------------------------------
+      ! Allocate plan array
+      !-------------------------------------------------------------------------
+      IF(ASSOCIATED(ppmplan%plan)) THEN
+         DEALLOCATE(ppmplan%plan,stat=info)
+         IF (info .NE. 0) THEN
+            CALL ppm_write(ppm_rank,'ppm_fft_plan','Failed to deallocate plan-array.',isub)
+            GOTO 9999
+         ENDIF
+      END IF
+      ALLOCATE(ppmplan%plan(nsubs))
+
+      DO isub=1,nsubs
+         isubl=isublist(isub)
+         !@ maybe the -1 needs to be removed when doing cell data
+         !we subtract the -1 to avoid the periodic vertex point
+         IF (topology%bcdef(1) .EQ. ppm_param_bcdef_periodic) THEN !vertex
+            ppmplan%nx(1,isub) = mesh%nnodes(1,isubl)-1
+            ppmplan%nx(2,isub) = mesh%nnodes(2,isubl)-1
+         ELSE
+            ppmplan%nx(1,isub) = mesh%nnodes(1,isubl)
+            ppmplan%nx(2,isub) = mesh%nnodes(2,isubl)
+         ENDIF
+
+         CALL dfftw_plan_many_dft_c2r(ppmplan%plan(isub),ppmplan%rank,&
+         & ppmplan%nx,ppmplan%howmany,infield(1,1,1,1,isub),ppmplan%inembed(1),&
+         & ppmplan%istride,ppmplan%idist,outfield(1,1,1,1,isub),&
+         & ppmplan%onembed(1),ppmplan%ostride,ppmplan%odist,ppmplan%flag)
+      END DO
+
+
+      !-------------------------------------------------------------------------
+      ! Return
+      !-------------------------------------------------------------------------
+ 9999 CONTINUE
+      CALL substop('ppm_fft_plan',t0,info)
+      RETURN
+
+      END SUBROUTINE __ROUTINE 
diff --git a/src/fft/ppm_fft_plan_3d_vec_fc2c_z.f b/src/fft/ppm_fft_plan_3d_vec_fc2c_z.f
new file mode 100644
index 0000000..2625176
--- /dev/null
+++ b/src/fft/ppm_fft_plan_3d_vec_fc2c_z.f
@@ -0,0 +1,149 @@
+      !-------------------------------------------------------------------------
+      !  Subroutine   : ppm_fft_plan_3d_vec_fc2c_z
+      !-------------------------------------------------------------------------
+      ! Copyright (c) 2010 CSE Lab (ETH Zurich), MOSAIC Group (ETH Zurich),
+      !                    Center for Fluid Dynamics (DTU)
+      !
+      ! FFTW plan wrapper for 3d arrays, 1d complex to complex
+      ! (forward) FFT in the xy directions
+      ! The routine does not work with fields that include ghost layers
+      !-------------------------------------------------------------------------
+#if __KIND == __SINGLE
+#define __ROUTINE ppm_fft_plan_3d_vec_fc2c_z_s
+#define __PREC ppm_kind_single
+#elif __KIND == __DOUBLE
+#define __ROUTINE ppm_fft_plan_3d_vec_fc2c_z_d
+#define __PREC ppm_kind_double
+#endif
+      SUBROUTINE __ROUTINE(topoid,meshid,ppmplan,infield,outfield,info)
+      !!! FFTW plan wrapper for 3d arrays, 1d complex to complex
+      !!! (forward) FFT in the xy directions
+      !!! The routine does not work with fields that include ghost layers
+      USE ppm_module_substart
+      USE ppm_module_substop
+      USE ppm_module_typedef
+      USE ppm_module_topo_get
+      USE ppm_module_write
+      USE ppm_module_data,ONLY:ppm_rank,ppm_kind_single,ppm_kind_double
+
+      IMPLICIT NONE
+
+      INCLUDE 'fftw3.f'
+
+      ! if debug check if dimensions are 2a 3b 5c 7d 11e 13f
+      !-------------------------------------------------------------------------
+      ! Arguments
+      !-------------------------------------------------------------------------
+      !!!topology identifier of target
+      INTEGER,INTENT(IN)                                             :: topoid
+      !!!id of the mesh
+      INTEGER,INTENT(IN)                                             :: meshid
+      !!!ppm fft plan type
+      TYPE(ppm_fft_plan),INTENT(INOUT)                               :: ppmplan
+      !!!input field to fourier transform
+      !COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER,INTENT(INOUT)     :: infield
+      COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: infield
+      !!!output field for the result of the fourier transform
+      !COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER,INTENT(INOUT)     :: outfield
+      COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: outfield
+      !!!Returns status, 0 upon success
+      INTEGER,INTENT(OUT)                                            :: info
+      !in time perhaps an argument for alternate directions
+
+      !-------------------------------------------------------------------------
+      ! Local variables
+      !-------------------------------------------------------------------------
+      REAL(__PREC)                  :: t0
+      INTEGER                       :: isub,isubl
+      INTEGER                       :: nsubs
+      INTEGER,DIMENSION(:),POINTER  :: isublist
+      TYPE(ppm_t_topo),POINTER      :: topology
+      TYPE(ppm_t_equi_mesh)         :: mesh
+
+      !-------------------------------------------------------------------------
+      ! Initialise routine
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_fft_plan',t0,info)
+
+      !-------------------------------------------------------------------------
+      ! Get topology and mesh values
+      !-------------------------------------------------------------------------
+      CALL ppm_topo_get(topoid,topology,info)
+      IF (info .NE. 0) THEN
+         CALL ppm_write(ppm_rank,'ppm_fft_plan','Failed to get topology.',isub)
+         GOTO 9999
+      ENDIF
+      nsubs = topology%nsublist
+      ALLOCATE(isublist(nsubs))
+      DO isub=1,nsubs
+        isublist(isub) = topology%isublist(isub)
+      ENDDO
+      mesh  = topology%mesh(meshid)
+
+      !-------------------------------------------------------------------------
+      ! Setup parameters for this particular routine
+      !-------------------------------------------------------------------------
+      !the dimension of the FFT (1D/2D/3D)
+      ppmplan%rank=1
+      !the number of points along each direction of the piece to be transformed
+      ALLOCATE(ppmplan%nx(ppmplan%rank,nsubs))
+      !the direction of the transform
+      ppmplan%sign=FFTW_FORWARD
+      !the method to setup the optimal plan
+      ppmplan%flag=FFTW_MEASURE
+      !the number of components to transform - 3 component vector
+      ppmplan%howmany=3
+      !the size of the input array - full size (assuming LBOUND=1 thus UBOUND)
+      ALLOCATE(ppmplan%inembed(ppmplan%rank))
+      ppmplan%inembed(1) = UBOUND(infield,4)
+      !the size of the output array - full size (assuming LBOUND=1 thus UBOUND)
+      ALLOCATE(ppmplan%onembed(ppmplan%rank))
+      ppmplan%onembed(1) = UBOUND(outfield,4)
+      !istride tells how the same componenet data points are spaced in memory
+      !e.g. for 2/3 component vector istride = 2/3 or for scalar istride = 1
+      ppmplan%istride = UBOUND(infield,2) *UBOUND(infield,3)*3
+      ppmplan%ostride = UBOUND(outfield,2)*UBOUND(outfield,3)*3
+      !idist tells how multiple arrays are spaced in memory. I.e. a memory 
+      !offset. e.g. vector components (idist=1) or scalar 2D arrays in 
+      !3D array(idist=NxNy)
+      ppmplan%idist = 1
+      ppmplan%odist = 1
+
+      !-------------------------------------------------------------------------
+      ! Allocate plan array
+      !-------------------------------------------------------------------------
+      IF(ASSOCIATED(ppmplan%plan)) THEN
+         DEALLOCATE(ppmplan%plan,stat=info)
+         IF (info .NE. 0) THEN
+            CALL ppm_write(ppm_rank,'ppm_fft_plan','Failed to deallocate plan-array.',isub)
+            GOTO 9999
+         ENDIF
+      END IF
+      ALLOCATE(ppmplan%plan(nsubs))
+
+      DO isub=1,nsubs
+         isubl=isublist(isub)
+         !@ maybe the -1 needs to be removed when doing cell data
+         !we subtract the -1 to avoid the periodic vertex point
+         IF (topology%bcdef(3) .EQ. ppm_param_bcdef_periodic) THEN !vertex
+            ppmplan%nx(1,isub) = mesh%nnodes(3,isubl)-1
+         ELSE
+            ppmplan%nx(1,isub) = mesh%nnodes(3,isubl)
+         ENDIF
+
+         CALL dfftw_plan_many_dft(ppmplan%plan(isub),ppmplan%rank,&
+         & ppmplan%nx(:,isub),ppmplan%howmany,infield(1,1,1,1,isub),&
+         & ppmplan%inembed(1),ppmplan%istride,ppmplan%idist,&
+         & outfield(1,1,1,1,isub),ppmplan%onembed(1),ppmplan%ostride,&
+         & ppmplan%odist,ppmplan%sign,ppmplan%flag)
+      END DO
+
+
+      !-------------------------------------------------------------------------
+      ! Return
+      !-------------------------------------------------------------------------
+ 9999 CONTINUE
+      CALL substop('ppm_fft_plan',t0,info)
+      RETURN
+
+      END SUBROUTINE __ROUTINE 
diff --git a/src/fft/ppm_fft_plan_3d_vec_fr2c_xy.f b/src/fft/ppm_fft_plan_3d_vec_fr2c_xy.f
new file mode 100644
index 0000000..d1eab5b
--- /dev/null
+++ b/src/fft/ppm_fft_plan_3d_vec_fr2c_xy.f
@@ -0,0 +1,153 @@
+      !-------------------------------------------------------------------------
+      !  Subroutine   : ppm_fft_plan_3d_vec_fr2c_xy
+      !-------------------------------------------------------------------------
+      ! Copyright (c) 2010 CSE Lab (ETH Zurich), MOSAIC Group (ETH Zurich),
+      !                    Center for Fluid Dynamics (DTU)
+      !
+      ! FFTW plan wrapper for 3d arrays, 2d real to complex
+      ! (forward) FFT in the xy directions
+      ! The routine does not work with fields that include ghost layers
+      !-------------------------------------------------------------------------
+#if __KIND == __SINGLE
+#define __ROUTINE ppm_fft_plan_3d_vec_fr2c_xy_s
+#define __PREC ppm_kind_single
+#elif __KIND == __DOUBLE
+#define __ROUTINE ppm_fft_plan_3d_vec_fr2c_xy_d
+#define __PREC ppm_kind_double
+#endif
+      SUBROUTINE __ROUTINE(topoid,meshid,ppmplan,infield,outfield,info)
+      !!! FFTW plan wrapper for 3d arrays, 2d real to complex
+      !!! (forward) FFT in the xy directions
+      !!! The routine does not work with fields that include ghost layers
+      USE ppm_module_substart
+      USE ppm_module_substop
+      USE ppm_module_typedef
+      USE ppm_module_topo_get
+      USE ppm_module_write
+      USE ppm_module_data,ONLY:ppm_rank,ppm_kind_single,ppm_kind_double
+
+      IMPLICIT NONE
+
+      INCLUDE 'fftw3.f'
+
+      ! if debug check if dimensions are 2a 3b 5c 7d 11e 13f
+      !-------------------------------------------------------------------------
+      ! Arguments
+      !-------------------------------------------------------------------------
+      !!!topology identifier of target
+      INTEGER,INTENT(IN)                                             :: topoid
+      !!!id of the mesh
+      INTEGER,INTENT(IN)                                             :: meshid
+      !!!ppm fft plan type
+      TYPE(ppm_fft_plan),INTENT(INOUT)                               :: ppmplan
+      !!!input field to fourier transform
+      !REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER,INTENT(INOUT)        :: infield
+      REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER                      :: infield
+      !!!output field for the result of the fourier transform
+      !COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER,INTENT(INOUT)     :: outfield
+      COMPLEX(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: outfield
+      !!!Returns status, 0 upon success
+      INTEGER,INTENT(OUT)                                            :: info
+      !in time perhaps an argument for alternate directions
+
+      !-------------------------------------------------------------------------
+      ! Local variables
+      !-------------------------------------------------------------------------
+      REAL(__PREC)                  :: t0
+      INTEGER                       :: isub,isubl
+      INTEGER                       :: nsubs
+      INTEGER,DIMENSION(:),POINTER  :: isublist
+      TYPE(ppm_t_topo),POINTER      :: topology
+      TYPE(ppm_t_equi_mesh)         :: mesh
+
+      !-------------------------------------------------------------------------
+      ! Initialise routine
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_fft_plan',t0,info)
+
+      !-------------------------------------------------------------------------
+      ! Get topology and mesh values
+      !-------------------------------------------------------------------------
+      CALL ppm_topo_get(topoid,topology,info)
+      IF (info .NE. 0) THEN
+         CALL ppm_write(ppm_rank,'ppm_fft_plan','Failed to get topology.',isub)
+         GOTO 9999
+      ENDIF
+      nsubs = topology%nsublist
+      ALLOCATE(isublist(nsubs))
+      DO isub=1,nsubs
+        isublist(isub) = topology%isublist(isub)
+      ENDDO
+      mesh  = topology%mesh(meshid)
+
+      !-------------------------------------------------------------------------
+      ! Setup parameters for this particular routine
+      !-------------------------------------------------------------------------
+      !the dimension of the FFT (1D/2D/3D)
+      ppmplan%rank=2
+      !the number of points along each direction of the piece to be transformed
+      ALLOCATE(ppmplan%nx(ppmplan%rank,nsubs))
+      !the direction of the transform
+      ppmplan%sign=FFTW_FORWARD
+      !the method to setup the optimal plan
+      ppmplan%flag=FFTW_MEASURE
+      !the number of components to transform - 3 component vector
+      ppmplan%howmany=3
+      !the size of the input array - full size (assuming LBOUND=1 thus UBOUND)
+      ALLOCATE(ppmplan%inembed(ppmplan%rank))
+      ppmplan%inembed(1) = UBOUND(infield,2)
+      ppmplan%inembed(2) = UBOUND(infield,3)
+      !the size of the output array - full size (assuming LBOUND=1 thus UBOUND)
+      ALLOCATE(ppmplan%onembed(ppmplan%rank))
+      ppmplan%onembed(1) = UBOUND(outfield,2)
+      ppmplan%onembed(2) = UBOUND(outfield,3)
+      !istride tells how the same componenet data points are spaced in memory
+      !e.g. for 2/3 component vector istride = 2/3 or for scalar istride = 1
+      ppmplan%istride = 3
+      ppmplan%ostride = 3
+      !idist tells how multiple arrays are spaced in memory. I.e. a memory 
+      !offset. e.g. vector components (idist=1) or scalar 2D arrays in 
+      !3D array(idist=NxNy)
+      ppmplan%idist = 1
+      ppmplan%odist = 1
+
+      !-------------------------------------------------------------------------
+      ! Allocate plan array
+      !-------------------------------------------------------------------------
+      IF(ASSOCIATED(ppmplan%plan)) THEN
+         DEALLOCATE(ppmplan%plan,stat=info)
+         IF (info .NE. 0) THEN
+            CALL ppm_write(ppm_rank,'ppm_fft_plan','Failed to deallocate plan-array.',isub)
+            GOTO 9999
+         ENDIF
+      END IF
+      ALLOCATE(ppmplan%plan(nsubs))
+
+      DO isub=1,nsubs
+         isubl=isublist(isub)
+         !@ maybe the -1 needs to be removed when doing cell data
+         !we subtract the -1 to avoid the periodic vertex point
+         IF (topology%bcdef(1) .EQ. ppm_param_bcdef_periodic) THEN !vertex
+            ppmplan%nx(1,isub) = mesh%nnodes(1,isubl)-1
+            ppmplan%nx(2,isub) = mesh%nnodes(2,isubl)-1
+         ELSE
+            ppmplan%nx(1,isub) = mesh%nnodes(1,isubl)
+            ppmplan%nx(2,isub) = mesh%nnodes(2,isubl)
+         ENDIF
+
+         CALL dfftw_plan_many_dft_r2c(ppmplan%plan(isub),ppmplan%rank,&
+         & ppmplan%nx(:,isub),ppmplan%howmany,infield(1,1,1,1,isub),&
+         & ppmplan%inembed(1),ppmplan%istride,ppmplan%idist,&
+         & outfield(1,1,1,1,isub),ppmplan%onembed(1),ppmplan%ostride,&
+         & ppmplan%odist,ppmplan%flag)
+      END DO
+
+
+      !-------------------------------------------------------------------------
+      ! Return
+      !-------------------------------------------------------------------------
+ 9999 CONTINUE
+      CALL substop('ppm_fft_plan',t0,info)
+      RETURN
+
+      END SUBROUTINE __ROUTINE 
diff --git a/src/poisson/ppm_poisson_extrapolateghost.f b/src/poisson/ppm_poisson_extrapolateghost.f
new file mode 100644
index 0000000..c2cc564
--- /dev/null
+++ b/src/poisson/ppm_poisson_extrapolateghost.f
@@ -0,0 +1,257 @@
+      !-------------------------------------------------------------------------
+      ! ppm_poisson_extrapolateghost.f90
+      !-------------------------------------------------------------------------
+!!#define __ROUTINE ppm_poisson_extrapolateghost_vr
+!!#define __DIM  3
+!!#define __NCOM  3
+!!#define __ZEROSI (/0,0,0/)
+      SUBROUTINE __ROUTINE(topoid,meshid,field,nextra,nbase,gstw,info)
+
+      USE ppm_module_topo_get
+
+
+      IMPLICIT NONE
+      !-------------------------------------------------------------------------
+      ! Arguments
+      !-------------------------------------------------------------------------
+      INTEGER, INTENT(IN)                                         :: topoid
+      !!! Topology id of the field
+      INTEGER, INTENT(IN)                                         :: meshid
+      !!! Mesh id of the field
+      REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: field
+      !!! Field to extrapolate ghost layer
+      INTEGER, INTENT(IN)                                         :: nextra
+      !!! Number of points to extrapolate into the ghostlayer
+      INTEGER, INTENT(IN)                                         :: nbase
+      !!! Number of points to base the extrapolation on
+      INTEGER,DIMENSION(__DIM),INTENT(IN)                         :: gstw
+      !!! Width of the ghotslayer
+      INTEGER, INTENT(OUT)                                        :: info
+      !!! Return state
+
+      !-------------------------------------------------------------------------
+      ! Local variables
+      !-------------------------------------------------------------------------
+      INTEGER,PARAMETER                    :: MK = __PREC
+      REAL(__PREC)                         :: t0
+      TYPE(ppm_t_topo),POINTER             :: topology
+      TYPE(ppm_t_equi_mesh)                :: mesh
+      INTEGER                              :: isub,isubl
+      INTEGER                              :: i,j,k,iextra,ibase
+      REAL(__PREC),DIMENSION(:,:),POINTER  :: coeff
+      REAL(__PREC),DIMENSION(__DIM)        :: tmpbuf
+
+
+      !-------------------------------------------------------------------------
+      ! Initialise routine
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_poisson_extrapolateghost',t0,info)
+
+
+      !-------------------------------------------------------------------------
+      ! Compare the number of points to extrapolate to the ghost layer width
+      !-------------------------------------------------------------------------
+      IF (iextra .GT. gstw(1) .OR. &
+        & iextra .GT. gstw(2) .OR. &
+        & iextra .GT. gstw(3)) THEN
+         CALL ppm_write(ppm_rank,'ppm_poisson_extrapolateghost',&
+         & 'The points to extrapolate exceeds the ghost layer.',info)
+         info = -1
+         GOTO 9999
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      !@ Check what has been implemented in this routine so far
+      !-------------------------------------------------------------------------
+
+      !-------------------------------------------------------------------------
+      ! Determine weights
+      !-------------------------------------------------------------------------
+      ALLOCATE(coeff(nbase,nextra))
+      IF (nbase .EQ. 4) THEN
+        IF (nextra .GE. 1) THEN
+          coeff(:,1) = (/4.0_MK,-6.0_MK,4.0_MK,-1.0_MK/)
+        ENDIF
+        IF (nextra .GE. 2) THEN
+          coeff(:,2) = (/10.0_MK,-20.0_MK,15.0_MK,-4.0_MK/)
+        ENDIF
+        IF (nextra .GE. 3) THEN
+          CALL ppm_write(ppm_rank,'ppm_poisson_extrapolateghost',&
+          & 'Extrapolation to more than two points has not been implemented.',info)
+          info = -1
+          GOTO 9999
+        ENDIF
+      ELSE
+        CALL ppm_write(ppm_rank,'ppm_poisson_extrapolateghost',&
+        & 'Only extrapolation based on 4 points has been implemented.',info)
+        info = -1
+        GOTO 9999
+      ENDIF
+
+
+      !-------------------------------------------------------------------------
+      ! Get topology
+      !-------------------------------------------------------------------------
+      CALL ppm_topo_get(topoid,topology,info)
+      IF (info .NE. 0) THEN
+         CALL ppm_write(ppm_rank,'ppm_poisson_extrapolateghost',&
+         & 'Failed to get topology.',isub)
+         GOTO 9999
+      ENDIF
+      mesh = topology%mesh(meshid)
+
+      !-------------------------------------------------------------------------
+      ! Extrapolate field into ghost layer
+      ! The indicies of subs_bc represent: 
+      ! west,east(x),south,north(y),bottom,top(z)
+      !@ Some more unrolling here would be nice
+      !-------------------------------------------------------------------------
+      DO isub=1,topology%nsublist
+         isubl=topology%isublist(isub)
+         !West (-x)
+         IF (topology%subs_bc(1,isubl) .EQ. 1) THEN
+            DO k=1-gstw(3),mesh%nnodes(3,isubl)+gstw(3)
+               DO j=1-gstw(2),mesh%nnodes(2,isubl)+gstw(2)
+                  !DO i=1-gstw(1),mesh%nnodes(1,isubl)+gstw(1)
+                  i = 1
+                  DO iextra=1,nextra
+                     tmpbuf = 0.0_MK
+                     DO ibase=0,nbase-1
+                        tmpbuf(1) = tmpbuf(1) + &
+                         & coeff(ibase+1,iextra)*field(1,i+ibase,j,k,isub)
+                        tmpbuf(2) = tmpbuf(2) + &
+                         & coeff(ibase+1,iextra)*field(2,i+ibase,j,k,isub)
+                        tmpbuf(3) = tmpbuf(3) + &
+                         & coeff(ibase+1,iextra)*field(3,i+ibase,j,k,isub)
+                     END DO !ibase
+                     field(1,i-iextra,j,k,isub) = tmpbuf(1)
+                     field(2,i-iextra,j,k,isub) = tmpbuf(2)
+                     field(3,i-iextra,j,k,isub) = tmpbuf(3)
+                  END DO !iextra
+               ENDDO !j
+            ENDDO !k
+         ENDIF
+         !East (+x)
+         IF (topology%subs_bc(2,isubl) .EQ. 1) THEN
+            DO k=1-gstw(3),mesh%nnodes(3,isubl)+gstw(3)
+               DO j=1-gstw(2),mesh%nnodes(2,isubl)+gstw(2)
+                  !DO i=1-gstw(1),mesh%nnodes(1,isubl)+gstw(1)
+                  i = mesh%nnodes(1,isubl)
+                  DO iextra=1,nextra
+                     tmpbuf = 0.0_MK
+                     DO ibase=0,nbase-1
+                        tmpbuf(1) = tmpbuf(1) + &
+                         & coeff(ibase+1,iextra)*field(1,i-ibase,j,k,isub)
+                        tmpbuf(2) = tmpbuf(2) + &
+                         & coeff(ibase+1,iextra)*field(2,i-ibase,j,k,isub)
+                        tmpbuf(3) = tmpbuf(3) + &
+                         & coeff(ibase+1,iextra)*field(3,i-ibase,j,k,isub)
+                     END DO !ibase
+                     field(1,i+iextra,j,k,isub) = tmpbuf(1)
+                     field(2,i+iextra,j,k,isub) = tmpbuf(2)
+                     field(3,i+iextra,j,k,isub) = tmpbuf(3)
+                  END DO !iextra
+               ENDDO !j
+            ENDDO !k
+         ENDIF
+         !South (-y)
+         IF (topology%subs_bc(3,isubl) .EQ. 1) THEN
+            DO k=1-gstw(3),mesh%nnodes(3,isubl)+gstw(3)
+               !DO j=1-gstw(2),mesh%nnodes(2,isubl)+gstw(2)
+               DO i=1-gstw(1),mesh%nnodes(1,isubl)+gstw(1)
+                  j = 1
+                  DO iextra=1,nextra
+                     tmpbuf = 0.0_MK
+                     DO ibase=0,nbase-1
+                        tmpbuf(1) = tmpbuf(1) + &
+                         & coeff(ibase+1,iextra)*field(1,i,j+ibase,k,isub)
+                        tmpbuf(2) = tmpbuf(2) + &
+                         & coeff(ibase+1,iextra)*field(2,i,j+ibase,k,isub)
+                        tmpbuf(3) = tmpbuf(3) + &
+                         & coeff(ibase+1,iextra)*field(3,i,j+ibase,k,isub)
+                     END DO !ibase
+                     field(1,i,j-iextra,k,isub) = tmpbuf(1)
+                     field(2,i,j-iextra,k,isub) = tmpbuf(2)
+                     field(3,i,j-iextra,k,isub) = tmpbuf(3)
+                  END DO !iextra
+               ENDDO !i
+            ENDDO !k
+         ENDIF
+         !North (+y)
+         IF (topology%subs_bc(4,isubl) .EQ. 1) THEN
+            DO k=1-gstw(3),mesh%nnodes(3,isubl)+gstw(3)
+               !DO j=1-gstw(2),mesh%nnodes(2,isubl)+gstw(2)
+               DO i=1-gstw(1),mesh%nnodes(1,isubl)+gstw(1)
+                  j = mesh%nnodes(2,isubl)
+                  DO iextra=1,nextra
+                     tmpbuf = 0.0_MK
+                     DO ibase=0,nbase-1
+                        tmpbuf(1) = tmpbuf(1) + &
+                         & coeff(ibase+1,iextra)*field(1,i,j-ibase,k,isub)
+                        tmpbuf(2) = tmpbuf(2) + &
+                         & coeff(ibase+1,iextra)*field(2,i,j-ibase,k,isub)
+                        tmpbuf(3) = tmpbuf(3) + &
+                         & coeff(ibase+1,iextra)*field(3,i,j-ibase,k,isub)
+                     END DO !ibase
+                     field(1,i,j+iextra,k,isub) = tmpbuf(1)
+                     field(2,i,j+iextra,k,isub) = tmpbuf(2)
+                     field(3,i,j+iextra,k,isub) = tmpbuf(3)
+                  END DO !iextra
+               ENDDO !i
+            ENDDO !k
+         ENDIF
+         !Bottom (-z)
+         IF (topology%subs_bc(5,isubl) .EQ. 1) THEN
+            !DO k=1-gstw(3),mesh%nnodes(3,isubl)+gstw(3)
+            DO j=1-gstw(2),mesh%nnodes(2,isubl)+gstw(2)
+               DO i=1-gstw(1),mesh%nnodes(1,isubl)+gstw(1)
+                  k = 1
+                  DO iextra=1,nextra
+                     tmpbuf = 0.0_MK
+                     DO ibase=0,nbase-1
+                        tmpbuf(1) = tmpbuf(1) + &
+                         & coeff(ibase+1,iextra)*field(1,i,j,k+ibase,isub)
+                        tmpbuf(2) = tmpbuf(2) + &
+                         & coeff(ibase+1,iextra)*field(2,i,j,k+ibase,isub)
+                        tmpbuf(3) = tmpbuf(3) + &
+                         & coeff(ibase+1,iextra)*field(3,i,j,k+ibase,isub)
+                     END DO !ibase
+                     field(1,i,j,k-iextra,isub) = tmpbuf(1)
+                     field(2,i,j,k-iextra,isub) = tmpbuf(2)
+                     field(3,i,j,k-iextra,isub) = tmpbuf(3)
+                  END DO !iextra
+               ENDDO !i
+            ENDDO !j
+         ENDIF
+         !Top (+z)
+         IF (topology%subs_bc(6,isubl) .EQ. 1) THEN
+            !DO k=1-gstw(3),mesh%nnodes(3,isubl)+gstw(3)
+            DO j=1-gstw(2),mesh%nnodes(2,isubl)+gstw(2)
+               DO i=1-gstw(1),mesh%nnodes(1,isubl)+gstw(1)
+                  k = mesh%nnodes(3,isubl)
+                  DO iextra=1,nextra
+                     tmpbuf = 0.0_MK
+                     DO ibase=0,nbase-1
+                        tmpbuf(1) = tmpbuf(1) + &
+                         & coeff(ibase+1,iextra)*field(1,i,j,k-ibase,isub)
+                        tmpbuf(2) = tmpbuf(2) + &
+                         & coeff(ibase+1,iextra)*field(2,i,j,k-ibase,isub)
+                        tmpbuf(3) = tmpbuf(3) + &
+                         & coeff(ibase+1,iextra)*field(3,i,j,k-ibase,isub)
+                     END DO !ibase
+                     field(1,i,j,k+iextra,isub) = tmpbuf(1)
+                     field(2,i,j,k+iextra,isub) = tmpbuf(2)
+                     field(3,i,j,k+iextra,isub) = tmpbuf(3)
+                  END DO !iextra
+               ENDDO !i
+            ENDDO !j
+         ENDIF
+      ENDDO !isub
+
+
+ 9999 CONTINUE
+      CALL substop('ppm_poisson_extrapolateghost',t0,info)
+      RETURN
+
+      END SUBROUTINE __ROUTINE
+
diff --git a/src/poisson/ppm_poisson_fd.f b/src/poisson/ppm_poisson_fd.f
new file mode 100644
index 0000000..ebc7415
--- /dev/null
+++ b/src/poisson/ppm_poisson_fd.f
@@ -0,0 +1,147 @@
+      !-------------------------------------------------------------------------
+      ! ppm_poisson_fd.f90
+      !-------------------------------------------------------------------------
+      !@ TODO: Somewhere check if fieldin is equal to fieldout and give a warning
+      !-------------------------------------------------------------------------
+      !!#define __ROUTINE ppm_poisson_fd
+      !!#define __DIM  3
+      !!#define __NCOM  3
+      !!#define __ZEROSI (/0,0,0/)
+      SUBROUTINE __ROUTINE(topoid,meshid,fieldin,fieldout,dtype,info)
+
+      USE ppm_module_topo_get
+
+      IMPLICIT NONE
+      !-------------------------------------------------------------------------
+      ! Arguments
+      !-------------------------------------------------------------------------
+      INTEGER, INTENT(IN)                                         :: topoid
+      INTEGER, INTENT(IN)                                         :: meshid
+      REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: fieldin
+      REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: fieldout
+      !INTEGER,DIMENSION(__DIM),INTENT(IN)                         :: gstw
+      INTEGER, INTENT(IN)                                         :: dtype
+      INTEGER, INTENT(OUT)                                        :: info
+
+      !-------------------------------------------------------------------------
+      ! Local variables
+      !-------------------------------------------------------------------------
+      INTEGER,PARAMETER                 :: MK = __PREC
+      REAL(__PREC)                      :: t0
+      TYPE(ppm_t_topo),POINTER          :: topology
+      TYPE(ppm_t_equi_mesh)             :: mesh
+      REAL(__PREC)                      :: dx,dy,dz
+      REAL(__PREC)                      :: facx,facy,facz
+      INTEGER                           :: isub,isubl
+      INTEGER                           :: i,j,k
+
+      !-------------------------------------------------------------------------
+      ! Initialise routine
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_poisson_fd',t0,info)
+
+      !@ perhaps ensure that fieldin .NE. fieldout
+      !-------------------------------------------------------------------------
+      ! Get topology and mesh values
+      !-------------------------------------------------------------------------
+      CALL ppm_topo_get(topoid,topology,info)
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank,'ppm_poisson_init_predef','Failed to get topology.',isub)
+        GOTO 9999
+      ENDIF
+      mesh  = topology%mesh(meshid)
+
+      dx = (topology%max_physd(1)-topology%min_physd(1))/REAL(mesh%nm(1)-1) !vertex
+      dy = (topology%max_physd(2)-topology%min_physd(2))/REAL(mesh%nm(2)-1)
+      dz = (topology%max_physd(3)-topology%min_physd(3))/REAL(mesh%nm(3)-1)
+
+      !-----------------------------------------------------------------------
+      ! Do the finite difference calculation
+      !-----------------------------------------------------------------------
+      !-----------------------------------------------------------------------
+      ! Curl, 2nd order FD
+      !-----------------------------------------------------------------------
+      IF (dtype .EQ. ppm_poisson_drv_curl_fd2) THEN
+        facx = 1.0_MK/(2.0_MK*dx)
+        facy = 1.0_MK/(2.0_MK*dy)
+        facz = 1.0_MK/(2.0_MK*dz)
+
+        DO isub=1,topology%nsublist
+          isubl=topology%isublist(isub)
+          DO k=1,mesh%nnodes(3,isubl)
+            DO j=1,mesh%nnodes(2,isubl)
+              DO i=1,mesh%nnodes(1,isubl)
+                fieldout(1,i,j,k,isub) = &
+                &  facy*(fieldin(3,i  ,j+1,k  ,isub)- &
+                       & fieldin(3,i  ,j-1,k  ,isub)) &
+                & -facz*(fieldin(2,i  ,j  ,k+1,isub)- &
+                       & fieldin(2,i  ,j  ,k-1,isub))
+                fieldout(2,i,j,k,isub) = &
+                &  facz*(fieldin(1,i  ,j  ,k+1,isub)- &
+                       & fieldin(1,i  ,j  ,k-1,isub)) &
+                & -facx*(fieldin(3,i+1,j  ,k  ,isub)- &
+                       & fieldin(3,i-1,j  ,k  ,isub))
+                fieldout(3,i,j,k,isub) = &
+                &  facx*(fieldin(2,i+1,j  ,k  ,isub)- &
+                       & fieldin(2,i-1,j  ,k  ,isub)) &
+                & -facy*(fieldin(1,i  ,j+1,k  ,isub)- &
+                       & fieldin(1,i  ,j-1,k  ,isub))
+              ENDDO
+            ENDDO
+          ENDDO
+        ENDDO
+      !-----------------------------------------------------------------------
+      ! Curl, 4th order FD - untested
+      !-----------------------------------------------------------------------
+      ELSE IF (dtype .EQ. ppm_poisson_drv_curl_fd4) THEN
+        facx = 1.0_MK/(12.0_MK*dx)
+        facy = 1.0_MK/(12.0_MK*dy)
+        facz = 1.0_MK/(12.0_MK*dz)
+
+        DO isub=1,topology%nsublist
+          isubl=topology%isublist(isub)
+          DO k=1,mesh%nnodes(3,isubl)
+            DO j=1,mesh%nnodes(2,isubl)
+              DO i=1,mesh%nnodes(1,isubl)
+                fieldout(1,i,j,k,isub) = &
+                &  facy*(         -fieldin(3,i  ,j+2,k  ,isub)  &
+                       &   +8.0_MK*fieldin(3,i  ,j+1,k  ,isub)  &
+                       &   -8.0_MK*fieldin(3,i  ,j-1,k  ,isub)  &
+                       &          +fieldin(3,i  ,j-2,k  ,isub)) &
+                & -facz*(         -fieldin(2,i  ,j  ,k+2,isub)  &
+                       &   +8.0_MK*fieldin(2,i  ,j  ,k+1,isub)  &
+                       &   -8.0_MK*fieldin(2,i  ,j  ,k-1,isub)  &
+                       &          +fieldin(2,i  ,j  ,k-2,isub))
+                fieldout(2,i,j,k,isub) = &
+                &  facz*(         -fieldin(1,i  ,j  ,k+2,isub)  &
+                       &   +8.0_MK*fieldin(1,i  ,j  ,k+1,isub)  &
+                       &   -8.0_MK*fieldin(1,i  ,j  ,k-1,isub)  &
+                       &          +fieldin(1,i  ,j  ,k-2,isub)) &
+                & -facx*(         -fieldin(3,i+2,j  ,k  ,isub)  &
+                       &   +8.0_MK*fieldin(3,i+1,j  ,k  ,isub)  &
+                       &   -8.0_MK*fieldin(3,i-1,j  ,k  ,isub)  &
+                       &          +fieldin(3,i-2,j  ,k  ,isub))
+                fieldout(3,i,j,k,isub) = &
+                &  facx*(         -fieldin(2,i+2,j  ,k  ,isub)  &
+                       &   +8.0_MK*fieldin(2,i+1,j  ,k  ,isub)  &
+                       &   -8.0_MK*fieldin(2,i-1,j  ,k  ,isub)  &
+                       &          +fieldin(2,i-2,j  ,k  ,isub)) &
+                & -facy*(         -fieldin(1,i  ,j+2,k  ,isub)  &
+                       &   +8.0_MK*fieldin(1,i  ,j+1,k  ,isub)  &
+                       &   -8.0_MK*fieldin(1,i  ,j-1,k  ,isub)  &
+                       &          +fieldin(1,i  ,j-2,k  ,isub))
+              ENDDO
+            ENDDO
+          ENDDO
+        ENDDO
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      ! Return
+      !-------------------------------------------------------------------------
+ 9999 CONTINUE
+      CALL substop('ppm_poisson_fd',t0,info)
+      RETURN
+
+      END SUBROUTINE __ROUTINE
+
diff --git a/src/poisson/ppm_poisson_init_predef.f b/src/poisson/ppm_poisson_init_predef.f
new file mode 100644
index 0000000..5baa4c8
--- /dev/null
+++ b/src/poisson/ppm_poisson_init_predef.f
@@ -0,0 +1,637 @@
+      !-------------------------------------------------------------------------
+      ! ppm_poisson_init_predef.f90
+      !-------------------------------------------------------------------------
+      ! Routine to initialise the convolution using build in Greens function
+      !-------------------------------------------------------------------------
+!!#define __PREC ppm_kind_double
+!!#define __CMPLXDEF DCMPLX
+!!#define __DIM  3
+!!#define __NCOM  3
+!!#define __ZEROSI (/0,0,0/)
+!!#define __ROUTINE ppm_poisson_init_predef
+      SUBROUTINE __ROUTINE(topoid,meshid,ppmpoisson,fieldin,fieldout,green,info&
+                                &,bc,derive)
+
+      USE ppm_module_mktopo
+      USE ppm_module_topo_get
+      USE ppm_module_mesh_define
+      USE ppm_module_map_field
+      USE ppm_module_map_field_global
+      USE ppm_module_map
+
+      IMPLICIT NONE
+      !-------------------------------------------------------------------------
+      ! Arguments
+      !-------------------------------------------------------------------------
+      INTEGER, INTENT(IN)                                         :: topoid
+      INTEGER, INTENT(IN)                                         :: meshid
+      TYPE(ppm_poisson_plan),INTENT(INOUT)                        :: ppmpoisson
+      !@ strictly speaking fieldin is not being used in the init routine
+      REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: fieldin
+      REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: fieldout
+      !REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: green
+      INTEGER, INTENT(IN)                                         :: green
+      !!!flag to select build-in Greens functions:
+      !!!ppm_poisson_grn_pois_per - Poisson equation, periodic boundaries
+      !!!ppm_poisson_grn_pois_fre - Poisson equation, freespace boundaries (not implemented)
+      !!!ppm_poisson_grn_reprojec - Do vorticity reprojection to kill divergence
+      INTEGER, INTENT(OUT)                                        :: info
+      INTEGER,INTENT(IN),OPTIONAL                                 :: bc
+      !!!boundary condition for the convolution. Can be on of the following:
+      !!!ppm_poisson_grn_pois_per, ppm_poisson_grn_pois_fre.
+      !!!One could argue that this is redundant in the build-in case
+      !!!@ Isnt this redundant because of green?
+      INTEGER,INTENT(IN),OPTIONAL                                 :: derive
+      !!!flag to toggle various derivatives of the solution (not to be used with
+      !!!green=ppm_poisson_grn_reprojec):
+      !!!ppm_poisson_drv_none
+      !!!ppm_poisson_drv_curl_fd (not implemented)
+      !!!ppm_poisson_drv_grad_fd (not implemented)
+      !!!ppm_poisson_drv_lapl_fd (not implemented)
+      !!!ppm_poisson_drv_curl_sp (not implemented)
+      !!!ppm_poisson_drv_grad_sp (not implemented)
+      !!!ppm_poisson_drv_lapl_sp (not implemented)
+      !!!The spectral derivatives can only be computed in this routine. Since 
+      !!!the flag exists finite difference derivatives have also been included.
+
+      !-------------------------------------------------------------------------
+      ! Local variables
+      !-------------------------------------------------------------------------
+      REAL(__PREC)                            :: t0
+      REAL(__PREC),DIMENSION(:,:),POINTER     :: xp      !particle positions
+      TYPE(ppm_t_topo),POINTER                :: topology,topologyxy,topologyxyc,topologyz
+      TYPE(ppm_t_equi_mesh)                   :: mesh!!,meshtmp1,meshtmp2 !@
+      INTEGER ,DIMENSION(__DIM)               :: indl,indu
+      INTEGER,PARAMETER                       :: MK = __PREC
+      REAL(__PREC),PARAMETER                  :: PI=ACOS(-1.0_MK) !@ use ppm pi
+      !factor for the Green's function, including FFT normalization
+      REAL(__PREC)                            :: normfac
+      INTEGER                                 :: i,j,k
+      INTEGER                                 :: kx,ky,kz
+      INTEGER                                 :: isubl,isub
+      INTEGER,DIMENSION(__DIM*2)              :: bcdef
+      INTEGER                                 :: assigning
+      INTEGER                                 :: decomposition
+      INTEGER,SAVE                            :: ttopoid
+      INTEGER                                 :: tmeshid
+      REAL(__PREC)                            :: dx,dy,dz
+      REAL(__PREC)                            :: Lx2,Ly2,Lz2
+
+      REAL(__PREC),DIMENSION(__DIM)           :: tmpmin,tmpmax
+
+      !-------------------------------------------------------------------------
+      ! Initialise routine
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_poisson_init_predef',t0,info)
+
+      !-------------------------------------------------------------------------
+      ! Investigate optional arguments, setup routine accordingly
+      ! !@ Also check if the input/output and derivatives match
+      !-------------------------------------------------------------------------
+      IF (green .EQ. ppm_poisson_grn_pois_per) THEN
+        ppmpoisson%case  = ppm_poisson_grn_pois_per
+      ELSE IF (green .EQ. ppm_poisson_grn_pois_fre) THEN
+        ppmpoisson%case  = ppm_poisson_grn_pois_fre
+      ELSE IF (green .EQ. ppm_poisson_grn_reprojec) THEN
+        ppmpoisson%case  = ppm_poisson_grn_reprojec
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      ! Get topology and mesh values
+      !-------------------------------------------------------------------------
+      CALL ppm_topo_get(topoid,topology,info)
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank,'ppm_poisson_init_predef','Failed to get topology.',isub)
+        GOTO 9999
+      ENDIF
+      !nsubs = topology%nsublist
+      mesh  = topology%mesh(meshid)
+
+      !-------------------------------------------------------------------------
+      ! Setup mesh sizes for intermediate meshes/topologies
+      !-------------------------------------------------------------------------
+      IF (green .EQ. ppm_poisson_grn_pois_per) THEN
+        !Copy size of global mesh
+        ppmpoisson%nmxy (1) =  mesh%nm(1)
+        ppmpoisson%nmxy (2) =  mesh%nm(2)
+        ppmpoisson%nmxy (3) =  mesh%nm(3)
+        !ppmpoisson%nmxyc(1) = (mesh%nm(1)-1)/2+1
+        ppmpoisson%nmxyc(1) = (mesh%nm(1)) !tmp until meshid>1 works !No keep first component as the size of the complex and real arrays differ - and remember to keep ndataxyc(1) etc
+        ppmpoisson%nmxyc(2) =  mesh%nm(2)
+        ppmpoisson%nmxyc(3) =  mesh%nm(3)
+        !ppmpoisson%nmz  (1) = (mesh%nm(1)-1)/2+1!/2+1 !trying to reduce the number of points in matrix+1
+        ppmpoisson%nmz  (1) = (mesh%nm(1)) !tmp until meshid>1 works
+        ppmpoisson%nmz  (2) =  mesh%nm(2)
+        ppmpoisson%nmz  (3) =  mesh%nm(3)
+        !Inverse of the size of the domain squared
+        Lx2 = 1.0_MK/(topology%max_physd(1)-topology%min_physd(1))**2
+        Ly2 = 1.0_MK/(topology%max_physd(2)-topology%min_physd(2))**2
+        Lz2 = 1.0_MK/(topology%max_physd(3)-topology%min_physd(3))**2
+      ELSE IF (green .EQ. ppm_poisson_grn_pois_fre) THEN !vertex
+        !Copy size of global mesh
+        ppmpoisson%nmxy (1) =  mesh%nm(1)*2
+        ppmpoisson%nmxy (2) =  mesh%nm(2)*2
+        ppmpoisson%nmxy (3) =  mesh%nm(3)*2
+        !ppmpoisson%nmxyc(1) = (mesh%nm(1)-1)/2+1
+        ppmpoisson%nmxyc(1) = (mesh%nm(1)*2) !tmp until meshid>1 works !No keep first component as the size of the complex and real arrays differ - and remember to keep ndataxyc(1) etc
+        ppmpoisson%nmxyc(2) =  mesh%nm(2)*2
+        ppmpoisson%nmxyc(3) =  mesh%nm(3)*2
+        !ppmpoisson%nmz  (1) = (mesh%nm(1)-1)/2+1!/2+1 !trying to reduce the number of points in matrix+1
+        ppmpoisson%nmz  (1) = (mesh%nm(1)*2) !tmp until meshid>1 works
+        ppmpoisson%nmz  (2) =  mesh%nm(2)*2
+        ppmpoisson%nmz  (3) =  mesh%nm(3)*2
+        !Determine the grid spacing !vertex
+        dx = (topology%max_physd(1)-topology%min_physd(1))/(mesh%nm(1)-1)
+        dy = (topology%max_physd(2)-topology%min_physd(2))/(mesh%nm(2)-1)
+        dz = (topology%max_physd(3)-topology%min_physd(3))/(mesh%nm(3)-1)
+        !maybe they should look like this: - no I think not for declaring the Greens function - after all the above dx is the value we have
+        !dx = (topology%max_physd(1)-topology%min_physd(1))/(mesh%nm(1))
+        !dy = (topology%max_physd(2)-topology%min_physd(2))/(mesh%nm(2))
+        !dz = (topology%max_physd(3)-topology%min_physd(3))/(mesh%nm(3))
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      ! Create temporary derivation arrays if necessary
+      ! or spectral scaling coefficients
+      !-------------------------------------------------------------------------
+      IF (PRESENT(derive)) THEN
+        IF ((      derive .EQ. ppm_poisson_drv_curl_fd2  &
+          &  .OR.  derive .EQ. ppm_poisson_drv_curl_fd4)) THEN
+          ppmpoisson%derivatives = derive
+          ALLOCATE(ppmpoisson%drv_vr(LBOUND(fieldout,1):UBOUND(fieldout,1),&
+                                   & LBOUND(fieldout,2):UBOUND(fieldout,2),&
+                                   & LBOUND(fieldout,3):UBOUND(fieldout,3),&
+                                   & LBOUND(fieldout,4):UBOUND(fieldout,4),&
+                                   & LBOUND(fieldout,5):UBOUND(fieldout,5)))
+        !IF ((      derive .EQ. ppm_poisson_drv_curl_fd2  &
+          !&  .OR.  derive .EQ. ppm_poisson_drv_curl_fd4) &
+          !&  .AND. ppmpoisson%case .EQ. ppm_poisson_grn_pois_per) THEN
+          !ppmpoisson%derivatives = derive
+          !ALLOCATE(ppmpoisson%drv_vr(LBOUND(fieldout,1):UBOUND(fieldout,1),&
+                                   !& LBOUND(fieldout,2):UBOUND(fieldout,2),&
+                                   !& LBOUND(fieldout,3):UBOUND(fieldout,3),&
+                                   !& LBOUND(fieldout,4):UBOUND(fieldout,4),&
+                                   !& LBOUND(fieldout,5):UBOUND(fieldout,5)))
+        !ELSE IF ((      derive .EQ. ppm_poisson_drv_curl_fd2  &
+          !&  .OR.  derive .EQ. ppm_poisson_drv_curl_fd4) &
+          !&  .AND. ppmpoisson%case .EQ. ppm_poisson_grn_pois_fre) THEN
+          !ppmpoisson%derivatives = derive
+          !ALLOCATE(ppmpoisson%drv_vr(LBOUND(fieldout,1):UBOUND(fieldout,1),&
+                                   !& LBOUND(fieldout,2):UBOUND(fieldout,2),&
+                                   !& LBOUND(fieldout,3):UBOUND(fieldout,3),&
+                                   !& LBOUND(fieldout,4):UBOUND(fieldout,4),&
+                                   !& LBOUND(fieldout,5):UBOUND(fieldout,5)))
+        ELSE IF (derive .EQ. ppm_poisson_drv_curl_sp) THEN
+          ppmpoisson%normkx = 2*PI/(topology%max_physd(1)-topology%min_physd(1))
+          ppmpoisson%normky = 2*PI/(topology%max_physd(2)-topology%min_physd(2))
+          ppmpoisson%normkz = 2*PI/(topology%max_physd(3)-topology%min_physd(3))
+          ppmpoisson%derivatives = ppm_poisson_drv_curl_sp
+        ELSE IF (derive .EQ. ppm_poisson_drv_none) THEN
+          ppmpoisson%derivatives = ppm_poisson_drv_none
+        ELSE
+          CALL ppm_write(ppm_rank,'ppm_poisson_init_predef','Undefined derivation input.',isub)
+          GOTO 9999
+        ENDIF
+      ELSE
+        ppmpoisson%derivatives = ppm_poisson_drv_none
+      ENDIF
+
+
+
+      !-------------------------------------------------------------------------
+      ! Create new slab topology !@sofar periodic
+      !-------------------------------------------------------------------------
+      ttopoid = 0
+      tmeshid = -1
+      decomposition       = ppm_param_decomp_xy_slab
+      assigning           = ppm_param_assign_internal
+      IF (ppmpoisson%case .EQ. ppm_poisson_grn_pois_per) THEN
+        bcdef               = ppm_param_bcdef_periodic
+      ELSE IF (ppmpoisson%case .EQ. ppm_poisson_grn_pois_fre) THEN
+        bcdef               = ppm_param_bcdef_freespace
+      ENDIF
+      tmpmin              = topology%min_physd
+      tmpmax              = topology%max_physd
+      !!tmpmin2             = topology%min_physd
+      !!tmpmax2             = topology%max_physd
+
+      CALL ppm_mktopo(ttopoid,tmeshid,xp,0,&
+      & decomposition,assigning,&
+      !& topology%min_physd,topology%max_physd,bcdef,&
+      & tmpmin,tmpmax,bcdef,&
+      & __ZEROSI,ppmpoisson%costxy,ppmpoisson%istartxy,ppmpoisson%ndataxy,&
+      & ppmpoisson%nmxy,info)
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank,'ppm_poisson_init_predef','Failed to create xy-topology.',isub)
+        GOTO 9999
+      ENDIF
+      ppmpoisson%topoidxy = ttopoid
+      ppmpoisson%meshidxy = tmeshid
+
+      !-------------------------------------------------------------------------
+      ! Create complex slab mesh
+      ! !@ not used until meshid>1 works
+      !-------------------------------------------------------------------------
+      ttopoid = ppmpoisson%topoidxy
+      tmeshid = -1
+      CALL ppm_mesh_define(ttopoid,tmeshid,&
+      & ppmpoisson%nmxy,ppmpoisson%istartxyc,ppmpoisson%ndataxyc,info) !@nmxyC
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank,'ppm_poisson_init_predef','Failed to create complex xy mesh definition.',isub)
+        GOTO 9999
+      ENDIF
+      ppmpoisson%meshidxyc = tmeshid
+      !write(*,*) ppmpoisson%meshidxy,tmeshid,ttopoid,ppmpoisson%meshidxyc
+      !!write(*,*) ppmpoisson%istartxyc,ppmpoisson%ndataxyc
+
+
+      !-------------------------------------------------------------------------
+      ! Create new pencil topology !@sofar periodic
+      !-------------------------------------------------------------------------
+      ttopoid = 0
+      tmeshid = -1
+      IF (ppmpoisson%case .EQ. ppm_poisson_grn_pois_per) THEN
+        bcdef               = ppm_param_bcdef_periodic
+      ELSE IF (ppmpoisson%case .EQ. ppm_poisson_grn_pois_fre) THEN
+        bcdef               = ppm_param_bcdef_freespace
+      ENDIF
+      assigning       = ppm_param_assign_internal
+      decomposition   = ppm_param_decomp_zpencil
+      !tmpmin              = topology%min_physd
+      !tmpmax              = topology%max_physd
+
+      CALL ppm_mktopo(ttopoid,tmeshid,xp,0,&
+      & decomposition,assigning,&
+      !& topology%min_physd,topology%max_physd,bcdef,&
+      & tmpmin,tmpmax,bcdef,&
+      & __ZEROSI,ppmpoisson%costz,ppmpoisson%istartz,ppmpoisson%ndataz,&
+      & ppmpoisson%nmz,info)
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank,'ppm_poisson_init_predef','Failed to create z-topology.',isub)
+        GOTO 9999
+      ENDIF
+      ppmpoisson%topoidz = ttopoid
+      ppmpoisson%meshidz = tmeshid
+
+      !-------------------------------------------------------------------------
+      ! Get the new topologies (slabs and pencils)
+      !-------------------------------------------------------------------------
+      CALL ppm_topo_get(ppmpoisson%topoidxy,topologyxy,info)
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank,'ppm_poisson_init_predef','Failed to get xy topology.',isub)
+        GOTO 9999
+      ENDIF
+
+      !!CALL ppm_topo_get(ppmpoisson%topoidxyc,topologyxyc,info)
+      !!IF (info .NE. 0) THEN
+        !!CALL ppm_write(ppm_rank,'ppm_poisson_init_predef','Failed to get complex xy topology.',isub)
+        !!GOTO 9999
+      !!ENDIF
+
+      CALL ppm_topo_get(ppmpoisson%topoidz,topologyz,info)
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank,'ppm_poisson_init_predef','Failed to get z topology.',isub)
+        GOTO 9999
+      ENDIF
+
+
+      !-------------------------------------------------------------------------
+      ! Copy data to ppm_poisson type
+      !-------------------------------------------------------------------------
+      ppmpoisson%nsublistxy  = topologyxy %nsublist
+      !!ppmpoisson%nsublistxyc = topologyxyc%nsublist
+      ppmpoisson%nsublistz   = topologyz  %nsublist
+
+      ALLOCATE(ppmpoisson%isublistxy (ppmpoisson%nsublistxy))
+      !!ALLOCATE(ppmpoisson%isublistxyc(ppmpoisson%nsublistxyc))
+      ALLOCATE(ppmpoisson%isublistz  (ppmpoisson%nsublistz))
+
+      DO isub=1,ppmpoisson%nsublistxy
+        ppmpoisson%isublistxy(isub)  = topologyxy%isublist(isub)
+      ENDDO
+      !!DO isub=1,ppmpoisson%nsublistxyc
+        !!ppmpoisson%isublistxyc(isub) = topologyxyc%isublist(isub)
+      !!ENDDO
+      DO isub=1,ppmpoisson%nsublistz
+        ppmpoisson%isublistz(isub)   = topologyz%isublist(isub)
+      ENDDO
+
+      !-------------------------------------------------------------------------
+      ! Set and get minimum and maximum indicies of xy slabs
+      !-------------------------------------------------------------------------
+      indl(1) = 1
+      indl(2) = 1
+      indl(3) = 1
+      indu(1) = 0
+      indu(2) = 0
+      indu(3) = 0
+      DO isub=1,ppmpoisson%nsublistxy
+        isubl = ppmpoisson%isublistxy(isub)
+        indu(1) = MAX(indu(1),ppmpoisson%ndataxy(1,isubl))
+        indu(2) = MAX(indu(2),ppmpoisson%ndataxy(2,isubl))
+        indu(3) = MAX(indu(3),ppmpoisson%ndataxy(3,isubl))
+      ENDDO
+
+      !-------------------------------------------------------------------------
+      ! Allocate real xy slabs
+      !-------------------------------------------------------------------------
+      ALLOCATE(ppmpoisson%fldxyr(__DIM,&
+      & indl(1):indu(1),indl(2):indu(2),indl(3):indu(3),&
+      & 1:ppmpoisson%nsublistxy),stat=info)
+
+      !!ALLOCATE(ppmpoisson%fldxyc(__DIM,&
+      !!& indl(1):indu(1),indl(2):indu(2),indl(3):indu(3),&
+      !!& 1:ppmpoisson%nsublistxy),stat=info)
+
+      !-------------------------------------------------------------------------
+      ! Set and get minimum and maximum indicies of COMPLEX xy slabs
+      !-------------------------------------------------------------------------
+      indl(1) = 1
+      indl(2) = 1
+      indl(3) = 1
+      indu(1) = 0
+      indu(2) = 0
+      indu(3) = 0
+      DO isub=1,ppmpoisson%nsublistxy
+        isubl = ppmpoisson%isublistxy(isub)
+        indu(1) = MAX(indu(1),ppmpoisson%ndataxyc(1,isubl))
+        indu(2) = MAX(indu(2),ppmpoisson%ndataxyc(2,isubl))
+        indu(3) = MAX(indu(3),ppmpoisson%ndataxyc(3,isubl))
+      ENDDO
+
+      !-------------------------------------------------------------------------
+      ! Allocate real and complex xy slabs
+      !-------------------------------------------------------------------------
+      !!ALLOCATE(ppmpoisson%fldxyr(__DIM,&
+      !!& indl(1):indu(1),indl(2):indu(2),indl(3):indu(3),&
+      !!& 1:ppmpoisson%nsublistxy),stat=info)
+!!
+      ALLOCATE(ppmpoisson%fldxyc(__DIM,&
+      & indl(1):indu(1),indl(2):indu(2),indl(3):indu(3),&
+      & 1:ppmpoisson%nsublistxy),stat=info)
+
+      !-------------------------------------------------------------------------
+      ! Set and get minimum and maximum indicies of z pencils
+      !-------------------------------------------------------------------------
+      indl(1) = 1
+      indl(2) = 1
+      indl(3) = 1
+      indu(1) = 0
+      indu(2) = 0
+      indu(3) = 0
+      DO isub=1,ppmpoisson%nsublistz
+        isubl = ppmpoisson%isublistz(isub)
+        indu(1) = MAX(indu(1),ppmpoisson%ndataz(1,isubl))
+        indu(2) = MAX(indu(2),ppmpoisson%ndataz(2,isubl))
+        indu(3) = MAX(indu(3),ppmpoisson%ndataz(3,isubl))
+      ENDDO
+
+      !-------------------------------------------------------------------------
+      ! Allocate two complex z pencils + Greens fcn array !@check return vars.
+      !-------------------------------------------------------------------------
+      ALLOCATE(ppmpoisson%fldzc1(__DIM,&
+      & indl(1):indu(1),indl(2):indu(2),indl(3):indu(3),&
+      & 1:ppmpoisson%nsublistz),stat=info)
+
+      ALLOCATE(ppmpoisson%fldzc2(__DIM,&
+      & indl(1):indu(1),indl(2):indu(2),indl(3):indu(3),&
+      & 1:ppmpoisson%nsublistz),stat=info)
+
+      !-------------------------------------------------------------------------
+      ! The complex Greens function is always kept on the z-pencil topology
+      !-------------------------------------------------------------------------
+      IF (green .EQ. ppm_poisson_grn_pois_per) THEN
+        ALLOCATE(ppmpoisson%fldgrnr(&
+        & indl(1):indu(1),indl(2):indu(2),indl(3):indu(3),&
+        & 1:ppmpoisson%nsublistz),stat=info)
+      ELSE IF (green .EQ. ppm_poisson_grn_pois_fre) THEN
+        !!!The z-dimension is defined to full extent for the real temporary
+        !!!Greens function array
+        !!ALLOCATE(ppmpoisson%fldgrnr(&
+        !!& indl(1):indu(1),indl(2):indu(2),indl(3):((indu(3)-1)*2),&
+        !!& 1:ppmpoisson%nsublistz),stat=info)
+        ALLOCATE(ppmpoisson%fldgrnc(&
+        & indl(1):indu(1),indl(2):indu(2),indl(3):indu(3),&
+        & 1:ppmpoisson%nsublistz),stat=info)
+      ENDIF
+
+      !-------------------------------------------------------------------------
+      ! Set up xy FFT plans
+      !-------------------------------------------------------------------------
+      CALL ppm_fft_forward_2d(ppmpoisson%topoidxy,ppmpoisson%meshidxy,&
+      & ppmpoisson%planfxy,ppmpoisson%fldxyr,&
+      & ppmpoisson%fldxyc,info)
+
+      CALL ppm_fft_backward_2d(ppmpoisson%topoidxy,ppmpoisson%meshidxy,&
+      & ppmpoisson%planbxy,ppmpoisson%fldxyc,&
+      & ppmpoisson%fldxyr,info)
+
+      !-------------------------------------------------------------------------
+      ! Set up z FFT plans
+      !-------------------------------------------------------------------------
+      CALL ppm_fft_forward_1d(ppmpoisson%topoidz,ppmpoisson%meshidz,&
+      & ppmpoisson%planfz,ppmpoisson%fldzc1,&
+      & ppmpoisson%fldzc2,info)
+
+      CALL ppm_fft_backward_1d(ppmpoisson%topoidz,ppmpoisson%meshidz,&
+      & ppmpoisson%planbz,ppmpoisson%fldzc2,&
+      & ppmpoisson%fldzc1,info)
+
+      !-------------------------------------------------------------------------
+      ! Compute Greens function. Analytic, periodic
+      !
+      ! (d2_/dx2 + d2_/dy2 + d2_/dz2)psi = -omega     =>
+      ! -4*pi2(kx2 + ky2 + kz2)PSI       = -OMEGA     =>
+      ! PSI                              = 1/(4*pi2)*1/(kx2 + ky2 + kz2)OMEGA
+      !-------------------------------------------------------------------------
+      IF (green .EQ. ppm_poisson_grn_pois_per) THEN
+        ! Scaling the spectral coefficients... one minus is due to (i*k)^2 ... how about one due to Poisson?
+        normfac = 1.0_MK/(4.0_MK*PI*PI * &
+                !and normalisation of FFTs
+                & REAL((ppmpoisson%nmz(1)-1)*(ppmpoisson%nmz(2)-1)*(ppmpoisson%nmz(3)-1),MK))
+        DO isub=1,ppmpoisson%nsublistz
+          isubl=ppmpoisson%isublistz(isub)
+          DO k=1,ppmpoisson%ndataz(3,isubl)
+            DO j=1,ppmpoisson%ndataz(2,isubl)
+              DO i=1,ppmpoisson%ndataz(1,isubl)
+                kx = i-1 + (ppmpoisson%istartz(1,isubl)-1)
+                ky = j-1 + (ppmpoisson%istartz(2,isubl)-1)
+                kz = k-1 + (ppmpoisson%istartz(3,isubl)-1)
+                !The integer division depends on mesh%nm to include N+1 points:
+                !This is a nasty way to do this but it is only done once so...:
+                !(we subtract nm '-1' as not all points are included (periodic))
+                IF (kx .GT. (ppmpoisson%nmz(1)-1)/2) kx = kx-(ppmpoisson%nmz(1)-1)
+                IF (ky .GT. (ppmpoisson%nmz(2)-1)/2) ky = ky-(ppmpoisson%nmz(2)-1)
+                IF (kz .GT. (ppmpoisson%nmz(3)-1)/2) kz = kz-(ppmpoisson%nmz(3)-1)
+                ppmpoisson%fldgrnr(i,j,k,isub) = &
+                      & normfac/(REAL(kx*kx,__PREC)*Lx2 &
+                      &        + REAL(ky*ky,__PREC)*Ly2 &
+                      &        + REAL(kz*kz,__PREC)*Lz2)
+                !Take care of singularity
+                !This is nasty as well
+                IF ((kx*kx+ky*ky+kz*kz) .EQ. 0) THEN
+                  ppmpoisson%fldgrnr(i,j,k,isub) = 0.0_MK
+                ENDIF
+              ENDDO
+            ENDDO
+          ENDDO
+        ENDDO
+
+      !-------------------------------------------------------------------------
+      ! Compute real free space Greens function. Analytic
+      ! The Greens function is initialised temporarily in the real xy slabs,
+      ! then FFTed in those directions, mapped to z-pencils, FFTed in z and
+      ! finally copied to ppmpoisson%fldgrnc. The real xy slabs have already
+      ! been setup for FFTs etc so they offer a convenient container for the
+      ! FFTing the Green's function instead of setting up the whole apparatus
+      ! for this one-time affair.
+      ! These loops must run over the padded(extended) domain thus %ndataxy
+      ! \nabla \Psi = -\omega
+      ! The Greens function is 1/4piR (R is distance to origo) and includes the
+      ! minus of the RHS
+      !-------------------------------------------------------------------------
+      ELSE IF (green .EQ. ppm_poisson_grn_pois_fre) THEN
+        !-----------------------------------------------------------------------
+        ! First initialise the real Green's function
+        !@alternatively this could come from as input
+        !-----------------------------------------------------------------------
+        !@write(*,*) 'what the fuck?'
+        !there should NOT be a minus here since this Greens function takes
+        !the minus of the Poisson equation into account
+        normfac = 1.0_MK/(4.0_MK*PI* &
+        !remembering FFT normalization of ALL points: !vertex
+        & REAL((ppmpoisson%nmxy(1))*(ppmpoisson%nmxy(2))*(ppmpoisson%nmxy(3)),MK))*dx*dy*dz
+        !& REAL((ppmpoisson%nmxy(1))*(ppmpoisson%nmxy(2))*(ppmpoisson%nmxy(3)),MK)& !this is the correct normalization to bring one field back and forth.
+        !remembering FFT normalization of ALL points: !vertex
+        !!& REAL((ppmpoisson%nmxy(1))*(ppmpoisson%nmxy(2))*(ppmpoisson%nmxy(3)),MK)& !this should be correct normalization. When back and forth transforming the green's function is correct
+        !!& *REAL((ppmpoisson%nmxy(1))*(ppmpoisson%nmxy(2))*(ppmpoisson%nmxy(3))/8,MK)) !this line is probably not necessary
+        !!!& *REAL((ppmpoisson%nmxy(1))*(ppmpoisson%nmxy(2))*(ppmpoisson%nmxy(3)),MK)) !this line is probably not necessary
+        !@write(*,*) ppmpoisson%nmxy, 'johannes'
+        DO isub=1,ppmpoisson%nsublistxy
+          isubl=ppmpoisson%isublistxy(isub)
+          DO k=1,ppmpoisson%ndataxy(3,isubl)
+            DO j=1,ppmpoisson%ndataxy(2,isubl)
+              DO i=1,ppmpoisson%ndataxy(1,isubl)
+                kx = i-1 + (ppmpoisson%istartxy(1,isubl)-1)
+                ky = j-1 + (ppmpoisson%istartxy(2,isubl)-1)
+                kz = k-1 + (ppmpoisson%istartxy(3,isubl)-1)
+                !The integer division depends on mesh%nm to include N+1 points:
+                !This is a nasty way to do this but it is only done once so...:
+                !(we subtract all nmxy as all points are included in fresspace)
+                IF (kx .GT. (ppmpoisson%nmxy(1)-2)/2) kx = kx-(ppmpoisson%nmxy(1))
+                IF (ky .GT. (ppmpoisson%nmxy(2)-2)/2) ky = ky-(ppmpoisson%nmxy(2))
+                IF (kz .GT. (ppmpoisson%nmxy(3)-2)/2) kz = kz-(ppmpoisson%nmxy(3))
+                ppmpoisson%fldxyr(1,i,j,k,isub) = &
+                        & normfac/(SQRT( REAL(kx*kx,__PREC)*dx*dx+ &
+                        &                REAL(ky*ky,__PREC)*dy*dy+ &
+                        &                REAL(kz*kz,__PREC)*dz*dz))
+                ppmpoisson%fldxyr(2,i,j,k,isub) = 0.0_MK
+                ppmpoisson%fldxyr(3,i,j,k,isub) = 0.0_MK
+                !Take care of singularity
+                !This is nasty as well
+                IF ((kx*kx+ky*ky+kz*kz) .EQ. 0) THEN
+                  !ppmpoisson%fldxyr(1,i,j,k,isub) = 2.0_MK*normfac/(dx) - normfac/(2.0_MK*dx)
+                  !ppmpoisson%fldxyr(1,i,j,k,isub) = normfac/(dx)
+                  ppmpoisson%fldxyr(1,i,j,k,isub) = 0.0_MK
+                  !ppmpoisson%fldxyr(1,i,j,k,isub) = 2.0_MK*normfac/(dx) - normfac/(2.0_MK*dx) + 1.0_MK
+                ENDIF
+              ENDDO
+            ENDDO
+          ENDDO
+        ENDDO
+        !-------------------------------------------------------------------------
+        ! FOURIER TRANSFORM AND MAP GALORE
+        ! @this should be updated when meshid>1 works
+        ! This part should be used both for freespace and a custom Greens function
+        !-------------------------------------------------------------------------
+        !-----------------------------------------------------------------------
+        ! Do slab FFT (XY) - using the non-reduced topology !@what does this mean
+        !-----------------------------------------------------------------------
+        CALL ppm_fft_execute_2d(ppmpoisson%topoidxy,&
+        & ppmpoisson%meshidxy, ppmpoisson%planfxy, &
+        & ppmpoisson%fldxyr, ppmpoisson%fldxyc, &
+        & info)
+        !-----------------------------------------------------------------------
+        ! Map to the pencils (Z)
+        !-----------------------------------------------------------------------
+        !Initialise
+        CALL ppm_map_field_global(&
+        & ppmpoisson%topoidxy, &
+        & ppmpoisson%topoidz, &
+        !& ppmpoisson%meshidxyc, & !@to be used when meshid>1 works
+        & ppmpoisson%meshidxy, &
+        & ppmpoisson%meshidz,info)
+        IF (info .NE. 0) THEN
+          CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to initialise field mapping.',isub)
+          GOTO 9999
+        ENDIF
+
+        !Push the data
+        CALL ppm_map_field_push(&
+        & ppmpoisson%topoidxy, &
+        & ppmpoisson%meshidxyc,ppmpoisson%fldxyc,__NCOM,info) !@I believe it should say meshidxy here until meshid>1 works. Then the following line will be used
+        !& ppmpoisson%meshidxyc,ppmpoisson%fldxyc,__NCOM,info)!@to be used when meshid>1 works
+        IF (info .NE. 0) THEN
+          CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to push vector field.',isub)
+          GOTO 9999
+        ENDIF
+
+        !Send
+        CALL ppm_map_field_send(info)
+        IF (info .NE. 0) THEN
+          CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to send field.',isub)
+          GOTO 9999
+        ENDIF
+
+        !Retrieve
+        CALL ppm_map_field_pop(&
+        & ppmpoisson%topoidz, &
+        & ppmpoisson%meshidz,ppmpoisson%fldzc1, &
+        & __NCOM,__ZEROSI,info)
+        IF (info .NE. 0) THEN
+          CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to pop vector field.',isub)
+          GOTO 9999
+        ENDIF
+
+        !-----------------------------------------------------------------------
+        ! Do pencil FFT (Z)
+        !-----------------------------------------------------------------------
+        CALL ppm_fft_execute_1d(ppmpoisson%topoidz,&
+        & ppmpoisson%meshidz, ppmpoisson%planfz, &
+        & ppmpoisson%fldzc1, ppmpoisson%fldzc2, &
+        & info)
+
+        !-----------------------------------------------------------------------
+        ! Copy first component of the Fourier transformed vector to fldgrnc
+        !-----------------------------------------------------------------------
+        DO isub=1,ppmpoisson%nsublistz
+          isubl=ppmpoisson%isublistz(isub)
+          DO k=1,ppmpoisson%ndataz(3,isubl)
+            DO j=1,ppmpoisson%ndataz(2,isubl)
+              DO i=1,ppmpoisson%ndataz(1,isubl)
+                ppmpoisson%fldgrnc(i,j,k,isub) = ppmpoisson%fldzc2(1,i,j,k,isub)!+1.0_MK
+              ENDDO
+            ENDDO
+          ENDDO
+        ENDDO
+
+        !@Deallocate field green r NOPE!
+      END IF
+
+      !-------------------------------------------------------------------------
+      ! Or alternatively FFT real Green from input
+      !-------------------------------------------------------------------------
+
+      !-------------------------------------------------------------------------
+      ! Deallocate fields? !@
+      !-------------------------------------------------------------------------
+
+      !-------------------------------------------------------------------------
+      ! Return
+      !-------------------------------------------------------------------------
+ 9999 CONTINUE
+      CALL substop('ppm_poisson_init_predef',t0,info)
+      RETURN
+
+      END SUBROUTINE __ROUTINE
+
diff --git a/src/poisson/ppm_poisson_solve.f b/src/poisson/ppm_poisson_solve.f
new file mode 100644
index 0000000..585fc0f
--- /dev/null
+++ b/src/poisson/ppm_poisson_solve.f
@@ -0,0 +1,837 @@
+      !-------------------------------------------------------------------------
+      ! ppm_poisson_solve.f90
+      !-------------------------------------------------------------------------
+      !@mapping calls can be cleaned up
+      !-------------------------------------------------------------------------
+!!#define __ROUTINE ppm_poisson_solve
+!!#define __DIM  3
+!!#define __NCOM  3
+!!#define __ZEROSI (/0,0,0/)
+!#define __NOPE
+      SUBROUTINE __ROUTINE(topoid,meshid,ppmpoisson,fieldin,fieldout,gstw,info,&
+                         & tmpcase)
+
+      USE ppm_module_map_field
+      USE ppm_module_map_field_global
+      USE ppm_module_map
+
+
+      IMPLICIT NONE
+      !-------------------------------------------------------------------------
+      ! Arguments
+      !-------------------------------------------------------------------------
+      INTEGER, INTENT(IN)                                         :: topoid
+      INTEGER, INTENT(IN)                                         :: meshid
+      TYPE(ppm_poisson_plan),INTENT(INOUT)                        :: ppmpoisson
+      !REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER,INTENT(INOUT)     :: fieldin
+      REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: fieldin
+      !REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER,INTENT(INOUT)     :: fieldout
+      REAL(__PREC),DIMENSION(:,:,:,:,:),POINTER                   :: fieldout
+      INTEGER,DIMENSION(__DIM),INTENT(IN)                         :: gstw
+      INTEGER, INTENT(OUT)                                        :: info
+      INTEGER,OPTIONAL,INTENT(IN)                                 :: tmpcase
+
+      !-------------------------------------------------------------------------
+      ! Local variables
+      !-------------------------------------------------------------------------
+      INTEGER,PARAMETER                 :: MK = __PREC
+      REAL(__PREC)                      :: t0
+      INTEGER                           :: isub,isubl
+      INTEGER                           :: i,j,k
+      INTEGER                           :: info2
+      INTEGER                           :: presentcase
+      REAL(__PREC)                      :: wdotk
+      INTEGER                           :: gi,gj,gk
+      REAL(__PREC)                      :: kx,ky,kz
+      REAL(__PREC)                      :: phix,phiy,phiz
+      REAL(__PREC)                      :: normfac
+#ifndef __NOPE
+INTEGER                           :: trank !@
+trank =0
+#endif
+      !-------------------------------------------------------------------------
+      ! Initialise routine
+      !-------------------------------------------------------------------------
+      CALL substart('ppm_poisson_solve',t0,info)
+
+      !-------------------------------------------------------------------------
+      ! Check if we run a different/temporary case
+      !-------------------------------------------------------------------------
+      IF (PRESENT(tmpcase)) THEN
+         presentcase = tmpcase
+      ELSE
+         presentcase = ppmpoisson%case
+      ENDIF
+!@write(*,*) 'solving ....  1', ppm_rank
+
+      !-------------------------------------------------------------------------
+      !@ Perhaps check if ghostlayer suffices for a given fd stencil
+      !-------------------------------------------------------------------------
+
+
+      !-------------------------------------------------------------------------
+      ! Perhaps allocate (and deallocate) arrays !@
+      !-------------------------------------------------------------------------
+#ifdef __VARMESH
+  !@tmp only works for one subdomain (not parallel)
+        write(*,*) 'fieldin', ppm_rank
+        DO isub=1,ppmpoisson%nsublistxy
+          isubl=ppmpoisson%isublistxy(isub)
+          DO k=1,ppmpoisson%ndataxy(3,isubl)/2-1
+            write(*,*) 'z',k
+            DO i=1,ppmpoisson%ndataxy(1,isubl)/2-1
+              DO j=1,ppmpoisson%ndataxy(2,isubl)/2-1
+                write(*,'(A,E12.4,A,$)') '  (',fieldin(1,i,j,k,isub),')'
+              END DO
+              write(*,*)
+            END DO
+          END DO
+        END DO
+#endif
+        !-----------------------------------------------------------------------
+        ! Set the real xy slabs 0 (part of the 0 padding) for free-space
+        !@ free-space calculations and reprojection may cause problems !why?
+        !-----------------------------------------------------------------------
+        IF (presentcase .EQ. ppm_poisson_grn_pois_fre) THEN
+          ppmpoisson%fldxyr = 0.0_MK
+        ENDIF
+        !-----------------------------------------------------------------------
+        ! Map data globally to the slabs (XY)
+        ! This is where the vorticity is extended and padded with 0 for free-space
+        !-----------------------------------------------------------------------
+        !Initialise
+        CALL ppm_map_field_global(&
+        & topoid, &
+        & ppmpoisson%topoidxy, &
+        & meshid, &
+        & ppmpoisson%meshidxy,info)
+        IF (info .NE. 0) THEN
+          CALL ppm_write(ppm_rank,'ppm_poisson_solve','Failed to initialise field mapping.',info2)
+          GOTO 9999
+        ENDIF
+
+        !Push the data
+        CALL ppm_map_field_push(&
+        & topoid, &
+        & meshid,fieldin,__NCOM,info)
+        IF (info .NE. 0) THEN
+          CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to push vector field.',info2)
+          GOTO 9999
+        ENDIF
+
+        !Send
+        CALL ppm_map_field_send(info)
+        IF (info .NE. 0) THEN
+          CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to send field.',info2)
+          GOTO 9999
+        ENDIF
+
+        !Retrieve
+        CALL ppm_map_field_pop(&
+        & ppmpoisson%topoidxy, &
+        & ppmpoisson%meshidxy,ppmpoisson%fldxyr, &
+        & __NCOM,__ZEROSI,info)
+        IF (info .NE. 0) THEN
+          CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to pop vector field.',info2)
+          GOTO 9999
+        ENDIF
+!@write(*,*) 'solving ....  2', ppm_rank
+#ifdef __VARMESH
+!@tmp
+      write(*,*) 'fldxyr', ppm_rank
+      DO isub=1,ppmpoisson%nsublistxy
+        isubl=ppmpoisson%isublistxy(isub)
+        DO k=1,ppmpoisson%ndataxy(3,isubl)-1
+          write(*,*) 'z',k
+          DO i=1,ppmpoisson%ndataxy(1,isubl)-1
+            DO j=1,ppmpoisson%ndataxy(2,isubl)-1
+              write(*,'(A,E12.4,A,$)') '  (',ppmpoisson%fldxyr(1,i,j,k,isub),')'
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+#endif
+
+      !-----------------------------------------------------------------------
+      ! Do slab FFT (XY) - use the non-reduced topology !@what does this mean
+      !-----------------------------------------------------------------------
+      CALL ppm_fft_execute_2d(ppmpoisson%topoidxy,&
+      & ppmpoisson%meshidxy, ppmpoisson%planfxy, &
+      & ppmpoisson%fldxyr, ppmpoisson%fldxyc, &
+      & info)
+!@write(*,*) 'solving ....  3', ppm_rank
+
+#ifdef __NOPE
+      if (ppm_rank .EQ. trank)   THEN
+      write(*,*) 'Rfftx12', ppm_rank
+      DO isub=1,ppmpoisson%nsublistxy
+        isubl=ppmpoisson%isublistxy(isub)
+        DO k=1,ppmpoisson%ndataxy(3,isubl)-1
+          write(*,*) 'z',k
+            DO i=1,ppmpoisson%ndataxy(1,isubl)-1
+          DO j=1,ppmpoisson%ndataxy(2,isubl)-1
+              write(*,'(A,E12.4,A,$)') '  (',ppmpoisson%fldxyr(1,i,j,k,isub),')'
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+      write(*,*) 'Rffty12', ppm_rank
+      DO isub=1,ppmpoisson%nsublistxy
+        isubl=ppmpoisson%isublistxy(isub)
+        DO k=1,ppmpoisson%ndataxy(3,isubl)-1
+          write(*,*) 'z',k
+            DO i=1,ppmpoisson%ndataxy(1,isubl)-1
+          DO j=1,ppmpoisson%ndataxy(2,isubl)-1
+              write(*,'(A,E12.4,A,$)') '  (',ppmpoisson%fldxyr(2,i,j,k,isub),')'
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+      write(*,*) 'Rfftz12', ppm_rank
+      DO isub=1,ppmpoisson%nsublistxy
+        isubl=ppmpoisson%isublistxy(isub)
+        DO k=1,ppmpoisson%ndataxy(3,isubl)-1
+          write(*,*) 'z',k
+            DO i=1,ppmpoisson%ndataxy(1,isubl)-1
+          DO j=1,ppmpoisson%ndataxy(2,isubl)-1
+              write(*,'(A,E12.4,A,$)') '  (',ppmpoisson%fldxyr(3,i,j,k,isub),')'
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+      ENDIF
+#endif
+
+
+#ifdef __NOPE
+      if (ppm_rank .EQ. trank)   THEN
+      write(*,*) 'fftx12', ppm_rank
+      DO isub=1,ppmpoisson%nsublistxy
+        isubl=ppmpoisson%isublistxy(isub)
+        DO k=1,ppmpoisson%ndataxy(3,isubl)-1
+          write(*,*) 'z',k
+            DO i=1,ppmpoisson%ndataxy(1,isubl)-1
+          DO j=1,ppmpoisson%ndataxy(2,isubl)-1
+              write(*,'(A,E12.4,E12.4,A,$)') '  (',ppmpoisson%fldxyc(1,i,j,k,isub),')'
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+      write(*,*) 'ffty12', ppm_rank
+      DO isub=1,ppmpoisson%nsublistxy
+        isubl=ppmpoisson%isublistxy(isub)
+        DO k=1,ppmpoisson%ndataxy(3,isubl)-1
+          write(*,*) 'z',k
+            DO i=1,ppmpoisson%ndataxy(1,isubl)-1
+          DO j=1,ppmpoisson%ndataxy(2,isubl)-1
+              write(*,'(A,E12.4,E12.4,A,$)') '  (',ppmpoisson%fldxyc(2,i,j,k,isub),')'
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+      write(*,*) 'fftz12', ppm_rank
+      DO isub=1,ppmpoisson%nsublistxy
+        isubl=ppmpoisson%isublistxy(isub)
+        DO k=1,ppmpoisson%ndataxy(3,isubl)-1
+          write(*,*) 'z',k
+            DO i=1,ppmpoisson%ndataxy(1,isubl)-1
+          DO j=1,ppmpoisson%ndataxy(2,isubl)-1
+              write(*,'(A,E12.4,E12.4,A,$)') '  (',ppmpoisson%fldxyc(3,i,j,k,isub),')'
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+      ENDIF
+#endif
+!@write(*,*) 'solving ....  4', ppm_rank
+
+      !-----------------------------------------------------------------------
+      ! Map to the pencils (Z)
+      !-----------------------------------------------------------------------
+      !Initialise
+      CALL ppm_map_field_global(&
+      & ppmpoisson%topoidxy, &
+      & ppmpoisson%topoidz, &
+      !& ppmpoisson%meshidxyc, & !@to be used when meshid>1 works
+      & ppmpoisson%meshidxy, &
+      & ppmpoisson%meshidz,info)
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to initialise field mapping.',info2)
+        GOTO 9999
+      ENDIF
+
+      !Push the data
+      CALL ppm_map_field_push(&
+      & ppmpoisson%topoidxy, &
+      & ppmpoisson%meshidxyc,ppmpoisson%fldxyc,__NCOM,info)
+      !& ppmpoisson%meshidxyc,ppmpoisson%fldxyc,__NCOM,info)!@to be used when meshid>1 works
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to push vector field.',info2)
+        GOTO 9999
+      ENDIF
+
+      !Send
+      CALL ppm_map_field_send(info)
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to send field.',info2)
+        GOTO 9999
+      ENDIF
+
+      !Retrieve
+      CALL ppm_map_field_pop(&
+      & ppmpoisson%topoidz, &
+      & ppmpoisson%meshidz,ppmpoisson%fldzc1, &
+      & __NCOM,__ZEROSI,info)
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to pop vector field.',info2)
+        GOTO 9999
+      ENDIF
+!@write(*,*) 'solving ....  5', ppm_rank
+
+      !-----------------------------------------------------------------------
+      ! Do pencil FFT (Z)
+      !-----------------------------------------------------------------------
+      CALL ppm_fft_execute_1d(ppmpoisson%topoidz,&
+      & ppmpoisson%meshidz, ppmpoisson%planfz, &
+      & ppmpoisson%fldzc1, ppmpoisson%fldzc2, &
+      & info)
+
+!@write(*,*) 'solving ....  6', ppm_rank
+#ifdef __NOPE
+      if (ppm_rank .EQ. trank)   THEN
+            write(*,*)
+            write(*,*) !ppmpoisson%fldzc1 = 0.0_MK
+      write(*,*) 'fftx123', ppm_rank
+      DO isub=1,ppmpoisson%nsublistz
+        isubl=ppmpoisson%isublistz(isub)
+        DO k=1,ppmpoisson%ndataz(3,isubl)-1
+          write(*,*) 'z',k
+            DO i=1,ppmpoisson%ndataz(1,isubl)-1
+          DO j=1,ppmpoisson%ndataz(2,isubl)-1
+              write(*,'(A,E12.4,E12.4,A,$)') '  (',ppmpoisson%fldzc2(1,i,j,k,isub),')'
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+      write(*,*) 'ffty123', ppm_rank
+      DO isub=1,ppmpoisson%nsublistz
+        isubl=ppmpoisson%isublistz(isub)
+        DO k=1,ppmpoisson%ndataz(3,isubl)-1
+          write(*,*) 'z',k
+            DO i=1,ppmpoisson%ndataz(1,isubl)-1
+          DO j=1,ppmpoisson%ndataz(2,isubl)-1
+              write(*,'(A,E12.4,E12.4,A,$)') '  (',ppmpoisson%fldzc2(2,i,j,k,isub),')'
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+      write(*,*) 'fftz123', ppm_rank
+      DO isub=1,ppmpoisson%nsublistz
+        isubl=ppmpoisson%isublistz(isub)
+        DO k=1,ppmpoisson%ndataz(3,isubl)-1
+          write(*,*) 'z',k
+            DO i=1,ppmpoisson%ndataz(1,isubl)-1
+          DO j=1,ppmpoisson%ndataz(2,isubl)-1
+              write(*,'(A,E12.4,E12.4,A,$)') '  (',ppmpoisson%fldzc2(3,i,j,k,isub),')'
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+
+      write(*,*)
+      write(*,*)
+      write(*,*) 'green', ppm_rank
+      DO isub=1,ppmpoisson%nsublistz
+        isubl=ppmpoisson%isublistz(isub)
+        DO k=1,ppmpoisson%ndataz(3,isubl)-1
+          write(*,*) 'z',k
+            DO i=1,ppmpoisson%ndataz(1,isubl)-1
+          DO j=1,ppmpoisson%ndataz(2,isubl)-1
+              write(*,'(E12.4,$)') REAL(ppmpoisson%fldgrnr(i,j,k,isub))
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+      ENDIF
+#endif
+!@write(*,*) 'solving ....  7', ppm_rank
+
+      !-----------------------------------------------------------------------
+      ! Apply the periodic Green's function
+      !-----------------------------------------------------------------------
+      IF (presentcase .EQ. ppm_poisson_grn_pois_per) THEN
+        DO isub=1,ppmpoisson%nsublistz
+          isubl=ppmpoisson%isublistz(isub)
+          DO k=1,ppmpoisson%ndataz(3,isubl)
+            DO j=1,ppmpoisson%ndataz(2,isubl)
+              DO i=1,ppmpoisson%ndataz(1,isubl)
+                ppmpoisson%fldzc2(1,i,j,k,isub) = ppmpoisson%fldgrnr( i,j,k,isub)*&
+                                                & ppmpoisson%fldzc2(1,i,j,k,isub)
+                ppmpoisson%fldzc2(2,i,j,k,isub) = ppmpoisson%fldgrnr( i,j,k,isub)*&
+                                                & ppmpoisson%fldzc2(2,i,j,k,isub)
+                ppmpoisson%fldzc2(3,i,j,k,isub) = ppmpoisson%fldgrnr( i,j,k,isub)*&
+                                                & ppmpoisson%fldzc2(3,i,j,k,isub)
+              ENDDO
+            ENDDO
+          ENDDO
+        ENDDO
+      !-----------------------------------------------------------------------
+      ! Apply the free-space Green's function
+      !-----------------------------------------------------------------------
+      ELSE IF (presentcase .EQ. ppm_poisson_grn_pois_fre) THEN
+        DO isub=1,ppmpoisson%nsublistz
+          isubl=ppmpoisson%isublistz(isub)
+          DO k=1,ppmpoisson%ndataz(3,isubl)
+            DO j=1,ppmpoisson%ndataz(2,isubl)
+              DO i=1,ppmpoisson%ndataz(1,isubl)
+                ppmpoisson%fldzc2(1,i,j,k,isub) = ppmpoisson%fldgrnc( i,j,k,isub)*&
+                                                & ppmpoisson%fldzc2(1,i,j,k,isub)
+                ppmpoisson%fldzc2(2,i,j,k,isub) = ppmpoisson%fldgrnc( i,j,k,isub)*&
+                                                & ppmpoisson%fldzc2(2,i,j,k,isub)
+                ppmpoisson%fldzc2(3,i,j,k,isub) = ppmpoisson%fldgrnc( i,j,k,isub)*&
+                                                & ppmpoisson%fldzc2(3,i,j,k,isub)
+                !!ppmpoisson%fldzc2(1,i,j,k,isub) = ppmpoisson%fldgrnc( i,j,k,isub)
+                !!ppmpoisson%fldzc2(2,i,j,k,isub) = ppmpoisson%fldgrnc( i,j,k,isub)
+                !!ppmpoisson%fldzc2(3,i,j,k,isub) = ppmpoisson%fldgrnc( i,j,k,isub)
+              ENDDO
+            ENDDO
+          ENDDO
+        ENDDO
+!@write(*,*) 'solving ....  8', ppm_rank
+      !-----------------------------------------------------------------------
+      ! Spectral derivatives
+      ! normkx, etc contains 2pi/Lx
+      !-----------------------------------------------------------------------
+      IF (ppmpoisson%derivatives .EQ. ppm_poisson_drv_curl_sp .AND.&
+         & (presentcase .EQ. ppm_poisson_grn_pois_per .OR. &
+            presentcase .EQ. ppm_poisson_grn_pois_fre)) THEN
+        write(*,*) 'curl fft style! not working yet though!'
+        !remembering to normalize the FFT
+        normfac = 1.0_MK/ REAL((ppmpoisson%nmz(1)-1)* & !vertex
+                             & (ppmpoisson%nmz(2)-1)* &
+                             & (ppmpoisson%nmz(3)-1),MK)
+        DO isub=1,ppmpoisson%nsublistz
+          isubl=ppmpoisson%isublistz(isub)
+          DO k=1,ppmpoisson%ndataz(3,isubl)
+            gk = k - 1 + (ppmpoisson%istartz(3,isubl)-1)
+            IF (gk .GT. (ppmpoisson%nmz(3)-1)/2) gk = gk-(ppmpoisson%nmz(3)-1)
+            kz = CMPLX(0.0_MK,gk*ppmpoisson%normkz,MK)
+            DO j=1,ppmpoisson%ndataz(2,isubl)
+              gj = j - 1 + (ppmpoisson%istartz(2,isubl)-1)
+              IF (gj .GT. (ppmpoisson%nmz(2)-1)/2) gj = gj-(ppmpoisson%nmz(2)-1)
+              ky = CMPLX(0.0_MK,gj*ppmpoisson%normky,MK)
+              DO i=1,ppmpoisson%ndataz(1,isubl)
+                gi = i - 1 + (ppmpoisson%istartz(1,isubl)-1)
+                IF (gi .GT. (ppmpoisson%nmz(1)-1)/2) gi = gi-(ppmpoisson%nmz(1)-1)
+                kx = CMPLX(0.0_MK,gi*ppmpoisson%normkx,MK)
+
+                phix = ppmpoisson%fldzc2(1,i,j,k,isub)
+                phiy = ppmpoisson%fldzc2(2,i,j,k,isub)
+                phiz = ppmpoisson%fldzc2(3,i,j,k,isub)
+
+                !maybe normfac on kx,ky,kz?
+                ppmpoisson%fldzc2(1,i,j,k,isub) = normfac*(ky*phiz-kz*phiy)
+                ppmpoisson%fldzc2(2,i,j,k,isub) = normfac*(kz*phix-kx*phiz)
+                ppmpoisson%fldzc2(3,i,j,k,isub) = normfac*(kx*phiy-ky*phix)
+              ENDDO
+            ENDDO
+          ENDDO
+        ENDDO
+      ENDIF
+
+      !-----------------------------------------------------------------------
+      ! Vorticity re-projection
+      !@ has the domain length really been included in these wave numbers
+      !-----------------------------------------------------------------------
+      ELSE IF (presentcase .EQ. ppm_poisson_grn_reprojec) THEN
+        !remembering to normalize the FFT
+        normfac = 1.0_MK/ REAL((ppmpoisson%nmz(1)-1)* & !vertex
+                              & (ppmpoisson%nmz(2)-1)* &
+                              & (ppmpoisson%nmz(3)-1),MK)
+        write(*,*) 'reprojection ppm style' !@
+        DO isub=1,ppmpoisson%nsublistz
+          isubl=ppmpoisson%isublistz(isub)
+          DO k=1,ppmpoisson%ndataz(3,isubl)
+            gk = k - 1 + (ppmpoisson%istartz(3,isubl)-1)
+            IF (gk .GT. (ppmpoisson%nmz(3)-1)/2) gk = gk-(ppmpoisson%nmz(3)-1)
+            kz = REAL(gk,MK)
+            DO j=1,ppmpoisson%ndataz(2,isubl)
+              gj = j - 1 + (ppmpoisson%istartz(2,isubl)-1)
+              IF (gj .GT. (ppmpoisson%nmz(2)-1)/2) gj = gj-(ppmpoisson%nmz(2)-1)
+              ky = REAL(gj,MK)
+              DO i=1,ppmpoisson%ndataz(1,isubl)
+                gi = i - 1 + (ppmpoisson%istartz(1,isubl)-1)
+                IF (gi .GT. (ppmpoisson%nmz(1)-1)/2) gi = gi-(ppmpoisson%nmz(1)-1)
+                kx = REAL(gi,MK)
+
+                IF (gi .EQ. 0 .AND. gj .EQ. 0 .AND. gk .EQ. 0) THEN
+                  wdotk = 0.0_mk
+                ELSE
+                  wdotk = (ppmpoisson%fldzc2(1,i,j,k,isub) * kx +  &
+                        &  ppmpoisson%fldzc2(2,i,j,k,isub) * ky +  &
+                        &  ppmpoisson%fldzc2(3,i,j,k,isub) * kz) / &
+                        &  (kx*kx+ky*ky+kz*kz)
+                ENDIF
+
+                ppmpoisson%fldzc2(1,i,j,k,isub) = &
+                  & (ppmpoisson%fldzc2(1,i,j,k,isub) - wdotk*kx)*normfac
+                ppmpoisson%fldzc2(2,i,j,k,isub) = &
+                  & (ppmpoisson%fldzc2(2,i,j,k,isub) - wdotk*ky)*normfac
+                ppmpoisson%fldzc2(3,i,j,k,isub) = &
+                  & (ppmpoisson%fldzc2(3,i,j,k,isub) - wdotk*kz)*normfac
+              ENDDO
+            ENDDO
+          ENDDO
+        ENDDO
+      ENDIF
+
+!@write(*,*) 'solving ....  9', ppm_rank
+      !-----------------------------------------------------------------------
+      ! IFFT pencil (Z)
+      !-----------------------------------------------------------------------
+      CALL ppm_fft_execute_1d(ppmpoisson%topoidz,&
+      & ppmpoisson%meshidz, ppmpoisson%planbz, &
+      & ppmpoisson%fldzc2, ppmpoisson%fldzc1, &
+      & info)
+
+!@write(*,*) 'solving ....  11', ppm_rank
+#ifdef __NOPE
+      if (ppm_rank .EQ. trank)   THEN
+            write(*,*)
+            write(*,*)
+      write(*,*) 'ifftx12', ppm_rank
+      DO isub=1,ppmpoisson%nsublistz
+        isubl=ppmpoisson%isublistz(isub)
+        DO k=1,ppmpoisson%ndataz(3,isubl)-1
+          write(*,*) 'z',k
+            DO i=1,ppmpoisson%ndataz(1,isubl)-1
+          DO j=1,ppmpoisson%ndataz(2,isubl)-1
+              write(*,'(A,E12.4,E12.4,A,$)') '  (',ppmpoisson%fldzc1(1,i,j,k,isub),')'
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+      write(*,*) 'iffty12', ppm_rank
+      DO isub=1,ppmpoisson%nsublistz
+        isubl=ppmpoisson%isublistz(isub)
+        DO k=1,ppmpoisson%ndataz(3,isubl)-1
+          write(*,*) 'z',k
+            DO i=1,ppmpoisson%ndataz(1,isubl)-1
+          DO j=1,ppmpoisson%ndataz(2,isubl)-1
+              write(*,'(A,E12.4,E12.4,A,$)') '  (',ppmpoisson%fldzc1(2,i,j,k,isub),')'
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+      write(*,*) 'ifftz12', ppm_rank
+      DO isub=1,ppmpoisson%nsublistz
+        isubl=ppmpoisson%isublistz(isub)
+        DO k=1,ppmpoisson%ndataz(3,isubl)-1
+          write(*,*) 'z',k
+            DO i=1,ppmpoisson%ndataz(1,isubl)-1
+          DO j=1,ppmpoisson%ndataz(2,isubl)-1
+              write(*,'(A,E12.4,E12.4,A,$)') '  (',ppmpoisson%fldzc1(3,i,j,k,isub),')'
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+      ENDIF
+#endif
+
+      !-----------------------------------------------------------------------
+      ! Map back to slabs (XY)
+      !-----------------------------------------------------------------------
+      !Initialise
+      CALL ppm_map_field_global(&
+      & ppmpoisson%topoidz, &
+      & ppmpoisson%topoidxy, &
+      & ppmpoisson%meshidz, &
+      & ppmpoisson%meshidxyc,info)
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to initialise field mapping.',info2)
+        GOTO 9999
+      ENDIF
+
+      !Push the data
+      CALL ppm_map_field_push(&
+      & ppmpoisson%topoidz, &
+      & ppmpoisson%meshidz,ppmpoisson%fldzc1,__NCOM,info)
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to push vector field.',info2)
+        GOTO 9999
+      ENDIF
+
+      !Send
+      CALL ppm_map_field_send(info)
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to send field.',info2)
+        GOTO 9999
+      ENDIF
+
+      !Retrieve
+      CALL ppm_map_field_pop(&
+      & ppmpoisson%topoidxy, &
+      & ppmpoisson%meshidxyc,ppmpoisson%fldxyc, &
+      & __NCOM,__ZEROSI,info)
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to pop vector field.',info2)
+        GOTO 9999
+      ENDIF
+
+!@write(*,*) 'solving ....  12', ppm_rank
+      !-----------------------------------------------------------------------
+      ! IFFT (XY) use the non-reduced topology
+      !-----------------------------------------------------------------------
+      CALL ppm_fft_execute_2d(ppmpoisson%topoidxy,&
+      & ppmpoisson%meshidxy, ppmpoisson%planbxy, &
+      & ppmpoisson%fldxyc, ppmpoisson%fldxyr, &
+      & info)
+
+!@write(*,*) 'solving ....  13', ppm_rank
+#ifdef __NOPE
+      if (ppm_rank .EQ. trank)   THEN
+            write(*,*)
+            write(*,*)
+      write(*,*) 'ifftx', ppm_rank
+      DO isub=1,ppmpoisson%nsublistxy
+        isubl=ppmpoisson%isublistxy(isub)
+        DO k=1,ppmpoisson%ndataxy(3,isubl)-1
+          write(*,*) 'z',k
+            DO i=1,ppmpoisson%ndataxy(1,isubl)-1
+          DO j=1,ppmpoisson%ndataxy(2,isubl)-1
+              write(*,'(E12.4,$)') ppmpoisson%fldxyr(1,i,j,k,isub)
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+      write(*,*) 'iffty', ppm_rank
+      DO isub=1,ppmpoisson%nsublistxy
+        isubl=ppmpoisson%isublistxy(isub)
+        DO k=1,ppmpoisson%ndataxy(3,isubl)-1
+          write(*,*) 'z',k
+            DO i=1,ppmpoisson%ndataxy(1,isubl)-1
+          DO j=1,ppmpoisson%ndataxy(2,isubl)-1
+              write(*,'(E12.4,$)') ppmpoisson%fldxyr(2,i,j,k,isub)
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+      write(*,*) 'ifftz', ppm_rank
+      DO isub=1,ppmpoisson%nsublistxy
+        isubl=ppmpoisson%isublistxy(isub)
+        DO k=1,ppmpoisson%ndataxy(3,isubl)-1
+          write(*,*) 'z',k
+            DO i=1,ppmpoisson%ndataxy(1,isubl)-1
+          DO j=1,ppmpoisson%ndataxy(2,isubl)-1
+              write(*,'(E12.4,$)') ppmpoisson%fldxyr(3,i,j,k,isub)
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+      ENDIF
+#endif
+
+#ifdef __VARMESH
+!@tmp
+      write(*,*) 'fldxyr2', ppm_rank
+      DO isub=1,ppmpoisson%nsublistxy
+        isubl=ppmpoisson%isublistxy(isub)
+        DO k=1,ppmpoisson%ndataxy(3,isubl)
+          write(*,*) 'z',k
+          DO i=1,ppmpoisson%ndataxy(1,isubl)
+            DO j=1,ppmpoisson%ndataxy(2,isubl)
+              write(*,'(A,E12.4,A,$)') '  (',ppmpoisson%fldxyr(1,i,j,k,isub),')'
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+#endif
+      !-----------------------------------------------------------------------
+      ! Map back to standard topology (XYZ)
+      !-----------------------------------------------------------------------
+      !Initialise
+      CALL ppm_map_field_global(&
+      & ppmpoisson%topoidxy, &
+      & topoid, &
+      & ppmpoisson%meshidxy, &
+      & meshid,info)
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to initialise field mapping.',info2)
+        GOTO 9999
+      ENDIF
+!@write(*,*) 'solving ....  13a', ppm_rank
+
+      !Push the data
+      CALL ppm_map_field_push(&
+      & ppmpoisson%topoidxy, &
+      & ppmpoisson%meshidxy,ppmpoisson%fldxyr,__NCOM,info)
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to push vector field.',info2)
+        GOTO 9999
+      ENDIF
+!@write(*,*) 'solving ....  13b', ppm_rank, ppmpoisson%topoidxy, topoid, ppmpoisson%meshidxy, meshid
+
+      !Send
+      CALL ppm_map_field_send(info)
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to send field.',info2)
+        GOTO 9999
+      ENDIF
+
+!@write(*,*) 'solving ....  14', ppm_rank
+      !-------------------------------------------------------------------------
+      ! FINAL RETRIEVE - Here we do different things depending on the task
+      ! i.e. the receiver varies
+      !-------------------------------------------------------------------------
+      IF ((ppmpoisson%derivatives .EQ. ppm_poisson_drv_curl_fd2 .OR. &
+           ppmpoisson%derivatives .EQ. ppm_poisson_drv_curl_fd4) .AND. &
+         & (presentcase .EQ. ppm_poisson_grn_pois_per .OR. &  !@these may be unnecessary - perhaps just the derive value. Or maybe not: in case of vorticity reprojection we could get lost
+            presentcase .EQ. ppm_poisson_grn_pois_fre)) THEN
+!@write(*,*) 'solving ....  14a', ppm_rank
+        CALL ppm_map_field_pop(&
+        & topoid, &
+        & meshid,ppmpoisson%drv_vr, &
+        & __NCOM,gstw,info) !!! gst
+        IF (info .NE. 0) THEN
+          CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to pop vector field.',info2)
+          GOTO 9999
+        ENDIF
+!@write(*,*) 'solving ....  14b', ppm_rank
+        !-------------------------------------------------------------------------
+        ! Ghost the temporary array for derivatives (drv_vr)
+        !-------------------------------------------------------------------------
+!@write(*,*) 'solving ....  14c', ppm_rank
+        CALL ppm_map_field_ghost_get(topoid,meshid,gstw,info)
+        IF (info .NE. 0) THEN
+           CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to initialise ghosts.',info2)
+           GOTO 9999
+        ENDIF
+!@write(*,*) 'solving ....  14d', ppm_rank
+        CALL ppm_map_field_push(topoid,meshid,ppmpoisson%drv_vr,__NCOM,info)
+        IF (info .NE. 0) THEN
+           CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to push ghosts.',info2)
+           GOTO 9999
+        ENDIF
+!@write(*,*) 'solving ....  14e', ppm_rank
+        CALL ppm_map_field_send(info)
+        IF (info .NE. 0) THEN
+           CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to send ghosts.',info2)
+           GOTO 9999
+        ENDIF
+!@write(*,*) 'solving ....  14f', ppm_rank
+        CALL ppm_map_field_pop(topoid,meshid,ppmpoisson%drv_vr,__NCOM,gstw,info)
+        IF (info .NE. 0) THEN
+           CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to pop ghosts.',info2)
+           GOTO 9999
+        ENDIF
+
+      ELSE
+!@write(*,*) 'solving ....  14g', ppm_rank
+        CALL ppm_map_field_pop(&
+        & topoid, &
+        & meshid,fieldout, &
+        & __NCOM,gstw,info) !!! gst
+!@write(*,*) 'solving ....  14h', ppm_rank
+      ENDIF
+      IF (info .NE. 0) THEN
+        CALL ppm_write(ppm_rank, 'ppm_poisson_solve','Failed to pop vector field.',info2)
+        GOTO 9999
+      ENDIF
+
+!@write(*,*) 'solving ....  15', ppm_rank
+#ifdef __VARMESH
+!@tmp only works for one subdomain (not parallel)
+      write(*,*) 'fieldout', ppm_rank
+      DO isub=1,ppmpoisson%nsublistxy
+        isubl=ppmpoisson%isublistxy(isub)
+        DO k=1,ppmpoisson%ndataxy(3,isubl)/2-1
+          write(*,*) 'z',k
+          DO i=1,ppmpoisson%ndataxy(1,isubl)/2-1
+            DO j=1,ppmpoisson%ndataxy(2,isubl)/2-1
+              write(*,'(A,E12.4,A,$)') '  (',fieldout(1,i,j,k,isub),')'
+            END DO
+            write(*,*)
+          END DO
+        END DO
+      END DO
+#endif
+
+      !-------------------------------------------------------------------------
+      !@To come: treat ghost layer to make FD stencils work
+      !-------------------------------------------------------------------------
+      IF (ppmpoisson%derivatives .EQ. ppm_poisson_drv_curl_fd2 .AND.&
+         & (presentcase .EQ. ppm_poisson_grn_pois_fre)) THEN
+         CALL ppm_poisson_extrapolateghost(topoid,meshid,ppmpoisson%drv_vr,&
+                                     & 2,4,gstw,info)
+      ENDIF
+      IF (ppmpoisson%derivatives .EQ. ppm_poisson_drv_curl_fd4 .AND.&
+         & (presentcase .EQ. ppm_poisson_grn_pois_fre)) THEN
+         CALL ppm_poisson_extrapolateghost(topoid,meshid,ppmpoisson%drv_vr,&
+                                     & 2,4,gstw,info)
+      ENDIF
+
+!@write(*,*) 'solving ....  16', ppm_rank
+      !-------------------------------------------------------------------------
+      ! Optionally do derivatives
+      ! Perhaps make ppm_poisson_fd take _none as argument. Then maybe no
+      ! if-statement is required
+      !-------------------------------------------------------------------------
+      IF (ppmpoisson%derivatives .EQ. ppm_poisson_drv_curl_fd2 .AND.&
+         & (presentcase .EQ. ppm_poisson_grn_pois_per .OR. &  !@these may be unnecessary - perhaps just the derive value
+            presentcase .EQ. ppm_poisson_grn_pois_fre)) THEN
+         CALL ppm_poisson_fd(topoid,meshid,ppmpoisson%drv_vr,fieldout,&
+                           & ppm_poisson_drv_curl_fd2,info)
+      ENDIF
+      IF (ppmpoisson%derivatives .EQ. ppm_poisson_drv_curl_fd4 .AND.&
+         & (presentcase .EQ. ppm_poisson_grn_pois_per .OR. &  !@these may be unnecessary - perhaps just the derive value
+            presentcase .EQ. ppm_poisson_grn_pois_fre)) THEN
+         CALL ppm_poisson_fd(topoid,meshid,ppmpoisson%drv_vr,fieldout,&
+                           & ppm_poisson_drv_curl_fd4,info)
+      ENDIF
+
+!@write(*,*) 'solving ....  17', ppm_rank
+      !-------------------------------------------------------------------------
+      ! Finally ghost the velocity/stream function field before returning it
+      ! Also extrapolate if freespace
+      !-------------------------------------------------------------------------
+      CALL ppm_map_field_ghost_get(topoid,meshid,gstw,info)
+      CALL ppm_map_field_push(topoid,meshid,fieldout,__NCOM,info)
+      CALL ppm_map_field_send(info)
+      CALL ppm_map_field_pop(topoid,meshid,fieldout,__NCOM,gstw,info)
+      IF (presentcase .EQ. ppm_poisson_grn_pois_fre) THEN
+         CALL ppm_poisson_extrapolateghost(topoid,meshid,fieldout,&
+                                     & 2,4,gstw,info)
+      ENDIF
+
+!@write(*,*) 'solving ....  18', ppm_rank
+      !-------------------------------------------------------------------------
+      ! Perhaps allocate (and deallocate) arrays !@
+      !-------------------------------------------------------------------------
+
+      !-------------------------------------------------------------------------
+      ! Return
+      !-------------------------------------------------------------------------
+ 9999 CONTINUE
+      CALL substop('ppm_poisson_solve',t0,info)
+      RETURN
+
+      END SUBROUTINE __ROUTINE
+
-- 
GitLab