diff --git a/src/fields_mod.f90 b/src/fields_mod.f90
index fc32d3a..d533d19 100644
--- a/src/fields_mod.f90
+++ b/src/fields_mod.f90
@@ -1,1560 +1,1519 @@
 !------------------------------------------------------------------------------
 ! EPFL/Swiss Plasma Center
 !------------------------------------------------------------------------------
 !
 ! MODULE: fields
 !
 !> @author
 !> Patryk Kaminski   EPFL/SPC
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !> Module responsible for initializing the magnetic field, solving the Poisson equation and computing the moments of the particles distribution function
 !------------------------------------------------------------------------------
 MODULE fields
     USE constants
     USE basic, ONLY: nr, nthet, nz, zgrid, rgrid, Br, Bz, Er, Ethet, Ez, femorder, ngauss, nlppform, pot, Athet, &
     & splrz, splrz_ext, nlperiod, phinorm, nlPhis, nrank, mpirank, mpisize, step, it2d, timera, potxt, Erxt, Ezxt
     USE beam, ONLY: partslist
     USE bsplines
     USE mumps_bsplines
     use mpi
     Use omp_lib
     Use mpihelper, ONLY: db_type
     USE particletypes
     USE, INTRINSIC :: iso_c_binding
 
     IMPLICIT NONE
 
     INCLUDE 'fftw3.f03'
     
-    REAL(kind=db), allocatable, SAVE :: matcoef(:,:), phi(:,:), dphidthet(:,:), vec1(:), vec2(:)
+    REAL(kind=db), allocatable, SAVE :: matcoef(:,:), phiext(:), phi(:,:), dphidthet(:,:), vec1(:), vec2(:)
     REAL(kind=db), ALLOCATABLE, SAVE :: dftrhsreal(:,:), dftrhsimag(:,:), dftphireal(:,:), dftphiimag(:,:)
     REAL(kind=db), allocatable, SAVE :: loc_moments(:,:,:), loc_rhs(:,:), omp_loc_rhs(:,:,:), gradgtilde(:), fverif(:), ppformwork(:,:,:)
     INTEGER, SAVE:: loc_zspan
     TYPE(mumps_mat), SAVE, ALLOCATABLE :: femat(:)          !< Finite Element  Method matrix for the full domain
     TYPE(mumps_mat), SAVE, ALLOCATABLE :: reduccedmat(:)    !< Finite Element Method matrix in the redduced web-spline sub-space
     INTEGER :: nbmoments = 4                       !< Number of moments to be calculated and stored
     INTEGER(kind=omp_lock_kind), Allocatable:: mu_lock(:) !< Stores the lock for fields parallelism
 
 CONTAINS
 
 !---------------------------------------------------------------------------
 !> @author
 !> Patryk kaminski   EPFL/SPC
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !>
 !> @brief
 !> Calculate magnetic field mirror components in grid points (Davidson analytical formula employed)
 !> or load it from magnetfile if present
 !---------------------------------------------------------------------------
 SUBROUTINE mag_init
     USE basic, ONLY: nr, nz,lu_in,cstep
     USE magnet
 
     ALLOCATE (Br((nr + 1)*(nz + 1)), Bz((nr + 1)*(nz + 1)))
     ALLOCATE (Athet((nr + 1)*(nz + 1)))
     call timera(0, "mag_init")
     CALL magnet_init(lu_in,cstep)
     call timera(1, "mag_init")
 end subroutine mag_init
 
 
 !---------------------------------------------------------------------------
 !> @author
 !> Patryk kaminski   EPFL/SPC
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !>
 !> @brief
 !> Set-up the necessary variables for solving Poisson and computes the magnetic field on the grid
 !---------------------------------------------------------------------------
 SUBROUTINE fields_init
     USE basic
     USE bsplines
     USE geometry
     USE mumps_bsplines
     USE mpihelper
     INTEGER :: nrz(2), i, d2, k1, n1, m
 
     ! Auxiliary vectors
     ALLOCATE(vec1((nz+1)*(nr+1)),vec2((nr+1)*(nz+1)))
     DO i=0,nz
         vec1(i*(nr+1)+1:(i+1)*(nr+1))=rgrid
         vec2(i*(nr+1)+1:(i+1)*(nr+1))=zgrid(i)
     END DO
     
     ! Set up 2d spline splrz_ext used in the FEM to calculate the external electric field and potential
     CALL set_spline(femorder, ngauss, rgrid, zgrid, splrz_ext, nlppform=nlppform, period=nlperiod)
     ! Set up 2d spline splrz used in the FEM
     ALLOCATE(splrz(nthet))
     DO m=1,nthet
         CALL set_spline(femorder, ngauss, rgrid, zgrid, splrz(m), nlppform=nlppform, period=nlperiod)
     END DO
     
     ! Allocate the work buffer to calculate the ppform
     d2 = splrz(1)%sp2%dim
     k1 = splrz(1)%sp1%order
     n1 = splrz(1)%sp1%nints
     ALLOCATE(ppformwork(d2,k1,n1))
 
     ! Calculate dimension of splines
     nrz(1) = nz
     nrz(2) = nr
     CALL get_dim(splrz(1), nrank, nrz, femorder)
 
     ! Allocate necessary variables
     ALLOCATE(femat(nthet/2+1))
     ALLOCATE(reduccedmat(nthet/2+1))
     ALLOCATE(matcoef(nrank(1), nrank(2)))
     ALLOCATE(pot((nr + 1)*(nz + 1),nthet))
     ALLOCATE(Er((nr + 1)*(nz + 1),nthet))
     ALLOCATE(Ethet((nr + 1)*(nz + 1),nthet))
     ALLOCATE(Ez((nr + 1)*(nz + 1),nthet))
     ALLOCATE(potxt((nr + 1)*(nz + 1)))
     ALLOCATE(Erxt((nr + 1)*(nz + 1)))
     ALLOCATE(Ezxt((nr + 1)*(nz + 1)))
     ALLOCATE(rhs(nrank(1)*nrank(2),nthet))
     rhs=0
     ALLOCATE(dftrhsreal(nrank(1)*nrank(2),nthet/2+1))
     ALLOCATE(dftrhsimag(nrank(1)*nrank(2),nthet/2+1))
     ALLOCATE(dftphireal(nrank(1)*nrank(2),nthet/2+1))
     ALLOCATE(dftphiimag(nrank(1)*nrank(2),nthet/2+1))
     ALLOCATE(gradgtilde(nrank(1)*nrank(2)))
     gradgtilde = 0
+    ALLOCATE(phiext(nrank(1)*nrank(2)))
     ALLOCATE(phi(nrank(1)*nrank(2),nthet))
     ALLOCATE(dphidthet(nrank(1)*nrank(2),nthet))
     ALLOCATE (volume(nrank(1)*nrank(2)))
     volume = 0
     ALLOCATE (mu_lock(nrank(1)*nrank(2)))
     DO i = 1, nrank(1)*nrank(2)
         CALL omp_init_lock(mu_lock(i))
     END DO
 END SUBROUTINE fields_init
 
 
 !---------------------------------------------------------------------------
 !> @author
 !> Patryk kaminski   EPFL/SPC
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !> @brief
 !> Set-up the geometry definition and read it from the standard input
 !> Precomputes the LHS matrix to solve Poisson abd the RHS effect of the dirichlet boundaries
 !---------------------------------------------------------------------------
 SUBROUTINE fields_start
     USE geometry
     USE basic, ONLY: nrank, nthet
     implicit none
     INTEGER:: i,j, k, m, ierr
     DOUBLE PRECISION:: val
       
     ! set up the geometry module for setting up non-conforming boundary conditions
     call timera(0, "geom_init")
     call geom_init(splrz(1), vec1, vec2)
     call timera(1, "geom_init")
 
     CALL timera(0, "compute femat")
     DO m=1,nthet/2+1
         ! Initialisation of FEM matrix
         CALL init(nrank(1)*nrank(2), 2, femat(m))
 
         ! Calculate and factorise FEM matrix (depends only on mesh)
         CALL fematrix(femat(m),m)
 
         IF(nlweb) THEN
             ! Calculate reduced matrix for use of web splines
             CALL reducematrix(femat(m), reduccedmat(m))
             CALL factor(reduccedmat(m))
         ELSE
             CALL factor(femat(m))
         END IF
     END DO
     CALL timera(1, "compute femat")
       
     IF(walltype .lt. 0) THEN
         ALLOCATE(fverif(nrank(1)*nrank(2)))
         fverif = 0
     END IF
       
     ! Compute the volume of the splines and gtilde for solving E using web-splines
     CALL comp_volume
     !$OMP PARALLEL 
     CALL comp_gradgtilde
     !$OMP END PARALLEL
     CALL vacuum_field
 END SUBROUTINE fields_start
 
 
 !---------------------------------------------------------------------------
 !> @author
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !> @brief
 !> Computes the externally imposed electric field
 !---------------------------------------------------------------------------
 SUBROUTINE vacuum_field
     USE geometry
     USE basic, ONLY: pot, rhs
     implicit none
     INTEGER:: i,m,iend
 
     !$OMP PARALLEL private(i)
     !$OMP DO SIMD
     DO i=1,size(rhs,1)
         rhs(i,1)=-gradgtilde(i)
     END DO
     !$OMP END DO SIMD
     !$OMP END PARALLEL
 
     CALL poisson2D
     
     !$OMP PARALLEL private(i,iend)
     CALL vacuum_field_comp(splrz_ext)
     !$OMP BARRIER
     !$OMP END PARALLEL
 END SUBROUTINE vacuum_field
 
 
 !---------------------------------------------------------------------------
 !> @author
 !> Pierrick Giroud EPFL/SPC
 !
 ! DESCRIPTION:
 !> @brief
 !> Updates the splinevar variable with the new phi coefficients and calculates
 !> Phi Er and Ez on the grid
 !---------------------------------------------------------------------------
 SUBROUTINE vacuum_field_comp(splinevar)
     USE basic, ONLY: nrank, pot, nlend, gradthet, rgrid, nr, nz
     USE bsplines, ONLY: spline2d, gridval
     USE mumps_bsplines, ONLY: bsolve, vmx
     USE futils
     USE geometry
     type(spline2d) :: splinevar
     INTEGER:: ierr, i, j, iend, rindex
     INTEGER:: Evalpot(2), EvalEr(2), EvalEz(2)
       
     Evalpot=(/0,0/)
     EvalEr=(/1,0/)
     EvalEz=(/0,1/)
 
     !$OMP DO SIMD collapse(2)
     DO j=1,nrank(2)
         DO i=1,nrank(1)
-            matcoef(i,j) = phi((j-1)*nrank(1)+i,1)
+            matcoef(i,j) = phiext((j-1)*nrank(1)+i)
         END DO
     END DO
     !$OMP END DO SIMD
     ! Update the ppform coefficients
     CALL updt_ppform2d(splinevar, matcoef)
     !$OMP BARRIER
     
     ! On the root process, compute the electric field for diagnostic purposes
     IF (mpirank .eq. 0) THEN
         !$OMP DO 
         DO i=1,size(potxt),16
             iend=min(size(pot,1),i+15)
             CALL gridval(splinevar, vec1(i:iend), vec2(i:iend), potxt(i:iend), Evalpot)
             CALL gridval(splinevar, vec1(i:iend), vec2(i:iend), Erxt(i:iend), EvalEr)
             CALL gridval(splinevar, vec1(i:iend), vec2(i:iend), Ezxt(i:iend), EvalEz)
             Ezxt(i:iend) = -potxt(i:iend)*gridwdir(1,i:iend) - Ezxt(i:iend)*gridwdir(0,i:iend) - gtilde(1,i:iend)
             Erxt(i:iend) = -potxt(i:iend)*gridwdir(2,i:iend) - Erxt(i:iend)*gridwdir(0,i:iend) - gtilde(2,i:iend)
             potxt(i:iend) = potxt(i:iend)*gridwdir(0,i:iend) + gtilde(0,i:iend)
         END DO
         !$OMP END DO NOWAIT
     END IF
 END SUBROUTINE vacuum_field_comp
 
 
 !---------------------------------------------------------------------------
 !> @author
 !> Patryk kaminski   EPFL/SPC
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !>
 !> @brief
 !> Set-up the necessary variables for the communication of moments and rhs grid
 !---------------------------------------------------------------------------
 SUBROUTINE fields_comm_init(Zbounds)
     USE basic, ONLY: nrank,nthet
     USE mpihelper
     USE omp_lib
     INTEGER:: Zbounds(0:), nbthreads
     nbthreads = omp_get_max_threads()
     loc_zspan = Zbounds(mpirank + 1) - Zbounds(mpirank) + femorder(2)
     if (allocated(loc_moments)) deallocate (loc_moments)
     ALLOCATE (loc_moments(nbmoments,loc_zspan*nrank(1),nthet))
     if (allocated(loc_rhs)) deallocate (loc_rhs)
     ALLOCATE (loc_rhs(loc_zspan*nrank(1),nthet))
     if (allocated(omp_loc_rhs)) deallocate (omp_loc_rhs)
     ALLOCATE (omp_loc_rhs(nbthreads,loc_zspan*nrank(1),nthet))
     IF (mpisize .gt. 1) THEN
         CALL init_overlaps(nrank, femorder, Zbounds(mpirank), Zbounds(mpirank + 1), nbmoments)
     END IF
 END SUBROUTINE fields_comm_init
 
 
 !---------------------------------------------------------------------------
 !> @author
 !> Patryk kaminski   EPFL/SPC
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !>
 !> @brief
 !> Construct the right hand side vector used in the FEM Poisson solver
 !
 !> @param[in] plist list of the particles type storing the desired specie parameters
 !
 !---------------------------------------------------------------------------
 SUBROUTINE rhscon(plist)
     USE bsplines
     use mpi
     USE basic!, ONLY: rhs, Zbounds
     USE beam, ONLY: particles
     USE mpihelper
     Use geometry
     Use omp_lib
     type(particles), INTENT(INOUT):: plist(:)
     INTEGER:: i,j,k,m
     
     IF(nlphis) THEN  
         !$OMP DO SIMD
         DO i=1,size(loc_rhs,1)
             DO m=1,size(loc_rhs,2)
                 loc_rhs(i,m)=0
             END DO
         END DO
         !$OMP END DO SIMD
 
         ! Assemble rhs for each specie
         DO i = 1, size(plist, 1)
             IF(plist(i)%is_field) CALL deposit_charge(plist(i))
         END DO
 
         ! Communicate the overlaps
         IF(mpisize .gt. 1) CALL rhs_overlap
 
         ! ! Add gradgtilde
         ! !$OMP DO SIMD
         ! DO i=1,size(loc_rhs,1)
         !     j=(i-1)/nrank(1)+Zbounds(mpirank)
         !     k=mod(i-1,nrank(1))+1
         !     DO m=1,size(loc_rhs,2)
         !         loc_rhs(i,m)=loc_rhs(i,m)-gradgtilde(k+j*nrank(1))
         !     END DO
         ! END DO
         ! !$OMP END DO SIMD
 
         ! If we are using MPI parallelism, reduce the rhs on the root process
         IF(mpisize .gt. 1) THEN
             CALL rhs_gather(rhs)
         ELSE ! in serial copy loc_rhs to rhs
             !$OMP DO
             DO i=1,size(loc_rhs,1)
                 DO m=1,size(loc_rhs,2)
                     rhs(i,m)=loc_rhs(i,m)
                 END DO
             END DO
             !$OMP END DO
         END IF
 
     ELSE ! We only consider the externally imposed field
         !$OMP DO
         DO i=1,size(rhs,1)
             DO m=1,size(rhs,2)
                 rhs(i,m)=0 !-gradgtilde(i)
             END DO
         END DO
         !$OMP END DO
     END IF
 END SUBROUTINE rhscon
 
 
 !---------------------------------------------------------------------------
 !> @author
 !> Patryk kaminski   EPFL/SPC
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !>
 !> @brief
 !> Deposit the particles charges (q) from p on the grid
 !
 !> @param[in] p the particles type storing the desired specie parameters
 !---------------------------------------------------------------------------
 SUBROUTINE deposit_charge(p)
     USE bsplines
     USE mpi
     USE constants
     USE basic, ONLY: Zbounds, rnorm, phinorm, thetgrid, invdthet
     USE beam, ONLY: particles
     USE mpihelper
     USE geometry
     USE omp_lib
 
     TYPE(particles), INTENT(IN) :: p
     INTEGER :: irow, jcol, it, jw, mu, i, k, iend, nbunch
     INTEGER, DIMENSION(:), ALLOCATABLE :: zindex, rindex, thetindex
     REAL(kind=db), ALLOCATABLE :: fun(:, :, :), fun2(:, :, :)
     INTEGER:: num_threads, curr_thread
     real(kind=db):: contrib, chargecoeff, wthet
 
     num_threads = omp_get_max_threads()
     nbunch = p%Nploc/num_threads ! Particle bunch size used when calling basfun
     nbunch = max(nbunch, 1) ! Particle bunch size used when calling basfun
     nbunch = min(nbunch, 16) ! Particle bunch size used when calling basfun
     chargecoeff = p%weight*p%q/(2*pi*eps_0*phinorm*rnorm) ! Normalized charge density simulated by each macro particle
 
     ! Assemble rhs
     IF (p%Nploc .gt. 0) THEN
         ALLOCATE (zindex(nbunch), rindex(nbunch), thetindex(nbunch))
         ALLOCATE (fun(1:femorder(1) + 1, 0:0, nbunch), fun2(1:femorder(2) + 1, 0:0, nbunch)) ! Arrays keeping values of b-splines at gauss node
         zindex=0
         rindex=0
         thetindex=0
         curr_thread=omp_get_thread_num()+1
         !$OMP DO SIMD
         DO i=1,size(loc_rhs,1)
             omp_loc_rhs(:,i,:)=0
         END DO
         !$OMP END DO SIMD
 
         !$OMP DO
         DO i = 1, p%Nploc, nbunch
             ! Avoid segmentation fault by accessing non relevant data
             iend = min(i + nbunch - 1, p%Nploc)
             k = iend - i + 1
             ! Localize the particle
             rindex(1:k) = p%cellindex(1,i:iend)
             thetindex(1:k) = p%cellindex(2,i:iend)
             zindex(1:k) = p%cellindex(3,i:iend)
             ! Compute the value of the splines at the particles positions
             CALL basfun(p%pos(1,i:iend), splrz(1)%sp1, fun, rindex(1:k) + 1)
             CALL basfun(p%pos(3,i:iend), splrz(1)%sp2, fun2, zindex(1:k) + 1)
             DO k = 1, (iend - i + 1)
                 DO jw = 1, (femorder(2) + 1)
                     jcol = zindex(k) + jw - Zbounds(mpirank)
                     DO it = 1, (femorder(1) + 1)
                     irow = rindex(k) + it 
                     mu = irow + (jcol - 1)*(nrank(1))
                     ! Add contribution of particle k to rhs grid point mu
                     contrib = fun(it, 0, k)*fun2(jw, 0, k)*p%geomweight(0,i + k - 1)*chargecoeff
                     wthet = (p%pos(2,i+k-1)-thetgrid(thetindex(k)))*invdthet
                     !omp_loc_rhs(curr_thread,mu) = omp_loc_rhs(curr_thread,mu) + contrib
                     IF(thetindex(k) .eq. nthet-1) THEN
                         omp_loc_rhs(curr_thread,mu,thetindex(k)+1) = omp_loc_rhs(curr_thread,mu,thetindex(k)+1) + contrib*(1-wthet)
                         omp_loc_rhs(curr_thread,mu,1) = omp_loc_rhs(curr_thread,mu,1) + contrib*wthet
                     ELSE
                         omp_loc_rhs(curr_thread,mu,thetindex(k)+1) = omp_loc_rhs(curr_thread,mu,thetindex(k)+1) + contrib*(1-wthet)
                         omp_loc_rhs(curr_thread,mu,thetindex(k)+2) = omp_loc_rhs(curr_thread,mu,thetindex(k)+2) + contrib*wthet
                     END IF
                     END DO
                 END DO
             END DO
         END DO
         !$OMP END DO
         !$OMP DO SIMD
         DO i=1,size(loc_rhs,1)
             DO k=1,num_threads
                 loc_rhs(i,:)=loc_rhs(i,:)+omp_loc_rhs(k,i,:)
             END DO
         END DO
         !$OMP END DO SIMD
         DEALLOCATE (fun, fun2, zindex, rindex, thetindex)
     END IF
 END SUBROUTINE deposit_charge
 
 
+!---------------------------------------------------------------------------
+!> @author
+!> Guillaume Le Bars EPFL/SPC
+!
+! DESCRIPTION:
+!> @brief
+!> Do the communication of the local moment matrices between mpi workers 
+!> for the overlap grid points
+!---------------------------------------------------------------------------
+SUBROUTINE rhs_overlap
+    USE mpihelper
+    USE Basic, ONLY: Zbounds, mpirank, leftproc, rightproc, nthet
+    INTEGER:: ierr, i, m
+
+    !$OMP MASTER
+    DO m=1,nthet
+        CALL rhsoverlapcomm(mpirank, leftproc, rightproc, loc_rhs(:,m), nrank, femorder, loc_zspan - femorder(2))
+        IF (mpirank .gt. 0) THEN
+            DO i = 1,femorder(2)*nrank(1)
+                loc_rhs(i,m) = loc_rhs(i,m) + rhsoverlap_buffer(i)
+            END DO
+        END IF
+    END DO
+    !$OMP END MASTER
+    !$OMP BARRIER
+END SUBROUTINE rhs_overlap
+
+
+!---------------------------------------------------------------------------
+!> @author
+!> Guillaume Le Bars EPFL/SPC
+!
+! DESCRIPTION:
+!> @brief
+!> Do the communication of the local moment matrices between mpi workers 
+!> to reduce the result on the host
+!---------------------------------------------------------------------------
+SUBROUTINE rhs_gather(rhs)
+    USE mpihelper
+    USE basic, ONLY: Zbounds, mpirank, leftproc, rightproc, nthet
+    REAL(kind=db), DIMENSION(:,:), INTENT(INOUT):: rhs
+    INTEGER:: ierr, m
+    INTEGER:: displs(mpisize), counts(mpisize)
+    INTEGER:: overlap_type
+    INTEGER:: rcvoverlap_type
+
+    displs = Zbounds(0:mpisize - 1)*nrank(1)
+    counts = (Zbounds(1:mpisize) - Zbounds(0:mpisize - 1))*nrank(1)
+    counts(mpisize) = counts(mpisize) + femorder(1)*nrank(1)
+
+    !$OMP MASTER
+    IF (mpirank .eq. 0) THEN
+        rhs = 0
+    END IF
+    DO m=1,nthet
+        CALL MPI_GATHERV(loc_rhs(:,m), counts(mpirank + 1), db_type, rhs(:,m), counts, displs, db_type, 0, MPI_COMM_WORLD, ierr)
+    END DO
+    !$OMP END MASTER
+    !$OMP BARRIER
+END SUBROUTINE rhs_gather
+
+
 !---------------------------------------------------------------------------
 !> @author
 !> Patryk kaminski   EPFL/SPC
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !> @brief
 !> Calculate the 0th 1st and 2nd order moments of the particle p and stores it in moment
 !
 !> @param[in] p the particles type storing the desired specie parameters
 !> @param[out] moment the 2d array storing the calculated moments
 !---------------------------------------------------------------------------
 SUBROUTINE momentsdiag(p)
     USE bsplines
     USE mpi
     USE beam, ONLY: particles
     USE basic
     USE mpihelper
     USE geometry
     type(particles), INTENT(INOUT):: p
     INTEGER :: i,istart,iend
 
     !$OMP SINGLE
     loc_moments=0 ! Reset the moments matrix
     !$OMP END SINGLE
 
     CALL deposit_moments(p)
 
     !$OMP SINGLE
     IF(.not. allocated(p%moments)) THEN
         IF(mpirank.eq.0) THEN
             ALLOCATE(p%moments(4,nrank(1)*nrank(2),nthet))
         ELSE
             ALLOCATE(p%moments(0,0,0))
         END IF
     END IF
     !$OMP END SINGLE
 
     ! If we are using MPI parallelism, reduce the moments on the root process
     IF (mpisize .gt. 1) THEN
         CALL moments_gather(p%moments)
     ELSE
         !$OMP SINGLE
         p%moments = loc_moments
         !$OMP END SINGLE NOWAIT
     END IF
 END SUBROUTINE momentsdiag
 
 
 !---------------------------------------------------------------------------
 !> @author
 !> Patryk kaminski   EPFL/SPC
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !> @brief
 !> Deposit the particles moments (n,v,v^2) from p on the grid
 !
 !> @param[in] p the particles type storing the desired specie parameters
 !---------------------------------------------------------------------------
 SUBROUTINE deposit_moments(p)
     USE bsplines
     USE mpi
     USE basic, ONLY: Zbounds, thetgrid, invdthet
     USE beam, ONLY: particles
     USE mpihelper
     USE geometry
     USE omp_lib
 
     TYPE(particles), INTENT(IN):: p
     INTEGER ::irow, jcol, it, jw, mu, i, k, iend, nbunch
     INTEGER, DIMENSION(:), ALLOCATABLE :: zindex, rindex, thetindex
     REAL(kind=db) :: vr, vthet, vz, coeff, wthet
     REAL(kind=db), ALLOCATABLE :: fun(:, :, :), fun2(:, :, :)
     INTEGER:: num_threads
 
     num_threads = omp_get_max_threads()
     nbunch = p%Nploc/num_threads ! Particle bunch size used when calling basfun
     nbunch = max(nbunch, 1) ! Particle bunch size used when calling basfun
     nbunch = min(nbunch, 64) ! Particle bunch size used when calling basfun
     
     ! Assemble moments
     IF (p%Nploc .gt. 0) THEN
         ALLOCATE(zindex(nbunch), rindex(nbunch), thetindex(nbunch))
         ALLOCATE(fun(1:femorder(1) + 1, 0:0, nbunch), fun2(1:femorder(2) + 1, 0:0, nbunch)) ! Arrays keeping values of b-splines at gauss node
         !$OMP DO
         DO i = 1, p%Nploc, nbunch
             ! Avoid segmentation fault by accessing non relevant data
             iend = min(i + nbunch - 1, p%Nploc)
             k = iend - i + 1
             ! Localize the particle
             rindex(1:k) = p%cellindex(1,i:iend)
             thetindex(1:k) = p%cellindex(2,i:iend)
             zindex(1:k) = p%cellindex(3,i:iend)
             ! Compute the value of the splines at the particles positions
             CALL basfun(p%pos(1,i:iend), splrz(1)%sp1, fun(:, :, 1:k), rindex(1:k) + 1)
             CALL basfun(p%pos(3,i:iend), splrz(1)%sp2, fun2(:, :, 1:k), zindex(1:k) + 1)
             DO k = 1, (iend - i + 1)
                 DO jw = 1, (femorder(2) + 1)
                     jcol = zindex(k) + jw - Zbounds(mpirank)
                     DO it = 1, (femorder(1) + 1)
                         irow = rindex(k) + it
                         mu = irow + (jcol - 1)*(nrank(1))
                         coeff = p%weight*fun(it, 0, k)*fun2(jw, 0, k)
                         wthet = (p%pos(2,i+k-1)-thetgrid(thetindex(k)))*invdthet
                         ! Add contribution of particle nbunch to moments grid point mu
                         vr = 0.5*(p%U(1,i + k - 1)/p%Gamma(i + k - 1) + p%Uold(1,i + k - 1)/p%Gammaold(i + k - 1))
                         vz = 0.5*(p%U(3,i + k - 1)/p%Gamma(i + k - 1) + p%Uold(3,i + k - 1)/p%Gammaold(i + k - 1))
                         vthet = 0.5*(p%U(2,i + k - 1)/p%Gamma(i + k - 1) + p%Uold(2,i + k - 1)/p%Gammaold(i + k - 1))
                         CALL omp_set_lock(mu_lock(mu))
                         !loc_moments(1:4,mu)=loc_moments(1:4,mu)+coeff*(/1.0_db,vr,vthet,vz/)
                         IF(thetindex(k) .eq. nthet-1) THEN
                             loc_moments(1:4,mu,thetindex(k)+1)=loc_moments(1:4,mu,thetindex(k)+1) + (1-wthet)*coeff*(/1.0_db,vr,vthet,vz/)
                             loc_moments(1:4,mu,1)=loc_moments(1:4,mu,1) + wthet*coeff*(/1.0_db,vr,vthet,vz/)
                         ELSE
                             loc_moments(1:4,mu,thetindex(k)+1)=loc_moments(1:4,mu,thetindex(k)+1) + (1-wthet)*coeff*(/1.0_db,vr,vthet,vz/)
                             loc_moments(1:4,mu,thetindex(k)+2)=loc_moments(1:4,mu,thetindex(k)+2) + wthet*coeff*(/1.0_db,vr,vthet,vz/)
                         END IF
                         CALL omp_unset_lock(mu_lock(mu))
                     END DO
                 END DO
             END DO
          END DO
         !$OMP END DO NOWAIT
         DEALLOCATE (fun, fun2, zindex, rindex, thetindex)
     END IF
 END subroutine deposit_moments
 
 
-!---------------------------------------------------------------------------
-!> @author
-!> Guillaume Le Bars EPFL/SPC
-!
-! DESCRIPTION:
-!> @brief
-!> Do the communication of the local moment matrices between mpi workers 
-!> for the overlap grid points
-!---------------------------------------------------------------------------
-SUBROUTINE rhs_overlap
-    USE mpihelper
-    USE Basic, ONLY: Zbounds, mpirank, leftproc, rightproc, nthet
-    INTEGER:: ierr, i, m
-
-    DO m=1,nthet
-        !$OMP MASTER
-        CALL rhsoverlapcomm(mpirank, leftproc, rightproc, loc_rhs(:,m), nrank, femorder, loc_zspan - femorder(2))
-        !$OMP END MASTER
-        IF (mpirank .gt. 0) THEN
-            !$OMP DO SIMD
-            DO i = 1,femorder(2)*nrank(1)
-                loc_rhs(i,m) = loc_rhs(i,m) + rhsoverlap_buffer(i)
-            END DO
-            !$OMP END DO SIMD
-        END IF
-        !$OMP BARRIER
-    END DO
-END SUBROUTINE rhs_overlap
-
-
-!---------------------------------------------------------------------------
-!> @author
-!> Guillaume Le Bars EPFL/SPC
-!
-! DESCRIPTION:
-!> @brief
-!> Do the communication of the local moment matrices between mpi workers 
-!> to reduce the result on the host
-!---------------------------------------------------------------------------
-SUBROUTINE rhs_gather(rhs)
-    USE mpihelper
-    USE basic, ONLY: Zbounds, mpirank, leftproc, rightproc, nthet
-    REAL(kind=db), DIMENSION(:,:), INTENT(INOUT):: rhs
-    INTEGER:: ierr, m
-    INTEGER:: displs(mpisize), counts(mpisize)
-    INTEGER:: overlap_type
-    INTEGER:: rcvoverlap_type
-
-    displs = Zbounds(0:mpisize - 1)*nrank(1)
-    counts = (Zbounds(1:mpisize) - Zbounds(0:mpisize - 1))*nrank(1)
-    counts(mpisize) = counts(mpisize) + femorder(1)*nrank(1)
-      
-    ! Set communication vector type
-    overlap_type = rhsoverlap_type
-    rcvoverlap_type = rcvrhsoverlap_type
-
-    !$OMP MASTER
-    IF (mpirank .eq. 0) THEN
-        rhs = 0
-    END IF
-    DO m=1,nthet
-        CALL MPI_GATHERV(loc_rhs(:,m), counts(mpirank + 1), db_type, rhs(:,m), counts, displs, db_type, 0, MPI_COMM_WORLD, ierr)
-    END DO
-    !$OMP END MASTER
-    !$OMP BARRIER
-END SUBROUTINE rhs_gather
-
-
 !---------------------------------------------------------------------------
 !> @author
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !> @brief
 !> Do the communication of the local moment matrices between mpi workers 
 !> for the overlap grid points and reduce the result on the host
 !---------------------------------------------------------------------------
 SUBROUTINE moments_gather(moment)
     USE mpihelper
     USE Basic, ONLY: Zbounds, mpirank, leftproc, rightproc, nthet
     REAL(kind=db), DIMENSION(:,:,:), INTENT(INOUT):: moment
     INTEGER:: ierr, i, j, m
     INTEGER:: displs(mpisize), counts(mpisize)
 
     displs = Zbounds(0:mpisize - 1)*nrank(1)*4
     counts = (Zbounds(1:mpisize) - Zbounds(0:mpisize - 1))*4*nrank(1)
     counts(mpisize) = counts(mpisize) + femorder(2)*4*nrank(1)
 
+    !$OMP MASTER
     ! Communicate overlaps
     DO m=1,nthet
-        !$OMP MASTER
         CALL momentsoverlapcomm(mpirank, leftproc, rightproc, loc_moments(:,:,m), nrank, femorder, loc_zspan - femorder(2))
-        !$OMP END MASTER
-        !$OMP BARRIER
-
         IF (mpirank .gt. 0) THEN
-            !!$OMP PARALLEL DO SIMD DEFAULT(SHARED) private(i)
-            !$OMP DO SIMD
             DO i = 1, nrank(1)*femorder(2)
                 loc_moments(1:nbmoments,i,m) = loc_moments(1:nbmoments,i,m) + momentsoverlap_buffer((i-1)*nbmoments+1:i*nbmoments)
             END DO
-            !$OMP END DO SIMD
         END IF
-        !$OMP BARRIER
     END DO
-
-    !$OMP MASTER
-    ! Set communication vector type
     IF (mpirank .eq. 0) THEN
         moment = 0
     END IF
     DO m=1,nthet
         CALL MPI_GATHERV(loc_moments(:,:,m), counts(mpirank + 1), db_type, moment(:,:,m), counts, displs, db_type, 0, MPI_COMM_WORLD, ierr)
     END DO
     !$OMP END MASTER
     !$OMP BARRIER
 END SUBROUTINE moments_gather
 
 
 !---------------------------------------------------------------------------
 !> @author
 !> Patryk kaminski   EPFL/SPC
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !> @brief
 !> Solves Poisson equation using FEM. Distributes the result on all MPI workers.
 !---------------------------------------------------------------------------
 SUBROUTINE poisson
     USE basic, ONLY: rhs, nrank, nlend, nthet, rgrid, nr, nz
     USE bsplines, ONLY: spline2d, gridval
     USE mumps_bsplines, ONLY: bsolve, vmx
     USE futils
     USE geometry
     INTEGER:: ierr, i, j, m, iend
     real(kind=db), allocatable::reducedrhsreal(:,:),reducedrhsimag(:,:)
     real(kind=db), allocatable::reducedsolreal(:,:), reducedsolimag(:,:), tempcol(:)
 
     ! FFT specific variables
     TYPE(C_PTR) :: plan_theta2m ! transform from (r,theta,z) to (r,m,z)
     TYPE(C_PTR) :: plan_m2theta ! transform from (r,m,z) to (r,theta,z)
     REAL(kind=db), DIMENSION(:,:), ALLOCATABLE :: rhstemp, phitemp
     COMPLEX(kind=8), DIMENSION(:,:), ALLOCATABLE :: dftrhstemp, dftphitemp
     
     ! double complex, allocatable:: rhstemp(:), soltemp(:)
     ! TYPE(zmumps_mat) :: mattemp
     
     ! ALLOCATE(rhstemp(nbreducedspline),soltemp(nbreducedspline))
     ! DO i=1,nbreducedspline
     !     rhstemp(i)=cmplx(reducedrhsreal(i),reducedrhsimag(i))
     ! END DO
 
     !mattemp=0
     ! rhstemp=0
     ! soltemp=0
     ! CALL bsolve(mattemp, rhstemp, soltemp)
 
-    ! Compute DFT of RHS along azimuthal direction
     ALLOCATE(rhstemp(nthet,nrank(1)*nrank(2)))
     ALLOCATE(dftrhstemp(nthet/2+1,nrank(1)*nrank(2)))
-
-    rhstemp=transpose(rhs)
-    CALL dfftw_plan_many_dft_r2c(plan_theta2m,1,nthet,nrank(1)*nrank(2),rhstemp,nthet,1,nthet,dftrhstemp,nthet/2+1,1,nthet/2+1,FFTW_ESTIMATE)
-    CALL dfftw_execute_dft_r2c(plan_theta2m,rhstemp,dftrhstemp)
-    CALL dfftw_destroy_plan(plan_theta2m)
-    dftrhsreal=real(transpose(dftrhstemp))
-    dftrhsimag=aimag(transpose(dftrhstemp))
-
-    DEALLOCATE(rhstemp)
-    DEALLOCATE(dftrhstemp)
-
-    ! Solves Poisson equation
     ALLOCATE(reducedrhsreal(nrank(1)*nrank(2),nthet/2+1),reducedrhsimag(nrank(1)*nrank(2),nthet/2+1))
     ALLOCATE(reducedsolreal(nbreducedspline,nthet/2+1),reducedsolimag(nbreducedspline,nthet/2+1))
     ALLOCATE(tempcol(nrank(1)*nrank(2)))
+    ALLOCATE(dftphitemp(nthet/2+1,nrank(1)*nrank(2)))
+    ALLOCATE(phitemp(nthet,nrank(1)*nrank(2)))
 
-    DO m=1,nthet/2+1
-        IF(mpirank .eq. 0) THEN
+    IF(mpirank .eq. 0) THEN
+        ! Compute DFT of RHS along azimuthal direction
+        rhstemp=transpose(rhs)
+        CALL dfftw_plan_many_dft_r2c(plan_theta2m,1,nthet,nrank(1)*nrank(2),rhstemp,nthet,1,nthet,dftrhstemp,nthet/2+1,1,nthet/2+1,FFTW_ESTIMATE)
+        CALL dfftw_execute_dft_r2c(plan_theta2m,rhstemp,dftrhstemp)
+        CALL dfftw_destroy_plan(plan_theta2m)
+        dftrhsreal=real(transpose(dftrhstemp))
+        dftrhsimag=aimag(transpose(dftrhstemp))
+
+        ! Solves Poisson equation
+        DO m=1,nthet/2+1
             IF(nlweb) THEN ! We use the web-spline reduction for stability
                 reducedrhsreal(:,m) = vmx(etilde, dftrhsreal(:,m))
                 reducedrhsimag(:,m) = vmx(etilde, dftrhsimag(:,m))
                 CALL bsolve(reduccedmat(m), reducedrhsreal(1:nbreducedspline,m), reducedsolreal(:,m))
                 CALL bsolve(reduccedmat(m), reducedrhsimag(1:nbreducedspline,m), reducedsolimag(:,m))
+                tempcol = 0
+                tempcol(1:nbreducedspline) = reducedsolreal(:,m)
+                dftphireal(:,m) = vmx(etildet, tempcol)
+                tempcol(1:nbreducedspline) = reducedsolimag(:,m)
+                dftphiimag(:,m) = vmx(etildet, tempcol)
             ELSE
                 CALL bsolve(femat(m), dftrhsreal(:,m), dftphireal(:,m))
                 CALL bsolve(femat(m), dftrhsimag(:,m), dftphiimag(:,m))
             END IF
-        END IF
-
-        !$OMP MASTER
-        ! Distributes the result on all MPI workers
-        IF(nlweb) THEN
-            CALL MPI_Bcast(reducedsolreal(:,m), nbreducedspline, db_type, 0, MPI_COMM_WORLD, ierr)
-            CALL MPI_Bcast(reducedsolimag(:,m), nbreducedspline, db_type, 0, MPI_COMM_WORLD, ierr)
-        ELSE
-            CALL MPI_Bcast(dftphireal(:,m), nrank(1)*nrank(2), db_type, 0, MPI_COMM_WORLD, ierr)
-            CALL MPI_Bcast(dftphiimag(:,m), nrank(1)*nrank(2), db_type, 0, MPI_COMM_WORLD, ierr)
-        END IF
-        IF(nlweb) THEN
-            tempcol = 0
-            tempcol(1:nbreducedspline) = reducedsolreal(:,m)
-            dftphireal(:,m) = vmx(etildet, tempcol)
-            tempcol(1:nbreducedspline) = reducedsolimag(:,m)
-            dftphiimag(:,m) = vmx(etildet, tempcol)
-        END IF
-        ! DEALLOCATE(reducedsolreal,reducedsolimag)
-        !$OMP END MASTER
-	    !$OMP BARRIER
-    END DO
-
-    ! Compute the inverse DFT of the potential
-    ALLOCATE(dftphitemp(nthet/2+1,nrank(1)*nrank(2)))
-    ALLOCATE(phitemp(nthet,nrank(1)*nrank(2)))
-
-    DO m=1,nthet/2+1
-        DO i=1,nrank(1)*nrank(2)
-            dftphitemp(m,i)=cmplx(dftphireal(i,m),dftphiimag(i,m))
         END DO
-    END DO
-    CALL dfftw_plan_many_dft_c2r(plan_m2theta,1,nthet,nrank(1)*nrank(2),dftphitemp,nthet/2+1,1,nthet/2+1,phitemp,nthet,1,nthet,FFTW_ESTIMATE)
-    CALL dfftw_execute_dft_c2r(plan_m2theta,dftphitemp,phitemp)
-    CALL dfftw_destroy_plan(plan_m2theta)
-    phi=transpose(phitemp)
 
-    ! Compute the inverse DFT of azimuthal derivative of potential
-    DO m=1,nthet/2+1
-        DO i=1,nrank(1)*nrank(2)
-            dftphitemp(m,i)=(m-1)*cmplx(0.0,1.0)*dftphitemp(m,i)
+        ! Compute the inverse DFT of the potential
+        DO m=1,nthet/2+1
+            DO i=1,nrank(1)*nrank(2)
+                dftphitemp(m,i)=cmplx(dftphireal(i,m),dftphiimag(i,m))
+            END DO
         END DO
-    END DO
-    CALL dfftw_plan_many_dft_c2r(plan_m2theta,1,nthet,nrank(1)*nrank(2),dftphitemp,nthet/2+1,1,nthet/2+1,phitemp,nthet,1,nthet,FFTW_ESTIMATE)
-    CALL dfftw_execute_dft_c2r(plan_m2theta,dftphitemp,phitemp)
-    CALL dfftw_destroy_plan(plan_m2theta)
-    dphidthet=transpose(phitemp)
+        CALL dfftw_plan_many_dft_c2r(plan_m2theta,1,nthet,nrank(1)*nrank(2),dftphitemp,nthet/2+1,1,nthet/2+1,phitemp,nthet,1,nthet,FFTW_ESTIMATE)
+        CALL dfftw_execute_dft_c2r(plan_m2theta,dftphitemp,phitemp)
+        CALL dfftw_destroy_plan(plan_m2theta)
+        phi=transpose(phitemp)
+
+        ! Compute the inverse DFT of azimuthal derivative of potential
+        DO m=1,nthet/2+1
+            DO i=1,nrank(1)*nrank(2)
+                dftphitemp(m,i)=(m-1)*cmplx(0.0,1.0)*dftphitemp(m,i)
+            END DO
+        END DO
+        CALL dfftw_plan_many_dft_c2r(plan_m2theta,1,nthet,nrank(1)*nrank(2),dftphitemp,nthet/2+1,1,nthet/2+1,phitemp,nthet,1,nthet,FFTW_ESTIMATE)
+        CALL dfftw_execute_dft_c2r(plan_m2theta,dftphitemp,phitemp)
+        CALL dfftw_destroy_plan(plan_m2theta)
+        dphidthet=transpose(phitemp)
+    END IF
 
-    DEALLOCATE(phitemp)
-    DEALLOCATE(dftphitemp)
+    ! Distributes the result on all MPI workers
+    DO m=1,nthet
+        CALL MPI_Bcast(phi(:,m), nrank(1)*nrank(2), db_type, 0, MPI_COMM_WORLD, ierr)
+        CALL MPI_Bcast(dphidthet(:,m), nrank(1)*nrank(2), db_type, 0, MPI_COMM_WORLD, ierr)
+    END DO
 END SUBROUTINE poisson
 
 
 !---------------------------------------------------------------------------
 !> @author
 !> Patryk kaminski   EPFL/SPC
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !> @brief
 !> Solves Poisson equation using FEM. Distributes the result on all MPI workers.
 !---------------------------------------------------------------------------
 SUBROUTINE poisson2D
     USE basic, ONLY: rhs, nrank, nlend
     USE bsplines, ONLY: spline2d, gridval
     USE mumps_bsplines, ONLY: bsolve, vmx
     USE futils
     USE geometry
     INTEGER:: ierr, i, j, iend
     real(kind=db), allocatable::reducedrhs(:), reducedsol(:), tempcol(:)
     ALLOCATE(reducedrhs(nrank(1)*nrank(2)))
     ALLOCATE(reducedsol(nbreducedspline))
     ALLOCATE(tempcol(nrank(1)*nrank(2)))
 
     ! Solves Poisson equation
     IF(nlweb .and. mpirank .eq. 0) THEN ! We use the web-spline reduction for stability
         reducedrhs = vmx(etilde, rhs(:,1))
         CALL bsolve(reduccedmat(1), reducedrhs(1:nbreducedspline), reducedsol)
+        tempcol = 0
+        tempcol(1:nbreducedspline) = reducedsol
+        phiext = vmx(etildet, tempcol)
     ELSE IF(mpirank.eq.0) THEN
-        CALL bsolve(femat(1), rhs(:,1), phi(:,1))
+        CALL bsolve(femat(1), rhs(:,1), phiext)
     END IF
+    DEALLOCATE(reducedsol,reducedrhs,tempcol)
 
     ! Distributes the result on all MPI workers
-    !$OMP MASTER
-    IF(nlweb) THEN
-        CALL MPI_Bcast(reducedsol, nbreducedspline, db_type, 0, MPI_COMM_WORLD, ierr)
-    ELSE
-        CALL MPI_Bcast(phi(:,1), nrank(1)*nrank(2), db_type, 0, MPI_COMM_WORLD, ierr)
-    END IF
-    IF(nlweb) THEN
-        tempcol = 0
-        tempcol(1:nbreducedspline) = reducedsol
-        phi(:,1) = vmx(etildet, tempcol)
-    END IF
-    DEALLOCATE(reducedsol)
-    !$OMP END MASTER
-	!$OMP BARRIER
+    CALL MPI_Bcast(phiext, nrank(1)*nrank(2), db_type, 0, MPI_COMM_WORLD, ierr)
 END SUBROUTINE poisson2D
 
 
 !---------------------------------------------------------------------------
 !> @author
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !> @brief
 !> Computes the electric fields and potential at the particles position 
 !> and on the grid for diagnostics purposes
 !---------------------------------------------------------------------------
 SUBROUTINE Efield_comp(splinevar,p)
     USE basic, ONLY: thetgrid, invdthet, nthet, nlend
     USE geometry
     USE splinebound
     USE bsplines, ONLY: spline2d, gridval
     USE beam, ONLY: particles
     
     TYPE(spline2d) :: splinevar(:)
     TYPE(particles), INTENT(INOUT) :: p
     INTEGER :: i,j,k,m,iend,nbunch
     INTEGER :: thetindex
     REAL(kind=db) :: wthet, pot1, pot2, Er1, Er2, Ez1, Ez2, dphidthet1, dphidthet2, potext, Erext, Ezext
     REAL(kind=db), ALLOCATABLE :: gtildeloc(:,:) !,potext(:), Erext(:), Ezext(:)
     INTEGER:: Evalpot(2), EvalEr(2), EvalEz(2)
 
     Evalpot=(/0,0/)
     EvalEr=(/1,0/)
     EvalEz=(/0,1/)
 
     nbunch =  64 ! Particle bunch size
     ALLOCATE(gtildeloc(0:2,0:nbunch - 1))
     ! ALLOCATE(potext(nbunch), Erext(nbunch), Ezext(nbunch))
 
     ! Update the splines with phi
     DO m=1,nthet
         !$OMP DO SIMD collapse(2)
         DO j=1,nrank(2)
             DO i=1,nrank(1)
-                matcoef(i,j) = phi((j-1)*nrank(1)+i,m)
+                matcoef(i,j) = phi((j-1)*nrank(1)+i,m) + phiext((j-1)*nrank(1)+i)
             END DO
         END DO
         !$OMP END DO SIMD
         ! Update the ppform coefficients
         CALL updt_ppform2d(splinevar(m), matcoef)
         !$OMP BARRIER
     END DO
 
     ! Evaluate pot, Er, Ez at the particle position
     !$OMP DO SIMD
     DO i=1,p%Nploc,nbunch
         ! Avoid segmentation fault by accessing non relevant data
         iend=min(i+nbunch-1,p%Nploc)
-        CALL speval(splrz_ext, p%pos(1,i:iend), p%pos(3,i:iend),p%cellindex(1,i:iend),p%cellindex(3,i:iend), p%pot(i:iend),p%E(1,i:iend),p%E(3,i:iend)) ! external field
+        ! CALL speval(splrz_ext, p%pos(1,i:iend), p%pos(3,i:iend),p%cellindex(1,i:iend),p%cellindex(3,i:iend), p%pot(i:iend),p%E(1,i:iend),p%E(3,i:iend)) ! external field
         DO k=1,(iend-i+1)
             thetindex=p%cellindex(2,i+k-1)
             wthet = (p%pos(2,i+k-1)-thetgrid(thetindex))*invdthet
             IF(thetindex .eq. nthet-1) THEN
                 CALL speval1(splrz(thetindex+1), p%pos(1,i+k-1), p%pos(3,i+k-1),p%cellindex(1,i+k-1),p%cellindex(3,i+k-1), pot1, Er1, Ez1)
                 CALL speval1(splrz(1), p%pos(1,i+k-1), p%pos(3,i+k-1),p%cellindex(1,i+k-1),p%cellindex(3,i+k-1), pot2, Er2, Ez2)
             ELSE
                 CALL speval1(splrz(thetindex+1), p%pos(1,i+k-1), p%pos(3,i+k-1),p%cellindex(1,i+k-1),p%cellindex(3,i+k-1), pot1, Er1, Ez1)
                 CALL speval1(splrz(thetindex+2), p%pos(1,i+k-1), p%pos(3,i+k-1),p%cellindex(1,i+k-1),p%cellindex(3,i+k-1), pot2, Er2, Ez2)
             END IF
             !CALL speval1(splrz_ext, p%pos(1,i+k-1), p%pos(3,i+k-1),p%cellindex(1,i+k-1),p%cellindex(3,i+k-1), potext, Erext, Ezext)
-            p%pot(i+k-1)=p%pot(i+k-1)+(1-wthet)*pot1+wthet*pot2 !+potext
-            p%E(1,i+k-1)=p%E(1,i+k-1)+(1-wthet)*Er1+wthet*Er2 !+Erext
-            p%E(3,i+k-1)=p%E(3,i+k-1)+(1-wthet)*Ez1+wthet*Ez2 !+Ezext
+            p%pot(i+k-1)=(1-wthet)*pot1+wthet*pot2 !+potext+p%pot(i+k-1)
+            p%E(1,i+k-1)=(1-wthet)*Er1+wthet*Er2 !+Erext+p%E(1,i+k-1)
+            p%E(3,i+k-1)=(1-wthet)*Ez1+wthet*Ez2 !+Ezext+p%E(3,i+k-1)
         END DO
         CALL total_gtilde(p%pos(1,i:iend), p%pos(3,i:iend), gtildeloc(:,0:iend - i), p%geomweight(:,i:iend))
         p%E(3,i:iend) = -p%E(3,i:iend)*p%geomweight(0,i:iend) - p%pot(i:iend)*p%geomweight(1,i:iend) - gtildeloc(1,0:iend - i)
         p%E(1,i:iend) = -p%E(1,i:iend)*p%geomweight(0,i:iend) - p%pot(i:iend)*p%geomweight(2,i:iend) - gtildeloc(2,0:iend - i)
         p%pot(i:iend) = p%geomweight(0,i:iend)*p%pot(i:iend) + gtildeloc(0,0:iend - i)
     END DO
     !$OMP END DO SIMD NOWAIT
  
     ! On the root process, evaluate pot, Er, Ez on the grid for diagnostic purposes
     IF (mpirank .eq. 0 .and. (modulo(step, it2d) .eq. 0 .or. nlend)) THEN
         DO m=1,nthet
             !$OMP DO 
             DO i=1,size(pot,1),16
                 iend=min(size(pot,1),i+15)
                 CALL gridval(splinevar(m), vec1(i:iend), vec2(i:iend), pot(i:iend,m), Evalpot)
                 CALL gridval(splinevar(m), vec1(i:iend), vec2(i:iend), Er(i:iend,m), EvalEr)
                 CALL gridval(splinevar(m), vec1(i:iend), vec2(i:iend), Ez(i:iend,m), EvalEz)
-                Ez(i:iend,m) = - pot(i:iend,m)*gridwdir(1,i:iend) - Ez(i:iend,m)*gridwdir(0,i:iend) !- gtilde(1,i:iend)
-                Er(i:iend,m) = - pot(i:iend,m)*gridwdir(2,i:iend) - Er(i:iend,m)*gridwdir(0,i:iend) !- gtilde(2,i:iend)
-                pot(i:iend,m) = pot(i:iend,m)*gridwdir(0,i:iend) !+ gtilde(0,i:iend)
+                Ez(i:iend,m) = - pot(i:iend,m)*gridwdir(1,i:iend) - Ez(i:iend,m)*gridwdir(0,i:iend) - gtilde(1,i:iend)
+                Er(i:iend,m) = - pot(i:iend,m)*gridwdir(2,i:iend) - Er(i:iend,m)*gridwdir(0,i:iend) - gtilde(2,i:iend)
+                pot(i:iend,m) = pot(i:iend,m)*gridwdir(0,i:iend) + gtilde(0,i:iend)
                 ! Add the external field
-                Ez(i:iend,m) = Ez(i:iend,m) + Ezxt(i:iend)
-                Er(i:iend,m) = Er(i:iend,m) + Erxt(i:iend)
-                pot(i:iend,m) = pot(i:iend,m) + potxt(i:iend)
+                ! Ez(i:iend,m) = Ez(i:iend,m) + Ezxt(i:iend)
+                ! Er(i:iend,m) = Er(i:iend,m) + Erxt(i:iend)
+                ! pot(i:iend,m) = pot(i:iend,m) + potxt(i:iend)
             END DO
             !$OMP END DO NOWAIT
         END DO
     END IF
 
     ! Update the splines with dphi/dthet
     DO m=1,nthet
         !$OMP DO SIMD collapse(2)
         DO j=1,nrank(2)
             DO i=1,nrank(1)
                 matcoef(i,j) = dphidthet((j-1)*nrank(1)+i,m)
             END DO
         END DO
         !$OMP END DO SIMD
         ! Update the ppform coefficients
         CALL updt_ppform2d(splinevar(m), matcoef)
         !$OMP BARRIER
     END DO
 
     ! Evaluate Ethet at the particle position
     !$OMP DO SIMD
     DO i=1,p%Nploc,nbunch
         ! Avoid segmentation fault by accessing non relevant data
         iend=min(i+nbunch-1,p%Nploc)
         DO k=1,(iend-i+1)
             thetindex=p%cellindex(2,i+k-1)
             wthet = (p%pos(2,i+k-1)-thetgrid(thetindex))*invdthet
             IF(thetindex .eq. nthet-1) THEN
                 CALL speval1(splrz(thetindex+1), p%pos(1,i+k-1), p%pos(3,i+k-1),p%cellindex(1,i+k-1),p%cellindex(3,i+k-1), dphidthet1)
                 CALL speval1(splrz(1), p%pos(1,i+k-1), p%pos(3,i+k-1),p%cellindex(1,i+k-1),p%cellindex(3,i+k-1), dphidthet2)
             ELSE
                 CALL speval1(splrz(thetindex+1), p%pos(1,i+k-1), p%pos(3,i+k-1),p%cellindex(1,i+k-1),p%cellindex(3,i+k-1), dphidthet1)
                 CALL speval1(splrz(thetindex+2), p%pos(1,i+k-1), p%pos(3,i+k-1),p%cellindex(1,i+k-1),p%cellindex(3,i+k-1), dphidthet2)
             END IF
-            p%E(2,i+k-1)=p%geomweight(0,i+k-1)*((1-wthet)*dphidthet1+wthet*dphidthet2)/p%pos(1,i+k-1)
+            p%E(2,i+k-1)=-p%geomweight(0,i+k-1)*((1-wthet)*dphidthet1+wthet*dphidthet2)/p%pos(1,i+k-1)
         END DO
     END DO
     !$OMP END DO SIMD NOWAIT
  
     ! On the root process, evaluate Ethet on the grid for diagnostic purposes
     IF (mpirank .eq. 0 .and. (modulo(step, it2d) .eq. 0 .or. nlend)) THEN
         DO m=1,nthet
             !$OMP DO 
             DO i=1,size(Ethet,1),16
                 iend=min(size(pot,1),i+15)
                 CALL gridval(splinevar(m), vec1(i:iend), vec2(i:iend), Ethet(i:iend,m), Evalpot)
                 DO k=i,iend
                     IF(rgrid(modulo(k-1,nr+1)) .eq. 0) THEN
                         Ethet(k,m) = 0
                     ELSE
-                        Ethet(k,m) = 1/rgrid(modulo(k-1,nr+1))*Ethet(k,m)*gridwdir(0,k)
+                        Ethet(k,m) = -1/rgrid(modulo(k-1,nr+1))*Ethet(k,m)*gridwdir(0,k)
                     END IF
                 END DO
             END DO
             !$OMP END DO NOWAIT
         END DO
     END IF
 END SUBROUTINE Efield_comp
 
 
 !---------------------------------------------------------------------------
 !> @author
 !> Patryk kaminski   EPFL/SPC
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !>
 !> @brief
 !> Constucts the FEM matrix using bsplines initialized in fields_init
 !---------------------------------------------------------------------------
 SUBROUTINE fematrix(mat,m)
     USE bsplines
     USE geometry
     USE omp_lib
     USE sparse
     type(mumps_mat) :: mat
     INTEGER :: m
     REAL(kind=db), ALLOCATABLE :: xgauss(:, :), wgauss(:), wgeom(:, :)
     INTEGER, ALLOCATABLE :: f(:, :), aux(:)
     REAL(kind=db), ALLOCATABLE :: coefs(:)
     REAL(kind=db), ALLOCATABLE :: fun(:, :, :), fun2(:, :, :)
     REAL(kind=db)  :: contrib
     INTEGER, ALLOCATABLE :: idert(:, :), iderw(:, :), iderg(:, :)
     integer,allocatable:: iid(:),jid(:)
     INTEGER :: i, j, jt, iw, irow, jcol, mu, igauss, iterm, irow2, jcol2, mu2, kterms, gausssize
     kterms=8
     
     If (allocated(fun)) deallocate (fun)
     If (allocated(fun2)) deallocate (fun2)
     ALLOCATE (fun(1:femorder(1) + 1, 0:1,3*ngauss(1)*ngauss(2)), fun2(1:femorder(2) + 1, 0:1,3*ngauss(1)*ngauss(2)))
     If (allocated(wgeom)) deallocate (wgeom)
     ALLOCATE (wgeom(0:2,3*ngauss(1)*ngauss(2))) !Arrays keeping values of b-splines at gauss node
     ALLOCATE (f((femorder(1) + 1)*(femorder(2) + 1), 2), aux(femorder(1) + 1)) !Auxiliary arrays ordering bsplines
     ALLOCATE (idert(kterms, 2), iderw(kterms, 2), coefs(kterms), iderg(kterms, 2))
     ALLOCATE (iid(3*ngauss(1)*ngauss(2)), jid(3*ngauss(1)*ngauss(2))) !Pointers on the order of derivatives
 
     ! Constuction of auxiliary array ordering bsplines in given interval
     DO i = 1, (femorder(1) + 1)
         aux(i) = i
     END DO
     DO i = 1, (femorder(2) + 1)
         f((i - 1)*(femorder(1) + 1) + 1:i*(femorder(1) + 1), 1) = aux
         f((i - 1)*(femorder(1) + 1) + 1:i*(femorder(1) + 1), 2) = i
     END DO
     CALL coefeq(splrz(1)%sp1%knots(0:1), idert, iderw, iderg, coefs, kterms)
 
     ! Assemble FEM matrix
     !$OMP PARALLEL DO DEFAULT(SHARED), PRIVATE(j,i,xgauss,wgauss,gausssize,wgeom, igauss,jt,irow,jcol, mu, iw, irow2,jcol2, mu2, contrib, fun, fun2,iid,jid), collapse(2)
     DO j = 1, nz ! Loop on z position
         DO i = 1, nr ! Loop on r position
             ! Computation of gauss weight and position in r and z direction for gaussian integration
             CALL calc_gauss(splrz(1), ngauss, i, j, xgauss, wgauss, gausssize)
             iid=i
             jid=j
             IF(gausssize .gt. 1) THEN
                 CALL geom_weight(xgauss(1:gausssize, 1), xgauss(1:gausssize, 2), wgeom(:,1:gausssize))
                 CALL basfun(xgauss(1:gausssize, 1), splrz(1)%sp1, fun(:,:,1:gausssize), iid(1:gausssize))
                 CALL basfun(xgauss(1:gausssize, 2), splrz(1)%sp2, fun2(:,:,1:gausssize), jid(1:gausssize))
             END IF
             DO jt = 1, (1 + femorder(1))*(femorder(2) + 1)
                 irow = i + f(jt, 1) - 1; jcol = j + f(jt, 2) - 1
                 mu = irow + (jcol - 1)*nrank(1)
                 DO iw = 1, (1 + femorder(1))*(femorder(2) + 1)
                     irow2 = i + f(iw, 1) - 1; jcol2 = j + f(iw, 2) - 1
                     mu2 = irow2 + (jcol2 - 1)*nrank(1)
                     contrib=0.0_db
                     DO igauss = 1, gausssize ! Loop on gaussian weights and positions
                         DO iterm = 1, kterms ! Loop on the two integration dimensions
                             contrib = contrib+wgeom(iderg(iterm, 1),igauss)*wgeom(iderg(iterm, 2),igauss)* &
                             &   fun(f(jt, 1), idert(iterm, 1),igauss)*fun(f(iw, 1), idert(iterm, 2),igauss)* &
                             &   fun2(f(jt, 2), iderw(iterm, 1),igauss)*fun2(f(iw, 2), iderw(iterm, 2),igauss)* &
                             &   wgauss(igauss)*xgauss(igauss, 1) 
                         END DO
                         contrib = contrib + (m-1)**2*wgeom(0,igauss)*wgeom(0,igauss)*fun(f(jt, 1),0,igauss)*fun(f(iw, 1),0,igauss)*fun2(f(jt, 2),0,igauss)*fun2(f(iw, 2),0,igauss)*wgauss(igauss)/xgauss(igauss,1)
                     END DO
                     CALL omp_set_lock(mu_lock(mu))
                     CALL updt_sploc(mat%mat%row(mu), mu2, contrib)
                     CALL omp_unset_lock(mu_lock(mu))
                 END DO
             END DO
         END DO
     END DO
     !$OMP END PARALLEL DO
 
     DEALLOCATE (f, aux)
     DEALLOCATE (idert, iderw, coefs, fun, fun2)
 END SUBROUTINE fematrix
 
 
 !---------------------------------------------------------------------------
 !> @author
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !> @brief
 !> Computes the volume of the splines cells needed to display the density in post-processing
 !---------------------------------------------------------------------------
 SUBROUTINE comp_volume
 
     USE bsplines
     USE geometry
     USE basic, ONLY: Volume,nrank,rnorm,nthet
 
     REAL(kind=db), ALLOCATABLE :: xgauss(:, :), wgauss(:), wgeom(:, :)
     INTEGER, ALLOCATABLE :: f(:, :), aux(:)
     REAL(kind=db), ALLOCATABLE :: coefs(:)
     REAL(kind=db), ALLOCATABLE :: fun(:, :), fun2(:, :), ftestpt(:, :)
     Integer, ALLOCATABLE, Dimension(:) :: idg, idt, idp, idw
     INTEGER :: i, j, jt, irow, jcol, mu, igauss, gausssize, iterm, nterms
     Real(kind=db)::newcontrib
 
     CALL timera(0, "comp_volume")
     
     ALLOCATE(fun(1:femorder(1) + 1, 0:1), fun2(1:femorder(2) + 1, 0:1)) ! Arrays keeping values of b-splines at gauss node
     ALLOCATE(f((femorder(1) + 1)*(femorder(2) + 1), 2), aux(femorder(1) + 1)) ! Auxiliary arrays ordering bsplines
     nterms = 4
     ALLOCATE(idg(nterms), idt(nterms), idw(nterms), idp(nterms), coefs(nterms))
     ! Constuction of auxiliary array ordering bsplines in given interval
     DO i = 1, (femorder(1) + 1)
         aux(i) = i
     END DO
     DO i = 1, (femorder(2) + 1)
         f((i - 1)*(femorder(1) + 1) + 1:i*(femorder(1) + 1), 1) = aux
         f((i - 1)*(femorder(1) + 1) + 1:i*(femorder(1) + 1), 2) = i
     END DO
 
       volume = 0
       volume = 0
       if (walltype .lt. 0) fverif = 0
 
     volume = 0  
       if (walltype .lt. 0) fverif = 0
 
     ! Assemble Volume matrix
     !$OMP PARALLEL DO DEFAULT(SHARED) PRIVATE(j,i,xgauss,wgauss,gausssize,wgeom, igauss, ftestpt, iterm,jt,irow,jcol, mu, idw, idt, idg, idp, coefs, fun, fun2, newcontrib), collapse(2)
     DO j = 1, nz ! Loop on z position
         DO i = 1, nr ! Loop on r position
             ! Computation of gauss weight and position in r and z direction for gaussian integration
             Call calc_gauss(splrz(1), ngauss, i, j, xgauss, wgauss, gausssize)
             IF(allocated(wgeom)) DEALLOCATE(wgeom)
             IF(gausssize .gt. 0) THEN
                 ALLOCATE(wgeom(0:2,size(xgauss, 1)))
                 CALL geom_weight(xgauss(:, 1), xgauss(:, 2), wgeom)
             END IF
             DO igauss = 1, gausssize ! Loop on gaussian weights and positions
                 CALL basfun(xgauss(igauss, 1), splrz(1)%sp1, fun, i)
                 CALL basfun(xgauss(igauss, 2), splrz(1)%sp2, fun2, j)
                 DO jt = 1, (1 + femorder(1))*(femorder(2) + 1)
                     irow = i + f(jt, 1) - 1; 
                     jcol = j + f(jt, 2) - 1
                     mu = irow + (jcol - 1)*nrank(1)
                     newcontrib = 2*pi*fun(f(jt, 1), 0)*fun2(f(jt, 2), 0)*wgauss(igauss)*xgauss(igauss, 1)!*wgeom(igauss,0)
                     !$OMP ATOMIC UPDATE
                     volume(mu) = volume(mu) + newcontrib*rnorm**3
                     !$OMP END ATOMIC
                 END DO
             END DO
         END DO
     END DO
     !$OMP END PARALLEL DO
     DEALLOCATE (f, aux)
     DEALLOCATE (fun, fun2)
     volume=volume/nthet
 
     CALL timera(1, "comp_volume")
 END SUBROUTINE comp_volume
 
 
 !---------------------------------------------------------------------------
 !> @author
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !>
 !> @brief
 !> Computes the gradient of the gtilde function for the web-spline method needed to correctly apply the dirichlet boundary conditions
 !---------------------------------------------------------------------------
 
    SUBROUTINE comp_gradgtilde
 
       USE bsplines
       USE geometry
 
       REAL(kind=db), ALLOCATABLE :: xgauss(:, :), wgauss(:), wgeom(:, :)
       INTEGER, ALLOCATABLE :: f(:, :), aux(:)
       REAL(kind=db), ALLOCATABLE :: coefs(:)
       REAL(kind=db), ALLOCATABLE :: fun(:, :,:), fun2(:, :,:), gtildeintegr(:, :)
       Integer, ALLOCATABLE, Dimension(:) :: idg, idt, idp, idw
       integer,allocatable:: iid(:),jid(:)
       INTEGER :: i, j, jt, irow, jcol, mu, igauss, gausssize, iterm, nterms
       Real(kind=db)::newcontrib
 
       !call timera(0, "comp_gradgtilde")
 
       ALLOCATE (fun(1:femorder(1) + 1, 0:1,3*ngauss(1)*ngauss(2)), fun2(1:femorder(2) + 1, 0:1,3*ngauss(1)*ngauss(2)))!Arrays keeping values of b-splines at gauss node
       ALLOCATE (wgeom(0:2,3*ngauss(1)*ngauss(2)))!Arrays keeping values of b-splines at gauss node
       ALLOCATE (f((femorder(1) + 1)*(femorder(2) + 1), 2), aux(femorder(1) + 1)) !Auxiliary arrays ordering bsplines
       nterms = 4
       Allocate (idg(nterms), idt(nterms), idw(nterms), idp(nterms), coefs(nterms))
       ALLOCATE (iid(3*ngauss(1)*ngauss(2)), jid(3*ngauss(1)*ngauss(2)))
 
       If (allocated(gtildeintegr)) deallocate (gtildeintegr)
       ALLOCATE (gtildeintegr(0:2,3*ngauss(1)*ngauss(2)))
 
 ! Constuction of auxiliary array ordering bsplines in given interval
       DO i = 1, (femorder(1) + 1)
          aux(i) = i
       END DO
       DO i = 1, (femorder(2) + 1)
          f((i - 1)*(femorder(1) + 1) + 1:i*(femorder(1) + 1), 1) = aux
          f((i - 1)*(femorder(1) + 1) + 1:i*(femorder(1) + 1), 2) = i
       END DO
       CALL coefeqext(splrz(1)%sp1%knots(0:1), idt, idw, idg, idp, coefs)
 
       !$OMP DO SIMD
       do j=1,size(gradgtilde)
          gradgtilde(j) = 0
       END DO
       !$OMP END DO SIMD
       !$OMP BARRIER
       ! Assemble gradgtilde matrix
       !$OMP DO collapse(2)
       DO j = 1, nz ! Loop on z position
          DO i = 1, nr        ! Loop on r position
             ! Computation of gauss weight and position in r and z direction for gaussian integration
             Call calc_gauss(splrz(1), ngauss, i, j, xgauss, wgauss, gausssize)
             iid=i
             jid=j
             if (gausssize .gt. 1) then
                !If (allocated(wgeom)) deallocate (wgeom)
                !ALLOCATE (wgeom(0:2,gausssize))
                CALL geom_weight(xgauss(1:gausssize, 1), xgauss(1:gausssize, 2), wgeom(:,1:gausssize))
                CALL basfun(xgauss(1:gausssize, 1), splrz(1)%sp1, fun(:,:,1:gausssize), iid(1:gausssize))
                CALL basfun(xgauss(1:gausssize, 2), splrz(1)%sp2, fun2(:,:,1:gausssize), jid(1:gausssize))
                Call total_gtilde(xgauss(1:gausssize, 1), xgauss(1:gausssize, 2), gtildeintegr(:,1:gausssize),wgeom(:,1:gausssize))
             End if
             DO jt = 1, (1 + femorder(1))*(femorder(2) + 1)
                irow = i + f(jt, 1) - 1; jcol = j + f(jt, 2) - 1
                mu = irow + (jcol - 1)*nrank(1)
                newcontrib = 0.0_db
                DO igauss = 1, gausssize ! Loop on gaussian weights and positions
                   
                   Do iterm = 1, nterms
                      newcontrib = newcontrib + wgeom( idg(iterm),igauss)*gtildeintegr( idp(iterm),igauss)* &
                      &   fun(f(jt, 1), idt(iterm),igauss)*fun2(f(jt, 2), idw(iterm),igauss)* &
                      &   wgauss(igauss)*xgauss(igauss, 1)
                   End do
                end do
                !$OMP ATOMIC UPDATE
                gradgtilde(mu) = gradgtilde(mu) + newcontrib
                !$OMP END ATOMIC
             END DO
          END DO
       END DO
       !$OMP END DO
 
       !DEALLOCATE(xgauss, wgauss,zg,rg, wzg, wrg)
       DEALLOCATE (f, aux)
       DEALLOCATE (fun, fun2)
 
       !call timera(1, "comp_gradgtilde")
 
    END SUBROUTINE comp_gradgtilde
 
 
 !---------------------------------------------------------------------------
 !> @author
 !> Patryk kaminski   EPFL/SPC
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !>
 !> @brief
 !> Imposes the dirichlet boundary conditions on the FEM matrix for the case where we use regular splines ( not web-splines).
 !---------------------------------------------------------------------------
    SUBROUTINE fe_dirichlet
       REAL(kind=db), ALLOCATABLE :: arr(:)
       INTEGER :: i
       ALLOCATE (arr(nrank(1)*nrank(2)))
       DO i = 1, nrank(1)
          IF (rgrid(0) .ne. 0.0_db) THEN
             arr = 0; arr(i) = 1;
             CALL putrow(femat(1), i, arr)
          END IF
          arr = 0; arr(nrank(1)*nrank(2) + 1 - i) = 1;
          CALL putrow(femat(1), nrank(1)*nrank(2) + 1 - i, arr)
       END DO
       DEALLOCATE (arr)
    END SUBROUTINE fe_dirichlet
 !________________________________________________________________________________
    SUBROUTINE coefeq(x, idt, idw, idg, c, kterms)
       REAL(kind=db), INTENT(in) :: x(:)
       INTEGER, INTENT(out) :: idt(:, :), idw(:, :), idg(:, :),kterms
       REAL(kind=db), INTENT(out) :: c(:)
       kterms=8
 
 
       c = x(2)
       idt(1, 1) = 0
       idt(1, 2) = 0
       idw(1, 1) = 0
       idw(1, 2) = 0
       idg(1, 1) = 1
       idg(1, 2) = 1
       idt(2, 1) = 0
       idt(2, 2) = 0
       idw(2, 1) = 0
       idw(2, 2) = 1
       idg(2, 1) = 1
       idg(2, 2) = 0
       idt(3, 1) = 0
       idt(3, 2) = 0
       idw(3, 1) = 1
       idw(3, 2) = 0
       idg(3, 1) = 0
       idg(3, 2) = 1
       idt(4, 1) = 0
       idt(4, 2) = 0
       idw(4, 1) = 1
       idw(4, 2) = 1
       idg(4, 1) = 0
       idg(4, 2) = 0
       idt(5, 1) = 0
       idt(5, 2) = 0
       idw(5, 1) = 0
       idw(5, 2) = 0
       idg(5, 1) = 2
       idg(5, 2) = 2
       idt(6, 1) = 0
       idt(6, 2) = 1
       idw(6, 1) = 0
       idw(6, 2) = 0
       idg(6, 1) = 2
       idg(6, 2) = 0
       idt(7, 1) = 1
       idt(7, 2) = 0
       idw(7, 1) = 0
       idw(7, 2) = 0
       idg(7, 1) = 0
       idg(7, 2) = 2
       idt(8, 1) = 1
       idt(8, 2) = 1
       idw(8, 1) = 0
       idw(8, 2) = 0
       idg(8, 1) = 0
       idg(8, 2) = 0
    END SUBROUTINE coefeq
 
    SUBROUTINE coefeqext(x, idt, idw, idg, idp, c)
       REAL(kind=db), INTENT(in) :: x(:)
       INTEGER, INTENT(out) :: idp(:), idt(:), idw(:), idg(:)
       REAL(kind=db), INTENT(out) :: c(:)
 
       c(1) = x(2)
       idp(1) = 1
       idg(1) = 1
       idt(1) = 0
       idw(1) = 0
       c(2) = x(2)
       idp(2) = 1
       idg(2) = 0
       idt(2) = 0
       idw(2) = 1
       c(3) = x(2)
       idp(3) = 2
       idg(3) = 2
       idt(3) = 0
       idw(3) = 0
       c(4) = x(2)
       idp(4) = 2
       idg(4) = 0
       idt(4) = 1
       idw(4) = 0
    END SUBROUTINE coefeqext
 
 !---------------------------------------------------------------------------
 !> @author
 !> Patryk kaminski   EPFL/SPC
 !> Guillaume Le Bars EPFL/SPC
 !
 ! DESCRIPTION:
 !>
 !> @brief
 !> Free the memory used by the fields module
 !---------------------------------------------------------------------------
 SUBROUTINE clean_fields
     USE bsplines
     USE basic, ONLY: rhs
     INTEGER:: i,m
     DO i = 1, nrank(1)*nrank(2)
         CALL omp_destroy_lock(mu_lock(i))
     END DO
     DEALLOCATE(mu_lock)
     DEALLOCATE(matcoef)
     DEALLOCATE(pot)
     DEALLOCATE(rhs)
     DEALLOCATE(dftrhsreal)
     DEALLOCATE(dftrhsimag)
     DEALLOCATE(loc_rhs)
     DEALLOCATE(loc_moments)
     DEALLOCATE(phi)
     DEALLOCATE(dphidthet)
     DEALLOCATE(dftphireal)
     DEALLOCATE(dftphiimag)
     DEALLOCATE(Br,Bz)
     DEALLOCATE(Er,Ethet,Ez)
     DEALLOCATE(vec1,vec2)
     DO m=1,nthet
         CALL DESTROY_SP(splrz(m))
     END DO
     DEALLOCATE(splrz)
     CALL DESTROY_SP(splrz_ext)
 END SUBROUTINE clean_fields
 
 
    SUBROUTINE updt_sploc(arow, j, val)
       !
       !   Update element j of row arow or insert it in an increasing "index"
       !
       USE sparse
       TYPE(sprow), TARGET          :: arow
       INTEGER, INTENT(in)          :: j
       DOUBLE PRECISION, INTENT(in) :: val
       !
       TYPE(elt), TARGET :: pre_root
       TYPE(elt), POINTER :: t, p
       !
       if(val.eq.0) return
       pre_root%next => arow%row0 ! pre_root is linked to the head of the list.
       t => pre_root
       DO WHILE (ASSOCIATED(t%next))
          p => t%next
          IF (p%index .EQ. j) THEN
             p%val = p%val + val
             RETURN
          END IF
          IF (p%index .GT. j) EXIT
          t => t%next
       END DO
       ALLOCATE (p)
       p = elt(j, val, t%next)
       t%next => p
       !
       arow%nnz = arow%nnz + 1
       arow%row0 => pre_root%next ! In case the head is altered
    END SUBROUTINE updt_sploc
 
 
 SUBROUTINE updt_ppform2d(sp,c)
     USE bsplines
     TYPE(spline2d), INTENT(inout) :: sp
     DOUBLE PRECISION, DIMENSION(:,:), INTENT(in) :: c
     !DOUBLE PRECISION, ALLOCATABLE :: work(:,:,:)
     INTEGER:: i,m,mm
     INTEGER :: d1, d2, k1, k2, n1, n2
 
     d1 = sp%sp1%dim
     d2 = sp%sp2%dim
     k1 = sp%sp1%order
     k2 = sp%sp2%order
     n1 = sp%sp1%nints
     n2 = sp%sp2%nints
 
     !$OMP SINGLE
     IF( ASSOCIATED(sp%bcoefs) ) DEALLOCATE(sp%bcoefs)
     ALLOCATE(sp%bcoefs(SIZE(c,1),SIZE(c,2)))
     !$OMP END SINGLE
 
     !ALLOCATE(work(d2,k1,n1))
     !$OMP DO
     DO m=1,SIZE(c,2)
         CALL topp0(sp%sp1, c(:,m), ppformwork(m,:,:))
         sp%bcoefs(:,m)=c(:,m)
     END DO
     !$OMP END DO NOWAIT
 
     !$OMP SINGLE
     IF( ASSOCIATED(sp%ppform) ) DEALLOCATE(sp%ppform)
     ALLOCATE(sp%ppform(k1,n1,k2,n2))
     !$OMP END SINGLE
 
     !$OMP DO 
     DO mm=1,SIZE(ppformwork,3)
         DO m=1,SIZE(ppformwork,2)
             CALL topp0(sp%sp2, ppformwork(:,m,mm), sp%ppform(m,mm,:,:))
         END DO
     END DO
     !$OMP END DO
     !DEALLOCATE(work)
 END SUBROUTINE updt_ppform2d
 
 
    !===========================================================================
   SUBROUTINE topp0(sp, c, ppform)
    !
    !   Compute PPFORM of a fuction defined by the spline SP
    !   and spline coefficients C(1:d)
    !
        use bsplines
        TYPE(spline1d), INTENT(in) :: sp
        DOUBLE PRECISION, INTENT(in) :: c(:)
        DOUBLE PRECISION, INTENT(out) :: ppform(0:,:)
        INTEGER :: p, nints, i, j, k
    !
        p = sp%order - 1
        nints = sp%nints
    !
        ppform = 0.0d0
        DO i=1,nints       ! on each knot interval
           DO j=1,p+1      ! all spline in interval i
              DO k=0,p     ! k_th derivatives
                 ppform(k,i) = ppform(k,i) + sp%val0(k,j,i)*c(j+i-1)
              END DO
           END DO
        END DO
    !
      END SUBROUTINE topp0
    !+
 END MODULE fields
diff --git a/src/mpihelper_mod.f90_old b/src/mpihelper_mod.f90_old
deleted file mode 100644
index 764c19d..0000000
--- a/src/mpihelper_mod.f90_old
+++ /dev/null
@@ -1,401 +0,0 @@
-!------------------------------------------------------------------------------
-! EPFL/Swiss Plasma Center
-!------------------------------------------------------------------------------
-!
-! MODULE: mpihelper
-!
-!> @author
-!> Guillaume Le Bars EPFL/SPC
-!
-! DESCRIPTION: 
-!> Module responsible for setting up the MPI variables used in the communications.
-!------------------------------------------------------------------------------
-
-MODULE mpihelper
-    USE constants
-    use mpi
-    USE particletypes
-    
-    IMPLICIT NONE
-    
-    INTEGER, SAVE :: basicdata_type=MPI_DATATYPE_NULL      !< Stores the MPI data type used for communicating basicdata
-    INTEGER, SAVE :: particle_type=MPI_DATATYPE_NULL       !< Stores the MPI data type used for particles communication between nodes
-      !INTEGER, SAVE :: particles_type=MPI_DATATYPE_NULL      !< Stores the MPI data type used for particles gathering on node 0 and broadcast from node 0
-    INTEGER, SAVE :: rhsoverlap_type=MPI_DATATYPE_NULL     !< Stores the MPI data type used for the communication of a rhs column
-    INTEGER, SAVE :: densityoverlap_type=MPI_DATATYPE_NULL
-    INTEGER, SAVE :: db_type=MPI_DATATYPE_NULL             !< Stores the MPI data type used for the communication of a REAL(kind=db)
-    INTEGER, SAVE :: momentsoverlap_type=MPI_DATATYPE_NULL !< Stores the MPI data type used for the communication of a column of a grid variable
-    INTEGER, SAVE :: rcvrhsoverlap_type=MPI_DATATYPE_NULL      !< Stores the MPI data type used for the receive communication of a rhs column
-    INTEGER, SAVE :: rcvdensityoverlap_type=MPI_DATATYPE_NULL
-    INTEGER, SAVE :: rcvmomentsoverlap_type=MPI_DATATYPE_NULL  !< Stores the MPI data type used for the receive communication of a column of a grid variable
-    INTEGER, SAVE:: db_sum_op               !< Store the MPI sum operation for db_type
-      REAL(kind=db), ALLOCATABLE, SAVE:: rhsoverlap_buffer(:)     !< buffer used for storing the rhs ghost cells 
-                                                                     !< received from the left or right MPI process
-      REAL(kind=db), ALLOCATABLE, SAVE:: densityoverlap_buffer(:)
-      REAL(kind=db), ALLOCATABLE, SAVE:: momentsoverlap_buffer(:) !< buffer used for storing the moments ghost cells 
-                                                                     !< received from the left or right MPI process
-      !INTEGER, SAVE:: momentsoverlap_requests(2) = MPI_REQUEST_NULL
-      !INTEGER, SAVE:: rhsoverlap_requests(2)     = MPI_REQUEST_NULL
-      INTEGER:: rhsoverlap_tag= 200
-      INTEGER:: densityoverlap_tag=400
-      INTEGER:: momentsoverlap_tag= 300
-      INTEGER:: partsgather_tag= 500
-      INTEGER:: partsexchange_tag=600
-      INTEGER:: nbpartsexchange_tag=700
-    
-    
-      CONTAINS 
-      
-    !---------------------------------------------------------------------------  
-    !> @author 
-    !> Guillaume Le Bars EPFL/SPC
-    !
-    ! DESCRIPTION: 
-    !> 
-    !> @brief
-    !> Initialize the MPI types used for inter process communications
-    !
-    !---------------------------------------------------------------------------  
-      SUBROUTINE mpitypes_init
-        IMPLICIT NONE
-        INTEGER:: ierr
-        ! Initialize db_type to use real(kind=db) in MPI and the sum operator for reduce
-        CALL MPI_TYPE_CREATE_F90_REAL(dprequestedprec,MPI_UNDEFINED,db_type,ierr)
-        CALL MPI_Type_commit(db_type,ierr)
-        CALL MPI_Op_Create(DB_sum, .true., db_sum_op, ierr)
-    
-    
-        CALL init_particlempi
-    
-      END SUBROUTINE mpitypes_init
-    
-    !---------------------------------------------------------------------------  
-    !> @author 
-    !> Guillaume Le Bars EPFL/SPC
-    !
-    ! DESCRIPTION: 
-    !> 
-    !> @brief
-    !> Computes the sum in MPI_Reduce operations involving Real(kinc=db)
-    !
-    !---------------------------------------------------------------------------  
-    
-      SUBROUTINE DB_sum(INVEC, INOUTVEC, LEN, TYPE)bind(c)
-        !REAL(kind=db):: INVEC(0:LEN-1), INOUTVEC(0:LEN-1)
-        use, intrinsic:: iso_c_binding, ONLY: c_ptr,c_f_pointer
-        use mpi
-        implicit none
-        TYPE(C_PTR), VALUE:: invec, inoutvec 
-        real(kind=db),pointer:: ivec(:), iovec(:)
-        INTEGER:: LEN
-        INTEGER:: TYPE
-        INTEGER:: i
-    
-        call c_f_pointer(INVEC,ivec, (/len/))
-        call c_f_pointer(inoutvec,iovec, (/len/))
-        Do i=1,LEN
-          IOVEC(i)=IVEC(i)+IOVEC(i)
-        END DO
-    
-    
-    
-      END SUBROUTINE DB_sum
-    
-    !--------------------------------------------------------------------------  
-    !> @author 
-    !> Guillaume Le Bars EPFL/SPC
-    !
-    ! DESCRIPTION: 
-    !> 
-    !> @brief
-    !> Initialize the MPI communicators used for allreduce between neighbors
-    !
-    !> @param[in] nrank ranks of the FEM array in (1) z direction and (2) r direction
-    !> @param[in] femorder finite element method order in z and r direction
-    !> @param[in] zlimleft z index delimiting the mpi local left boundary 
-    !> @param[in] zlimright z index delimiting the mpi local right boundary
-    !> @param[in] nbmoments number of moments calculated and stored. 
-    !
-    !---------------------------------------------------------------------------  
-      SUBROUTINE init_overlaps(nrank, femorder, zlimleft, zlimright, nbmoments)
-        INTEGER, INTENT(IN):: nrank(:), femorder(:), zlimright, zlimleft, nbmoments
-    
-        IF(ALLOCATED(rhsoverlap_buffer)) DEALLOCATE(rhsoverlap_buffer)
-        IF(ALLOCATED(densityoverlap_buffer)) DEALLOCATE(densityoverlap_buffer)
-        IF(ALLOCATED(momentsoverlap_buffer)) DEALLOCATE(momentsoverlap_buffer)
-        ALLOCATE(rhsoverlap_buffer(nrank(1)*femorder(2)))
-        ALLOCATE(densityoverlap_buffer(nrank(1)*femorder(2)))
-        ALLOCATE(momentsoverlap_buffer(nbmoments*nrank(1)*femorder(2)))
-        
-        ! Initialize the MPI column overlap type for rhs
-        CALL init_coltypempi(nrank(2), zlimright-zlimleft+femorder(2), 1, 1, db_type, rhsoverlap_type)
-        CALL init_coltypempi(nrank(2), zlimright-zlimleft+femorder(2), 1, 1, db_type, densityoverlap_type)
-      ! Initialize the MPI grid col type
-        CALL init_coltypempi(nrank(2), zlimright-zlimleft+femorder(2), nbmoments, 1, db_type, momentsoverlap_type)
-        ! Initialize the MPI receive column overlap type for rhs
-        CALL init_coltypempi(nrank(1), nrank(2), 1, 1, db_type, rcvrhsoverlap_type)
-        CALL init_coltypempi(nrank(1), nrank(2), 1, 1, db_type, rcvdensityoverlap_type)
-      ! Initialize the MPI receive grid col type
-        CALL init_coltypempi(nrank(1), nrank(2), nbmoments, 1, db_type, rcvmomentsoverlap_type)
-    
-      END SUBROUTINE init_overlaps
-    
-    
-    SUBROUTINE start_persistentcomm(requests, mpirank, leftproc, rightproc)
-    INTEGER,INTENT(INOUT):: requests(:)
-    INTEGER, INTENT(IN):: mpirank, leftproc, rightproc
-    INTEGER:: ierr
-    INTEGER:: stats(MPI_STATUS_SIZE,2)
-    LOGICAL:: completed=.false.
-     
-        IF(leftproc .lt. mpirank) THEN
-        ! Start to receive
-          CALL MPI_START(requests(2),ierr)
-           IF(IERR .ne. MPI_SUCCESS) WRITE(*,*) "error in recv_init"
-        END IF
-       
-        IF(rightproc .gt. mpirank) THEN
-        ! Start to send
-          CALL MPI_START(requests(1),ierr)
-          IF(IERR .ne. MPI_SUCCESS) WRITE(*,*) "error in send_init"
-        END IF
-    
-        IF(leftproc .lt. mpirank) THEN
-        ! Start to receive
-          completed=.FALSE.
-          DO WHILE(.not. completed)
-            CALL MPI_TEST(requests(2), completed,stats(:,2),ierr)
-          END DO
-           WRITE(*,*)"status 2", completed, stats(:,2)
-          !CALL MPI_WAIT(requests(2),stats(:,2),ierr)
-          !WRITE(*,*)"status 2", stats(:,2)
-          IF(IERR .ne. MPI_SUCCESS) WRITE(*,*) "error in recv_init"
-        END IF
-       
-        IF(rightproc .gt. mpirank) THEN
-        ! Start to send
-          completed=.FALSE.
-          DO WHILE(.not. completed)
-            CALL MPI_TEST(requests(1), completed,stats(:,1),ierr)
-          END DO
-          !CALL MPI_WAIT(requests(1),stats(:,1),ierr)
-          IF(IERR .ne. MPI_SUCCESS) WRITE(*,*) "error in send_init"
-        END IF
-    END SUBROUTINE start_persistentcomm
-    
-    
-    SUBROUTINE rhsoverlapcomm(mpirank, leftproc, rightproc, moments, nrank, femorder, zlimright)
-    INTEGER, INTENT(IN):: mpirank, leftproc, rightproc
-    REAL(kind=db), DIMENSION(:), INTENT(INOUT):: moments
-    INTEGER, INTENT(IN):: nrank(2), femorder(2), zlimright
-    INTEGER, SAVE:: rhsoverlap_requests(2)     = MPI_REQUEST_NULL
-    INTEGER:: ierr
-    INTEGER:: stats(MPI_STATUS_SIZE,2)
-        rhsoverlap_requests=MPI_REQUEST_NULL
-        rhsoverlap_buffer=0
-        IF(rightproc .gt. mpirank .and. rightproc .ge. 0) THEN
-          CALL MPI_ISEND(moments(zlimright*nrank(1)+1), femorder(2)*nrank(1), db_type, rightproc, rhsoverlap_tag, &
-          &                  MPI_COMM_WORLD, rhsoverlap_requests(1), ierr )
-        END IF
-    
-        ! If the processor on the left has actually lower z positions  
-        IF(leftproc .lt. mpirank .and. leftproc .ge. 0) THEN
-          CALL MPI_IRECV(rhsoverlap_buffer, nrank(1)*(femorder(2)), db_type, leftproc, rhsoverlap_tag, &
-          &                  MPI_COMM_WORLD, rhsoverlap_requests(2), ierr )
-        END IF
-     
-        CALL MPI_WAITALL(2,rhsoverlap_requests,stats, ierr)
-    END SUBROUTINE rhsoverlapcomm
-
-    SUBROUTINE densityoverlapcomm(mpirank, leftproc, rightproc, moments, nrank, femorder, zlimright)
-        INTEGER, INTENT(IN):: mpirank, leftproc, rightproc
-        REAL(kind=db), DIMENSION(:), INTENT(INOUT):: moments
-        INTEGER, INTENT(IN):: nrank(2), femorder(2), zlimright
-        INTEGER, SAVE:: densityoverlap_requests(2)     = MPI_REQUEST_NULL
-        INTEGER:: ierr
-        INTEGER:: stats(MPI_STATUS_SIZE,2)
-            densityoverlap_requests=MPI_REQUEST_NULL
-            densityoverlap_buffer=0
-            IF(rightproc .gt. mpirank .and. rightproc .ge. 0) THEN
-              CALL MPI_ISEND(moments(zlimright*nrank(1)+1), femorder(2)*nrank(1), db_type, rightproc, densityoverlap_tag, &
-              &                  MPI_COMM_WORLD, densityoverlap_requests(1), ierr )
-            END IF
-        
-            ! If the processor on the left has actually lower z positions  
-            IF(leftproc .lt. mpirank .and. leftproc .ge. 0) THEN
-              CALL MPI_IRECV(densityoverlap_buffer, nrank(1)*(femorder(2)), db_type, leftproc, densityoverlap_tag, &
-              &                  MPI_COMM_WORLD, densityoverlap_requests(2), ierr )
-            END IF
-         
-            CALL MPI_WAITALL(2,densityoverlap_requests,stats, ierr)
-        END SUBROUTINE densityoverlapcomm
-    
-    SUBROUTINE momentsoverlapcomm(mpirank, leftproc, rightproc, moments, nrank, femorder, zlimright)
-    INTEGER, INTENT(IN):: mpirank, leftproc, rightproc
-    REAL(kind=db), DIMENSION(:,:), INTENT(INOUT):: moments
-    INTEGER, INTENT(IN):: nrank(2), femorder(2), zlimright
-    INTEGER, SAVE:: momentsoverlap_requests(2) = MPI_REQUEST_NULL
-    INTEGER:: ierr
-    INTEGER:: stats(MPI_STATUS_SIZE,2)
-        momentsoverlap_requests=MPI_REQUEST_NULL
-        momentsoverlap_buffer=0
-    
-        IF(rightproc .gt. mpirank .and. rightproc .ge. 0) THEN
-          CALL MPI_ISEND(moments(1,zlimright*nrank(1)+1), femorder(2)*nrank(1)*10, db_type, rightproc, momentsoverlap_tag, &
-          &                  MPI_COMM_WORLD, momentsoverlap_requests(1), ierr )
-        END IF
-    
-        ! If the processor on the left has actually lower z positions  
-        IF(leftproc .lt. mpirank .and. leftproc .ge. 0) THEN
-          CALL MPI_IRECV(momentsoverlap_buffer, 10*nrank(1)*(femorder(2)), db_type, leftproc, momentsoverlap_tag, &
-          &                  MPI_COMM_WORLD, momentsoverlap_requests(2), ierr )
-        END IF
-     
-        CALL MPI_WAITALL(2,momentsoverlap_requests,stats, ierr)
-    END SUBROUTINE momentsoverlapcomm
-    
-    !---------------------------------------------------------------------------  
-    !> @author 
-    !> Guillaume Le Bars EPFL/SPC
-    !
-    ! DESCRIPTION: 
-    !> 
-    !> @brief
-    !> Initialize the particle MPI type used for inter process communications and publish it to 
-    !> the process in the communicator
-    !
-    !---------------------------------------------------------------------------  
-      SUBROUTINE init_particlempi()
-          INTEGER :: nblock = 7
-          INTEGER:: blocklength(7)
-          INTEGER(kind=MPI_ADDRESS_KIND):: displs(7), displ0
-          INTEGER:: types(7)
-          TYPE(particle) :: part
-          INTEGER:: ierr
-           
-          CALL mpi_get_address(part%partindex, displs(1), ierr)
-          CALL mpi_get_address(part%cellindex, displs(2), ierr)
-          types(1:2)=MPI_INTEGER
-          CALL mpi_get_address(part%pos, displs(3), ierr)
-          CALL mpi_get_address(part%U, displs(4), ierr)
-          CALL mpi_get_address(part%geomweight, displs(5), ierr)
-          CALL mpi_get_address(part%GAMMA, displs(6), ierr)
-          CALL mpi_get_address(part%pot, displs(7), ierr)
-          types(3:7)=db_type
-          blocklength(1:7) = 1
-          blocklength(2:5) =3
-          CALL mpi_get_address(part, displ0, ierr)
-          displs=displs-displ0
-      
-    
-          CALL MPI_Type_create_struct(nblock, blocklength, displs, types, particle_type, ierr)
-          CALL MPI_Type_commit(particle_type,ierr)
-    
-      END SUBROUTINE init_particlempi
-    
-    
-    !---------------------------------------------------------------------------  
-    !> @author 
-    !> Guillaume Le Bars EPFL/SPC
-    !
-    ! DESCRIPTION: 
-    !> 
-    !> @brief
-    !> Initialize the particles MPI type used for gathering particles to the root and broadcast them and publish it to 
-    !> the process in the communicator
-    !
-    !---------------------------------------------------------------------------  
-      SUBROUTINE init_particles_gather_mpi(p,idstart,nsend,mpi_particles_type)
-        INTEGER:: mpi_particles_type
-        INTEGER:: nsend
-        INTEGER:: idstart
-        INTEGER :: nblock = 8
-        INTEGER:: blocklength(8)
-        INTEGER(kind=MPI_ADDRESS_KIND):: displs(8), displ0
-        INTEGER:: types(8)
-        TYPE(particles), INTENT(INOUT):: p
-        INTEGER:: ierr
-        INTEGER:: temptype
-    
-        IF(nsend .lt. 1) RETURN
-    
-        temptype=MPI_DATATYPE_NULL
-        IF( mpi_particles_type .ne. MPI_DATATYPE_NULL) CALL MPI_TYPE_FREE(mpi_particles_type,ierr)
-         
-        !CALL mpi_get_address(p%Rindex(idstart), displs(1), ierr)
-        !CALL mpi_get_address(p%Zindex(idstart), displs(2), ierr)
-        CALL mpi_get_address(p%cellindex(1,idstart), displs(1), ierr)
-        CALL mpi_get_address(p%partindex(idstart), displs(2), ierr)
-        types(1:2)=MPI_INTEGER
-        CALL mpi_get_address(p%pos(1,idstart), displs(3), ierr)
-        !CALL mpi_get_address(p%Z(idstart), displs(5), ierr)
-        !CALL mpi_get_address(p%THET(idstart), displs(6), ierr)
-        CALL mpi_get_address(p%pot(idstart), displs(4), ierr)
-        CALL mpi_get_address(p%U(1,idstart), displs(5), ierr)
-        CALL mpi_get_address(p%Uold(1,idstart), displs(6), ierr)
-        !CALL mpi_get_address(p%UTHET(idstart), displs(10), ierr)
-        !CALL mpi_get_address(p%UTHETold(idstart), displs(11), ierr)
-        !CALL mpi_get_address(p%UZ(idstart), displs(12), ierr)
-        !CALL mpi_get_address(p%UZold(idstart), displs(13), ierr)
-        
-        CALL mpi_get_address(p%GAMMA(idstart), displs(7), ierr)
-        CALL mpi_get_address(p%GAMMAold(idstart), displs(8), ierr)
-        types(3:8)=db_type
-        blocklength = nsend
-        blocklength(1)=3*nsend
-        blocklength(3)=3*nsend
-        blocklength(5:6)=3*nsend
-        CALL mpi_get_address(p, displ0, ierr)
-        displs=displs-displ0
-    
-        CALL MPI_Type_create_struct(nblock, blocklength, displs, types, mpi_particles_type, ierr)
-        CALL MPI_TYPE_COMMIT(mpi_particles_type, ierr)
-    
-    END SUBROUTINE init_particles_gather_mpi
-    
-    
-      !---------------------------------------------------------------------------  
-    !> @author Guillaume Le Bars EPFL/SPC
-    !
-    ! DESCRIPTION:  
-    !> @brief Initialize the column MPI type used for inter process communications and publish it to 
-    !> the processes in the communicator (can be rhs or grid quantities)
-    !
-    !> @param[in] nr number of elements in the r direction
-    !> @param[in] nz number of elements in the z direction
-    !> @param[in] init_type MPI type of the initial data
-    !> @param[inout] mpi_coltype final type usable in communications
-    !---------------------------------------------------------------------------  
-      SUBROUTINE init_coltypempi(nr, nz, block_size, stride, init_type, mpi_coltype)
-          INTEGER, INTENT(IN)    :: nr
-          INTEGER, INTENT(IN)    :: nz
-          INTEGER, INTENT(IN)    :: block_size
-          INTEGER, INTENT(IN)    :: stride
-          INTEGER, INTENT(IN)  :: init_type
-          INTEGER, INTENT(OUT) :: mpi_coltype
-          INTEGER :: temp_mpi_coltype
-          INTEGER:: ierr
-          INTEGER(KIND=MPI_ADDRESS_KIND):: init_type_lb, init_type_extent
-         !(nrank(2), nrank(1), 1, 10, db_type, rhsoverlap_type)
-          ! if mpi_coltype was used, we free it first
-          IF( mpi_coltype .ne. MPI_DATATYPE_NULL) CALL MPI_TYPE_FREE(mpi_coltype,ierr)
-        ! Create vector type of length nx 
-          CALL MPI_TYPE_VECTOR(nr, block_size, stride*block_size*nz, init_type, temp_mpi_coltype, ierr)
-          CALL MPI_TYPE_COMMIT(temp_mpi_coltype, ierr)
-        
-        ! Get the size in bytes of the initial type
-          CALL MPI_TYPE_GET_EXTENT(init_type, init_type_lb, init_type_extent, ierr)
-    
-          if(mpi_coltype .ne. MPI_DATATYPE_NULL) CALL MPI_TYPE_FREE(mpi_coltype,ierr)
-        ! Resize temp_mpi_coltype such that the next item to read is at j+1 
-          CALL MPI_TYPE_CREATE_RESIZED(temp_mpi_coltype, init_type_lb, stride*block_size*init_type_extent ,& 
-          &  mpi_coltype, ierr)
-          CALL MPI_TYPE_COMMIT(mpi_coltype, ierr)
-    
-          CALL MPI_TYPE_FREE(temp_mpi_coltype,ierr)
-    
-    
-      END SUBROUTINE init_coltypempi
-    
-    END MODULE mpihelper
-    
\ No newline at end of file