! Module to compute long-range part of electrostatic (Coulomb) potential
module MW_coulomb_lr
   use MW_kinds, only: wp
   use MW_ewald, only: MW_ewald_t
   use MW_box, only: MW_box_t
   use MW_constants, only: twopi, block_vector_size
   use MW_electrode, only: MW_electrode_t
   use MW_molecule, only: MW_molecule_t
   use MW_ion, only: MW_ion_t
   use MW_localwork, only: MW_localwork_t
   implicit none
   private

   ! Public subroutines
   ! ------------------
   public :: diag_gradQelec_potential !diag[grad_Q [grad_Q [U^lr_QQ]]]
   public :: gradQelec_potential !grad_Q [grad_Q [U^lr_QQ]]
   public :: qmelt2Qelec_potential !grad_Q [U^lr_qQ]
   public :: Qelec2Qelec_potential !grad_Q [U^lr_QQ]
   public :: melt_efg !-grad_r grad_r [(U^lr_qq)]
   public :: melt_forces !-grad_r [(U^lr_qq) + (U^lr_QQ) + (U^lr_qQ)]
   public :: energy !(U^lr_qq) + (U^lr_QQ) + (U^lr_qQ)

contains

   !================================================================================
   ! Compute the Coulomb potential felt by each electrode atoms due to all electrode atoms
   subroutine diag_gradQelec_potential(localwork, ewald, box, &
         electrodes, diag_gradQ_V)
      implicit none

      ! Parameters in
      ! -------------
      type(MW_localwork_t), intent(in)    :: localwork  !< Localwork work distribution
      type(MW_ewald_t),     intent(inout) :: ewald      !< Ewald summation parameters
      type(MW_box_t),       intent(in)    :: box        !< Simulation box parameters

      type(MW_electrode_t), intent(in) :: electrodes(:)   !< electrode parameters

      ! Parameters out
      ! --------------
      real(wp), intent(inout) :: diag_gradQ_V(:)       !< Coulomb potential

      ! Local
      ! -----
      integer :: num_elec_types
      integer :: i, itype
      integer :: l, m, n, mabs, nabs
      integer :: kmax_x, kmax_y, kmax_z
      real(wp) :: sign_m, sign_n
      real(wp) :: kx, ky, kz, knorm2, knorm2_max
      real(wp) :: Sk_alpha !< Structure factor coefficients
      real(wp) :: volfactor
      real(wp) :: cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz
      real(wp) :: cos_kxky, sin_kxky
      real(wp) :: cos_kxkykz_i, sin_kxkykz_i
      real(wp) :: alpha, alphasq, alphaconst
      real(wp) :: box_lengthx_rec, box_lengthy_rec
      integer :: imode, num_modes, mode_offset
      integer :: iblock, num_blocks, istart_block, iend_block, iend_type
      integer :: num_pbc

      ! Precompute some factors
      ! -----------------------
      num_elec_types = size(electrodes,1)

      alpha = ewald%alpha
      alphasq = alpha * alpha
      alphaconst = -1.0_wp / (4.0_wp*alphasq)

      num_pbc = ewald%num_pbc
      box_lengthx_rec = 1.0_wp / box%length(1)
      box_lengthy_rec = 1.0_wp / box%length(2)

      knorm2_max = ewald%knorm2_max
      kmax_x = ewald%kmax_x
      kmax_y = ewald%kmax_y
      kmax_z = ewald%kmax_z

      num_modes = localwork%ewald_num_mode_local
      mode_offset = localwork%ewald_local_mode_offset

      !$acc data &
      !$acc present(ewald, ewald%zpoint, ewald%zweight, &
      !$acc        ewald%cos_kx_elec(:,0:kmax_x), ewald%sin_kx_elec(:,0:kmax_x), &
      !$acc        ewald%cos_ky_elec(:,0:kmax_y), ewald%sin_ky_elec(:,0:kmax_y), &
      !$acc        ewald%cos_kz_elec(:,0:kmax_z), ewald%sin_kz_elec(:,0:kmax_z), &
      !$acc        ewald%Sk_cos(:), ewald%Sk_sin(:), diag_gradQ_V(:))

      ! Long range contribution is computed in reciprocal space
      ! -------------------------------------------------------
      ! The sum over k-modes is symmetric
      !   -> we loop only on half of them and mulitply by 2.0
      ! Total number of modes
      !    (2*kmax_x+1)*(2*kmax_y+1)*nz
      ! Num modes executed globally
      !    (2*kmax_x*kmax_y + kmax_x + kmax_y)*nz
      ! Num modes executed by the local process (approx.)
      !    (2*kmax_x*kmax_y + kmax_x + kmax_y)*nz / num_rank
      volfactor = 2.0_wp / box%area(3)

      ! Setup cache blocking parameters
      do itype = 1, num_elec_types
         num_blocks = 0
         if (electrodes(itype)%count > 0) then
            num_blocks = (electrodes(itype)%count-1)/block_vector_size + 1
         end if
         iend_type = electrodes(itype)%offset + electrodes(itype)%count
         do iblock = 1, num_blocks
            istart_block = (iblock-1)*block_vector_size + 1 + electrodes(itype)%offset
            iend_block = min(istart_block+block_vector_size-1,iend_type)

            !$acc parallel loop gang &
            !$acc private(imode, l, m, n, kx, ky, kz, mabs, nabs, sign_m, sign_n, knorm2, Sk_alpha, &
            !$acc         cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz, &
            !$acc         cos_kxky, sin_kxky, cos_kxkykz_i, sin_kxkykz_i, i)
            do imode = 1, num_modes
               call compute_kmode_index(num_pbc, kmax_x, kmax_y, kmax_z, imode+mode_offset, l, m, n)
               ! kx = l * twopi / box%length(1)
               kx = (real(l,wp) * twopi) * box_lengthx_rec
               ! ky = m * twopi / box%length(2)
               mabs = abs(m)
               sign_m = real(sign(1,m), wp)
               ky = (real(m,wp) * twopi) * box_lengthy_rec
               ! kz = zpoint(n)
               nabs = abs(n)
               sign_n = real(sign(1,n), wp)
               kz = sign_n * ewald%zpoint(nabs)

               ! Norm square of the k-mode vector
               knorm2 = kx*kx + ky*ky + kz*kz
               if (knorm2 <= ewald%knorm2_max) then
                  Sk_alpha = 2.0_wp * volfactor * ewald%zweight(nabs) * &
                        (exp(alphaconst * knorm2) / knorm2)
                  !$acc loop vector
                  do i = istart_block, iend_block

                     cos_kx = ewald%cos_kx_elec(i,l)
                     sin_kx = ewald%sin_kx_elec(i,l)
                     cos_ky = ewald%cos_ky_elec(i,mabs)
                     sin_ky = ewald%sin_ky_elec(i,mabs) * sign_m
                     cos_kz = ewald%cos_kz_elec(i,nabs)
                     sin_kz = ewald%sin_kz_elec(i,nabs) * sign_n

                     cos_kxky = cos_kx * cos_ky - sin_kx * sin_ky
                     sin_kxky = sin_kx * cos_ky + cos_kx * sin_ky

                     cos_kxkykz_i = cos_kxky * cos_kz - sin_kxky * sin_kz
                     sin_kxkykz_i = sin_kxky * cos_kz + cos_kxky * sin_kz

                     !Non-parallelized loop over all particles
                     !$acc atomic update
                     diag_gradQ_V(i) = diag_gradQ_V(i) + Sk_alpha * (cos_kxkykz_i*cos_kxkykz_i + sin_kxkykz_i*sin_kxkykz_i) ! the term in parenthesis is 1!
                  end do
                  !$acc end loop
               end if
            end do
            !$acc end parallel loop
         end do
      end do
      !$acc end data
  end subroutine diag_gradQelec_potential

   !================================================================================
   ! Compute the Coulomb potential felt by each electrode atoms due to all electrode atoms
   subroutine gradQelec_potential(localwork, ewald, box, electrodes, gradQ_V)
      implicit none

      ! Parameters in
      ! -------------
      type(MW_localwork_t), intent(in)    :: localwork  !< Localwork work distribution
      type(MW_ewald_t),     intent(inout) :: ewald      !< Ewald summation parameters
      type(MW_box_t),       intent(in)    :: box        !< Simulation box parameters

      type(MW_electrode_t), intent(in) :: electrodes(:)   !< electrode parameters

      ! Parameters out
      ! --------------
      real(wp), intent(inout) :: gradQ_V(:,:)       !< Coulomb potential

      ! Local
      ! -----
      integer :: num_elec_types
      integer :: i, j, itype
      integer :: l, m, n, mabs, nabs
      integer :: kmax_x, kmax_y, kmax_z
      real(wp) :: sign_m, sign_n
      real(wp) :: kx, ky, kz, knorm2, knorm2_max
      real(wp) :: Sk_alpha !< Structure factor coefficients
      real(wp) :: volfactor
      real(wp) :: cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz
      real(wp) :: cos_kxky, sin_kxky
      real(wp) :: cos_kxkykz_i, sin_kxkykz_i, cos_kxkykz_j, sin_kxkykz_j
      real(wp) :: alpha, alphasq, alphaconst
      real(wp) :: box_lengthx_rec, box_lengthy_rec
      integer :: imode, num_modes, mode_offset
      integer :: iblock, num_blocks, istart_block, iend_block, iend_type
      integer :: num_pbc

      ! Precompute some factors
      ! -----------------------
      num_elec_types = size(electrodes,1)

      alpha = ewald%alpha
      alphasq = alpha * alpha
      alphaconst = -1.0_wp / (4.0_wp*alphasq)

      num_pbc = ewald%num_pbc
      box_lengthx_rec = 1.0_wp / box%length(1)
      box_lengthy_rec = 1.0_wp / box%length(2)

      knorm2_max = ewald%knorm2_max
      kmax_x = ewald%kmax_x
      kmax_y = ewald%kmax_y
      kmax_z = ewald%kmax_z

      num_modes = localwork%ewald_num_mode_local
      mode_offset = localwork%ewald_local_mode_offset

      !$acc data &
      !$acc present(ewald, ewald%zpoint, ewald%zweight, &
      !$acc        ewald%cos_kx_elec(:,0:kmax_x), ewald%sin_kx_elec(:,0:kmax_x), &
      !$acc        ewald%cos_ky_elec(:,0:kmax_y), ewald%sin_ky_elec(:,0:kmax_y), &
      !$acc        ewald%cos_kz_elec(:,0:kmax_z), ewald%sin_kz_elec(:,0:kmax_z), &
      !$acc        ewald%Sk_cos(:), ewald%Sk_sin(:), gradQ_V(:,:))

      ! Long range contribution is computed in reciprocal space
      ! -------------------------------------------------------
      ! The sum over k-modes is symmetric
      !   -> we loop only on half of them and mulitply by 2.0
      ! Total number of modes
      !    (2*kmax_x+1)*(2*kmax_y+1)*nz
      ! Num modes executed globally
      !    (2*kmax_x*kmax_y + kmax_x + kmax_y)*nz
      ! Num modes executed by the local process (approx.)
      !    (2*kmax_x*kmax_y + kmax_x + kmax_y)*nz / num_rank
      volfactor = 2.0_wp / box%area(3)

      ! Setup cache blocking parameters
      do itype = 1, num_elec_types
         num_blocks = 0
         if (electrodes(itype)%count > 0) then
            num_blocks = (electrodes(itype)%count-1)/block_vector_size + 1
         end if
         iend_type = electrodes(itype)%offset + electrodes(itype)%count
         do iblock = 1, num_blocks
            istart_block = (iblock-1)*block_vector_size + 1 + electrodes(itype)%offset
            iend_block = min(istart_block+block_vector_size-1,iend_type)

            !$acc parallel loop gang &
            !$acc private(imode, l, m, n, kx, ky, kz, mabs, nabs, sign_m, sign_n, knorm2, Sk_alpha, &
            !$acc         cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz, &
            !$acc         cos_kxky, sin_kxky, cos_kxkykz_i, sin_kxkykz_i, &
            !$acc         cos_kxkykz_j, sin_kxkykz_j, i)

            do imode = 1, num_modes
               call compute_kmode_index(num_pbc, kmax_x, kmax_y, kmax_z, imode+mode_offset, l, m, n)
               ! kx = l * twopi / box%length(1)
               kx = (real(l,wp) * twopi) * box_lengthx_rec
               ! ky = m * twopi / box%length(2)
               mabs = abs(m)
               sign_m = real(sign(1,m), wp)
               ky = (real(m,wp) * twopi) * box_lengthy_rec
               ! kz = zpoint(n)
               nabs = abs(n)
               sign_n = real(sign(1,n), wp)
               kz = sign_n * ewald%zpoint(nabs)

               ! Norm square of the k-mode vector
               knorm2 = kx*kx + ky*ky + kz*kz
               if (knorm2 <= ewald%knorm2_max) then
                  Sk_alpha = 2.0_wp * volfactor * ewald%zweight(nabs) * &
                        (exp(alphaconst * knorm2) / knorm2)
                  !$acc loop vector
                  do i = istart_block, iend_block

                     cos_kx = ewald%cos_kx_elec(i,l)
                     sin_kx = ewald%sin_kx_elec(i,l)
                     cos_ky = ewald%cos_ky_elec(i,mabs)
                     sin_ky = ewald%sin_ky_elec(i,mabs) * sign_m
                     cos_kz = ewald%cos_kz_elec(i,nabs)
                     sin_kz = ewald%sin_kz_elec(i,nabs) * sign_n

                     cos_kxky = cos_kx * cos_ky - sin_kx * sin_ky
                     sin_kxky = sin_kx * cos_ky + cos_kx * sin_ky

                     cos_kxkykz_i = cos_kxky * cos_kz - sin_kxky * sin_kz
                     sin_kxkykz_i = sin_kxky * cos_kz + cos_kxky * sin_kz
                     !Non-parallelized loop over all particles
                     do j = 1,i

                        cos_kx = ewald%cos_kx_elec(j,l)
                        sin_kx = ewald%sin_kx_elec(j,l)
                        cos_ky = ewald%cos_ky_elec(j,mabs)
                        sin_ky = ewald%sin_ky_elec(j,mabs) * sign_m
                        cos_kz = ewald%cos_kz_elec(j,nabs)
                        sin_kz = ewald%sin_kz_elec(j,nabs) * sign_n

                        cos_kxky = cos_kx * cos_ky - sin_kx * sin_ky
                        sin_kxky = sin_kx * cos_ky + cos_kx * sin_ky

                        cos_kxkykz_j = cos_kxky * cos_kz - sin_kxky * sin_kz
                        sin_kxkykz_j = sin_kxky * cos_kz + cos_kxky * sin_kz

                        !$acc atomic update
                        gradQ_V(j,i) = gradQ_V(j,i) + Sk_alpha * (cos_kxkykz_i*cos_kxkykz_j + sin_kxkykz_i*sin_kxkykz_j)
                     end do
                  end do
                  !$acc end loop
               end if
            end do
            !$acc end parallel loop
         end do
      end do
      !$acc end data
   end subroutine gradQelec_potential

   !================================================================================
   ! Compute the long-range Coulomb potential felt by each electrode
   ! atoms due to all melt ions
   subroutine qmelt2Qelec_potential(localwork, ewald, box, &
                   ions, electrodes, V, type_ions)
      implicit none

      ! Parameters in
      ! -------------
      type(MW_localwork_t), intent(in) :: localwork  !< Local work assignment
      type(MW_ewald_t), intent(inout)  :: ewald      !< Ewald summation parameters
      type(MW_box_t),   intent(in)     :: box        !< Simulation box parameters

      type(MW_ion_t), intent(in) :: ions(:)        !< ions parameters
      type(MW_electrode_t), intent(in) :: electrodes(:)   !< electrode parameters
      integer, intent(in) :: type_ions(:)      ! Ions type

      ! Parameters out
      ! --------------
      real(wp), intent(inout) :: V(:)       !< Coulomb potential

      ! Local
      ! -----
      integer :: num_ion_types, num_elec_types
      integer :: num_ions, num_elec_atoms
      integer :: i, j, jtype
      integer :: l, m, n, mabs, nabs
      integer :: kmax_x, kmax_y, kmax_z
      real(wp) :: sign_m, sign_n
      real(wp) :: qj !< ion charge
      real(wp) :: kx, ky, kz, knorm2, knorm2_max
      real(wp) :: Sk_alpha !< Structure factor coefficients
      real(wp) :: volfactor
      real(wp) :: cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz
      real(wp) :: cos_kxky, sin_kxky, cos_kxkykz, sin_kxkykz
      real(wp) :: sk_cos, sk_sin
      real(wp) :: alpha, alphasq, alphaconst
      real(wp) :: box_lengthx_rec, box_lengthy_rec

      integer :: imode, num_modes, mode_offset
      integer :: iblock, num_blocks, istart_block, iend_block
      integer :: num_pbc

      num_ion_types = size(ions,1)
      num_elec_types = size(electrodes,1)

      num_ions = 0
      if (num_ion_types > 0) then
         num_ions = ions(num_ion_types)%offset+ions(num_ion_types)%count
      end if
      num_elec_atoms = 0
      if (num_elec_types > 0) then
         num_elec_atoms = electrodes(num_elec_types)%offset+electrodes(num_elec_types)%count
      end if

      ! Precompute some factors
      ! -----------------------
      alpha = ewald%alpha
      alphasq = alpha * alpha
      alphaconst = -1.0_wp / (4.0_wp*alphasq)

      box_lengthx_rec = 1.0_wp / box%length(1)
      box_lengthy_rec = 1.0_wp / box%length(2)

      volfactor = 2.0_wp / box%area(3)

      knorm2_max = ewald%knorm2_max
      kmax_x = ewald%kmax_x
      kmax_y = ewald%kmax_y
      kmax_z = ewald%kmax_z

      num_pbc = ewald%num_pbc

      num_modes = localwork%ewald_num_mode_local
      mode_offset = localwork%ewald_local_mode_offset

      !$acc data &
      !$acc present(ewald, ewald%zpoint, ewald%zweight, &
      !$acc        ewald%cos_kx_elec(:,0:kmax_x), ewald%sin_kx_elec(:,0:kmax_x), &
      !$acc        ewald%cos_ky_elec(:,0:kmax_y), ewald%sin_ky_elec(:,0:kmax_y), &
      !$acc        ewald%cos_kz_elec(:,0:kmax_z), ewald%sin_kz_elec(:,0:kmax_z), &
      !$acc        ewald%cos_kx_ions(:,0:kmax_x), ewald%sin_kx_ions(:,0:kmax_x), &
      !$acc        ewald%cos_ky_ions(:,0:kmax_y), ewald%sin_ky_ions(:,0:kmax_y), &
      !$acc        ewald%cos_kz_ions(:,0:kmax_z), ewald%sin_kz_ions(:,0:kmax_z), &
      !$acc        ewald%Sk_cos(:), ewald%Sk_sin(:), V(:))

      ! Initiliaze potential to 0
      ! -------------------------
      !$acc kernels
      V(:) = 0.0_wp
      ewald%Sk_cos(:) = 0.0_wp
      ewald%Sk_sin(:) = 0.0_wp
      !$acc end kernels

      ! Long range contribution is computed in reciprocal space
      ! -------------------------------------------------------
      ! The sum over k-modes is symmetric
      !   -> we loop only on half of them and mulitply by 2.0
      ! Total number of modes
      !    (2*kmax_x+1)*(2*kmax_y+1)*nz
      ! Num modes in the exectude globally
      !    (2*kmax_x*kmax_y + kmax_x + kmax_y)*nz
      ! Num modes executed by the local process (approx.)
      !    (2*kmax_x*kmax_y + kmax_x + kmax_y)*nz / num_rank

      ! Setup cache blocking parameters
      num_blocks = (num_ions-1)/block_vector_size + 1
      do iblock = 1, num_blocks
         istart_block = (iblock-1)*block_vector_size + 1
         iend_block = min(istart_block+block_vector_size-1,num_ions)

         !$acc parallel
         !$acc loop gang &
         !$acc private(imode, l, m, n, kx, ky, kz, mabs, nabs, sign_m, sign_n, knorm2, &
         !$acc         cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz, cos_kxky, sin_kxky, &
         !$acc         cos_kxkykz, sin_kxkykz, sk_cos, sk_sin, i)
         do imode = 1, num_modes
            call compute_kmode_index(num_pbc, kmax_x, kmax_y, kmax_z, imode+mode_offset, l, m, n)
            ! kx = l * twopi / box%length(1)
            kx = (real(l,wp) * twopi) * box_lengthx_rec
            ! ky = m * twopi / box%length(2)
            mabs = abs(m)
            sign_m = real(sign(1,m), wp)
            ky = (real(m,wp) * twopi) * box_lengthy_rec
            ! kz = zpoint(n)
            nabs = abs(n)
            sign_n = real(sign(1,n), wp)
            kz = ewald%zpoint(nabs)

            ! Norm square of the k-mode vector
            knorm2 = kx*kx + ky*ky + kz*kz
            if (knorm2 <= ewald%knorm2_max) then

               sk_cos = 0.0_wp
               sk_sin = 0.0_wp
               !$acc loop vector reduction(+: sk_cos, sk_sin)
               do j = istart_block, iend_block
                  jtype = type_ions(j)
                  qj = ions(jtype)%charge

                  cos_kx = ewald%cos_kx_ions(j,l)
                  sin_kx = ewald%sin_kx_ions(j,l)
                  cos_ky = ewald%cos_ky_ions(j,mabs)
                  sin_ky = ewald%sin_ky_ions(j,mabs) * sign_m
                  cos_kz = ewald%cos_kz_ions(j,nabs)
                  sin_kz = ewald%sin_kz_ions(j,nabs) * sign_n

                  cos_kxky = cos_kx * cos_ky - sin_kx * sin_ky
                  sin_kxky = sin_kx * cos_ky + cos_kx * sin_ky

                  cos_kxkykz = cos_kxky * cos_kz - sin_kxky * sin_kz
                  sin_kxkykz = sin_kxky * cos_kz + cos_kxky * sin_kz

                  sk_cos = sk_cos + qj*cos_kxkykz
                  sk_sin = sk_sin + qj*sin_kxkykz
               end do
               !$acc end loop
               ewald%Sk_cos(imode) = ewald%Sk_cos(imode) + sk_cos
               ewald%Sk_sin(imode) = ewald%Sk_sin(imode) + sk_sin

            end if
         end do
         !$acc end loop
         !$acc end parallel
      end do

      ! Setup cache blocking parameters
      num_blocks = (num_elec_atoms-1)/block_vector_size + 1
      do iblock = 1, num_blocks
         istart_block = (iblock-1)*block_vector_size + 1
         iend_block = min(istart_block+block_vector_size-1,num_elec_atoms)

         num_modes = localwork%ewald_num_mode_local
         l = localwork%ewald_kstart_x
         m = localwork%ewald_kstart_y
         n = localwork%ewald_kstart_z

         !$acc parallel
         !$acc loop gang &
         !$acc private(imode, l, m, n, kx, ky, kz, mabs, nabs, sign_m, sign_n, knorm2, &
         !$acc         cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz, cos_kxky, sin_kxky, &
         !$acc         cos_kxkykz, sin_kxkykz, sk_cos, sk_sin, i)
         do imode = 1, num_modes
            call compute_kmode_index(num_pbc, kmax_x, kmax_y, kmax_z, imode+mode_offset, l, m, n)
            ! kx = l * twopi / box%length(1)
            kx = (real(l,wp) * twopi) * box_lengthx_rec
            ! ky = m * twopi / box%length(2)
            mabs = abs(m)
            sign_m = real(sign(1,m), wp)
            ky = (real(m,wp) * twopi) * box_lengthy_rec
            ! kz = zpoint(n)
            nabs = abs(n)
            sign_n = real(sign(1,n), wp)
            kz = sign_n*ewald%zpoint(nabs)

            ! Norm square of the k-mode vector
            knorm2 = kx*kx + ky*ky + kz*kz
            if (knorm2 <= ewald%knorm2_max) then

               Sk_alpha = 2.0_wp * volfactor * ewald%zweight(nabs) * &
                     (exp(alphaconst*knorm2) / knorm2)
               !$acc loop vector
               do i = istart_block, iend_block

                  cos_kx = ewald%cos_kx_elec(i,l)
                  sin_kx = ewald%sin_kx_elec(i,l)
                  cos_ky = ewald%cos_ky_elec(i,mabs)
                  sin_ky = ewald%sin_ky_elec(i,mabs) * sign_m
                  cos_kz = ewald%cos_kz_elec(i,nabs)
                  sin_kz = ewald%sin_kz_elec(i,nabs) * sign_n

                  cos_kxky = cos_kx * cos_ky - sin_kx * sin_ky
                  sin_kxky = sin_kx * cos_ky + cos_kx * sin_ky

                  cos_kxkykz = cos_kxky * cos_kz - sin_kxky * sin_kz
                  sin_kxkykz = sin_kxky * cos_kz + cos_kxky * sin_kz
                  !$acc atomic update
                  V(i) = V(i) + Sk_alpha * (cos_kxkykz*ewald%Sk_cos(imode) &
                        + sin_kxkykz*ewald%Sk_sin(imode))
               end do
               !$acc end loop
            end if
         end do
         !$acc end loop
         !$acc end parallel
      end do
      !$acc end data
   end subroutine qmelt2Qelec_potential

   !================================================================================
   ! Compute the Coulomb potential felt by each electrode atoms due to all electrode atoms
   subroutine Qelec2Qelec_potential(localwork, ewald, box, &
         electrodes, q_elec, V)
      implicit none

      ! Parameters in
      ! -------------
      type(MW_localwork_t), intent(in)    :: localwork  !< Localwork work distribution
      type(MW_ewald_t),     intent(inout) :: ewald      !< Ewald summation parameters
      type(MW_box_t),       intent(in)    :: box        !< Simulation box parameters

      type(MW_electrode_t), intent(in) :: electrodes(:)   !< electrode parameters
      real(wp),             intent(in) :: q_elec(:)       !< Electrode atoms charge

      ! Parameters out
      ! --------------
      real(wp), intent(inout) :: V(:)       !< Coulomb potential

      ! Local
      ! -----
      integer :: num_elec_types
      integer :: i, j, itype
      integer :: l, m, n, mabs, nabs
      integer :: kmax_x, kmax_y, kmax_z
      real(wp) :: sign_m, sign_n
      real(wp) :: kx, ky, kz, knorm2, knorm2_max
      real(wp) :: Sk_alpha !< Structure factor coefficients
      real(wp) :: volfactor
      real(wp) :: cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz
      real(wp) :: cos_kxky, sin_kxky, cos_kxkykz, sin_kxkykz
      real(wp) :: sk_cos, sk_sin
      real(wp) :: alpha, alphasq, alphaconst
      real(wp) :: box_lengthx_rec, box_lengthy_rec
      integer :: imode, num_modes, mode_offset
      integer :: iblock, num_blocks, istart_block, iend_block, iend_type
      integer :: num_pbc

      ! Precompute some factors
      ! -----------------------
      num_elec_types = size(electrodes,1)

      alpha = ewald%alpha
      alphasq = alpha * alpha
      alphaconst = -1.0_wp / (4.0_wp*alphasq)

      num_pbc = ewald%num_pbc
      box_lengthx_rec = 1.0_wp / box%length(1)
      box_lengthy_rec = 1.0_wp / box%length(2)

      knorm2_max = ewald%knorm2_max
      kmax_x = ewald%kmax_x
      kmax_y = ewald%kmax_y
      kmax_z = ewald%kmax_z

      num_modes = localwork%ewald_num_mode_local
      mode_offset = localwork%ewald_local_mode_offset

      !$acc data &
      !$acc present(ewald, ewald%zpoint, ewald%zweight, &
      !$acc        ewald%cos_kx_elec(:,0:kmax_x), ewald%sin_kx_elec(:,0:kmax_x), &
      !$acc        ewald%cos_ky_elec(:,0:kmax_y), ewald%sin_ky_elec(:,0:kmax_y), &
      !$acc        ewald%cos_kz_elec(:,0:kmax_z), ewald%sin_kz_elec(:,0:kmax_z), &
      !$acc        ewald%cos_kx_ions(:,0:kmax_x), ewald%sin_kx_ions(:,0:kmax_x), &
      !$acc        ewald%cos_ky_ions(:,0:kmax_y), ewald%sin_ky_ions(:,0:kmax_y), &
      !$acc        ewald%cos_kz_ions(:,0:kmax_z), ewald%sin_kz_ions(:,0:kmax_z), &
      !$acc        ewald%Sk_cos(:), ewald%Sk_sin(:), q_elec(:), V(:))

      !$acc kernels
      ewald%Sk_cos(:) = 0.0_wp
      ewald%Sk_sin(:) = 0.0_wp
      !$acc end kernels

      ! Long range contribution is computed in reciprocal space
      ! -------------------------------------------------------
      ! The sum over k-modes is symmetric
      !   -> we loop only on half of them and mulitply by 2.0
      ! Total number of modes
      !    (2*kmax_x+1)*(2*kmax_y+1)*nz
      ! Num modes executed globally
      !    (2*kmax_x*kmax_y + kmax_x + kmax_y)*nz
      ! Num modes executed by the local process (approx.)
      !    (2*kmax_x*kmax_y + kmax_x + kmax_y)*nz / num_rank
      volfactor = 2.0_wp / box%area(3)

      ! Setup cache blocking parameters
      do itype = 1, num_elec_types
         num_blocks = 0
         if (electrodes(itype)%count > 0) then
            num_blocks = (electrodes(itype)%count-1)/block_vector_size + 1
         end if
         iend_type = electrodes(itype)%offset + electrodes(itype)%count
         do iblock = 1, num_blocks
            istart_block = (iblock-1)*block_vector_size + 1 + electrodes(itype)%offset
            iend_block = min(istart_block+block_vector_size-1,iend_type)

            !$acc parallel
            !$acc loop gang &
            !$acc private(imode, l, m, n, kx, ky, kz, mabs, nabs, sign_m, sign_n, knorm2, &
            !$acc         cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz, cos_kxky, sin_kxky, &
            !$acc         cos_kxkykz, sin_kxkykz, sk_cos, sk_sin, i)
            do imode = 1, num_modes
               call compute_kmode_index(num_pbc, kmax_x, kmax_y, kmax_z, imode+mode_offset, l, m, n)
               ! kx = l * twopi / box%length(1)
               kx = (real(l,wp) * twopi) * box_lengthx_rec
               ! ky = m * twopi / box%length(2)
               mabs = abs(m)
               sign_m = real(sign(1,m), wp)
               ky = (real(m,wp) * twopi) * box_lengthy_rec
               ! kz = zpoint(n)
               nabs = abs(n)
               sign_n = real(sign(1,n), wp)
               kz = sign_n * ewald%zpoint(nabs)

               ! Norm square of the k-mode vector
               knorm2 = kx*kx + ky*ky + kz*kz
               if (knorm2 <= ewald%knorm2_max) then

                  sk_cos = 0.0_wp
                  sk_sin = 0.0_wp
                  !$acc loop vector reduction(+: sk_cos, sk_sin)
                  do j = istart_block, iend_block

                     cos_kx = ewald%cos_kx_elec(j,l)
                     sin_kx = ewald%sin_kx_elec(j,l)
                     cos_ky = ewald%cos_ky_elec(j,mabs)
                     sin_ky = ewald%sin_ky_elec(j,mabs) * sign_m
                     cos_kz = ewald%cos_kz_elec(j,nabs)
                     sin_kz = ewald%sin_kz_elec(j,nabs) * sign_n

                     cos_kxky = cos_kx * cos_ky - sin_kx * sin_ky
                     sin_kxky = sin_kx * cos_ky + cos_kx * sin_ky

                     cos_kxkykz = cos_kxky * cos_kz - sin_kxky * sin_kz
                     sin_kxkykz = sin_kxky * cos_kz + cos_kxky * sin_kz

                     Sk_cos = Sk_cos + q_elec(j)*cos_kxkykz
                     Sk_sin = Sk_sin + q_elec(j)*sin_kxkykz
                  end do
                  !$acc end loop
                  ewald%Sk_cos(imode) = ewald%Sk_cos(imode) + sk_cos
                  ewald%Sk_sin(imode) = ewald%Sk_sin(imode) + sk_sin
               end if
            end do
            !$acc end loop
            !$acc end parallel
         end do
      end do

      ! Setup cache blocking parameters
      do itype = 1, num_elec_types
         num_blocks = 0
         if (electrodes(itype)%count > 0) then
            num_blocks = (electrodes(itype)%count-1)/block_vector_size + 1
         end if
         iend_type = electrodes(itype)%offset + electrodes(itype)%count
         do iblock = 1, num_blocks
            istart_block = (iblock-1)*block_vector_size + 1 + electrodes(itype)%offset
            iend_block = min(istart_block+block_vector_size-1,iend_type)

            !$acc parallel
            !$acc loop gang &
            !$acc private(imode, l, m, n, kx, ky, kz, mabs, nabs, sign_m, sign_n, knorm2, &
            !$acc         cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz, cos_kxky, sin_kxky, &
            !$acc         cos_kxkykz, sin_kxkykz, sk_cos, sk_sin, i)
            do imode = 1, num_modes
               call compute_kmode_index(num_pbc, kmax_x, kmax_y, kmax_z, imode+mode_offset, l, m, n)
               ! kx = l * twopi / box%length(1)
               kx = (real(l,wp) * twopi) * box_lengthx_rec
               ! ky = m * twopi / box%length(2)
               mabs = abs(m)
               sign_m = real(sign(1,m), wp)
               ky = (real(m,wp) * twopi) * box_lengthy_rec
               ! kz = zpoint(n)
               nabs = abs(n)
               sign_n = real(sign(1,n), wp)
               kz = sign_n * ewald%zpoint(nabs)

               ! Norm square of the k-mode vector
               knorm2 = kx*kx + ky*ky + kz*kz
               if (knorm2 <= ewald%knorm2_max) then
                  Sk_alpha = 2.0_wp * volfactor * ewald%zweight(nabs) * &
                        (exp(alphaconst * knorm2) / knorm2)
                  do i = istart_block, iend_block

                     cos_kx = ewald%cos_kx_elec(i,l)
                     sin_kx = ewald%sin_kx_elec(i,l)
                     cos_ky = ewald%cos_ky_elec(i,mabs)
                     sin_ky = ewald%sin_ky_elec(i,mabs) * sign_m
                     cos_kz = ewald%cos_kz_elec(i,nabs)
                     sin_kz = ewald%sin_kz_elec(i,nabs) * sign_n

                     cos_kxky = cos_kx * cos_ky - sin_kx * sin_ky
                     sin_kxky = sin_kx * cos_ky + cos_kx * sin_ky

                     cos_kxkykz = cos_kxky * cos_kz - sin_kxky * sin_kz
                     sin_kxkykz = sin_kxky * cos_kz + cos_kxky * sin_kz
                     !$acc atomic update
                     V(i) = V(i) + Sk_alpha * (cos_kxkykz*ewald%Sk_cos(imode) + sin_kxkykz*ewald%Sk_sin(imode))
                  end do
                  !$acc end loop
               end if
            end do
            !$acc end loop
            !$acc end parallel
         end do
      end do
      !$acc end data
   end subroutine Qelec2Qelec_potential

   !================================================================================
   ! Compute the Coulomb forces felt by each melt ions due to other melt ions
   subroutine melt_forces(localwork, ewald, box, ions, &
         electrodes, q_elec, force,stress_tensor, compute_force)
      implicit none

      ! Parameters in
      ! -------------
      type(MW_localwork_t), intent(in) :: localwork       !< Local work assignment
      type(MW_ewald_t),     intent(inout) :: ewald           !< Ewald summation parameters
      type(MW_box_t),       intent(in) :: box             !< Simulation box parameters
      type(MW_ion_t),       intent(in) :: ions(:)         !< ions parameters
      type(MW_electrode_t), intent(inout) :: electrodes(:)   !< electrodes parameters
      real(wp),             intent(in) :: q_elec(:)       !< Electrode atoms charge
      logical,              intent(in) :: compute_force       !< compute electrode force

      ! Parameters out
      ! --------------
      real(wp), intent(inout) :: force(:,:) !< Coulomb force on ions
      real(wp), intent(inout) :: stress_tensor(:,:) !< Coulomb force contribution to the stress tensor

      ! Local
      ! -----
      integer :: num_ion_types, num_elec_types
      integer :: i, itype
      integer :: l, m, n, mabs, nabs
      integer :: kmax_x, kmax_y, kmax_z
      real(wp) :: sign_m, sign_n
      real(wp) :: qi
      real(wp) :: kx, ky, kz, knorm2, knorm2_max
      real(wp) :: Sk_alpha !< Structure factor coefficients
      real(wp) :: cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz
      real(wp) :: cos_kxky, sin_kxky, cos_kxkykz, sin_kxkykz
      real(wp) :: volfactor
      real(wp) :: alpha, alphasq, alphaconst
      real(wp) :: box_lengthx_rec, box_lengthy_rec
      real(wp) :: sk_cos, sk_sin
      integer :: imode, num_modes, mode_offset
      integer :: iblock, num_blocks, istart_block, iend_block, iend_type
      integer :: num_pbc
      real(wp) :: stfac1,stfac2
      real(wp) :: loc_stress_tensor_xx, loc_stress_tensor_yy, loc_stress_tensor_zz
      real(wp) :: loc_stress_tensor_xy, loc_stress_tensor_xz, loc_stress_tensor_yz

      num_ion_types = size(ions,1)
      num_elec_types = size(electrodes,1)

      loc_stress_tensor_xx = 0.0_wp
      loc_stress_tensor_yy = 0.0_wp
      loc_stress_tensor_zz = 0.0_wp
      loc_stress_tensor_xy = 0.0_wp
      loc_stress_tensor_xz = 0.0_wp
      loc_stress_tensor_yz = 0.0_wp

      ! Precompute some factors
      ! -----------------------
      alpha = ewald%alpha
      alphasq = alpha*alpha
      alphaconst = - 1.0_wp/(4.0_wp*alphasq)

      num_pbc = ewald%num_pbc
      box_lengthx_rec = 1.0_wp / box%length(1)
      box_lengthy_rec = 1.0_wp / box%length(2)

      knorm2_max = ewald%knorm2_max
      kmax_x = ewald%kmax_x
      kmax_y = ewald%kmax_y
      kmax_z = ewald%kmax_z

      num_modes = localwork%ewald_num_mode_local
      mode_offset = localwork%ewald_local_mode_offset

      !$acc data &
      !$acc present(ewald, ewald%zpoint, ewald%zweight, &
      !$acc        ewald%cos_kx_elec(:,0:kmax_x), ewald%sin_kx_elec(:,0:kmax_x), &
      !$acc        ewald%cos_ky_elec(:,0:kmax_y), ewald%sin_ky_elec(:,0:kmax_y), &
      !$acc        ewald%cos_kz_elec(:,0:kmax_z), ewald%sin_kz_elec(:,0:kmax_z), &
      !$acc        ewald%cos_kx_ions(:,0:kmax_x), ewald%sin_kx_ions(:,0:kmax_x), &
      !$acc        ewald%cos_ky_ions(:,0:kmax_y), ewald%sin_ky_ions(:,0:kmax_y), &
      !$acc        ewald%cos_kz_ions(:,0:kmax_z), ewald%sin_kz_ions(:,0:kmax_z), &
      !$acc        ewald%Sk_cos(:), ewald%Sk_sin(:), q_elec(:), force(:,:), &
      !$acc        electrodes, electrodes%force_ions) &
      !$acc copy(loc_stress_tensor_xx,loc_stress_tensor_yy,loc_stress_tensor_zz, &
      !$acc           loc_stress_tensor_xy,loc_stress_tensor_xz,loc_stress_tensor_yz)

      !$acc kernels
      ewald%Sk_cos(:) = 0.0_wp
      ewald%Sk_sin(:) = 0.0_wp
      !$acc end kernels

      ! Long range contribution is computed in reciprocal space
      ! -------------------------------------------------------
      ! The sum over k-modes is symmetric
      !   -> we loop only on half of them and mulitply by 2.0
      ! Total number of modes
      !    (2*kmax_x+1)*(2*kmax_y+1)*nz
      ! Num modes executed globally
      !    (2*kmax_x*kmax_y + kmax_x + kmax_y)*nz
      ! Num modes executed by the local process (approx.)
      !    (2*kmax_x*kmax_y + kmax_x + kmax_y)*nz / num_rank
      volfactor = 2.0_wp / box%area(3)

      ! Setup cache blocking parameters
      do itype = 1, num_ion_types
         qi = ions(itype)%charge

         num_blocks = 0
         if (ions(itype)%count > 0) then
            num_blocks = (ions(itype)%count-1)/block_vector_size + 1
         end if
         iend_type = ions(itype)%offset + ions(itype)%count
         do iblock = 1, num_blocks
            istart_block = (iblock-1)*block_vector_size + ions(itype)%offset + 1
            iend_block = min(istart_block+block_vector_size-1,iend_type)

            !$acc parallel
            !$acc loop gang &
            !$acc private(imode, l, m, n, kx, ky, kz, mabs, nabs, sign_m, sign_n, knorm2, &
            !$acc         cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz, cos_kxky, sin_kxky, &
            !$acc         cos_kxkykz, sin_kxkykz, sk_cos, sk_sin, i)
            do imode = 1, num_modes
               call compute_kmode_index(num_pbc, kmax_x, kmax_y, kmax_z, imode+mode_offset, l, m, n)
               ! kx = l * twopi / box%length(1)
               kx = (real(l,wp) * twopi) * box_lengthx_rec
               ! ky = m * twopi / box%length(2)
               mabs = abs(m)
               sign_m = real(sign(1,m),wp)
               ky = (real(m,wp) * twopi) * box_lengthy_rec
               ! kz = zpoint(n)
               nabs = abs(n)
               sign_n = real(sign(1,n),wp)
               kz = sign_n * ewald%zpoint(nabs)

               ! Norm square of the k-mode vector
               knorm2 = kx*kx + ky*ky + kz*kz
               if (knorm2 <= knorm2_max) then

                  ! Ions contribution to structure factor
                  sk_cos = 0.0_wp
                  sk_sin = 0.0_wp
                  !$acc loop vector reduction(+: sk_cos, sk_sin)
                  do i = istart_block, iend_block

                     cos_kx = ewald%cos_kx_ions(i,l)
                     sin_kx = ewald%sin_kx_ions(i,l)
                     cos_ky = ewald%cos_ky_ions(i,mabs)
                     sin_ky = ewald%sin_ky_ions(i,mabs) * sign_m
                     cos_kz = ewald%cos_kz_ions(i,nabs)
                     sin_kz = ewald%sin_kz_ions(i,nabs) * sign_n

                     cos_kxky = cos_kx * cos_ky - sin_kx * sin_ky
                     sin_kxky = sin_kx * cos_ky + cos_kx * sin_ky

                     cos_kxkykz = cos_kxky * cos_kz - sin_kxky * sin_kz
                     sin_kxkykz = sin_kxky * cos_kz + cos_kxky * sin_kz

                     sk_cos = sk_cos + qi*cos_kxkykz
                     sk_sin = sk_sin + qi*sin_kxkykz
                  end do
                  !$acc end loop
                  ewald%Sk_cos(imode) = ewald%Sk_cos(imode) + sk_cos
                  ewald%Sk_sin(imode) = ewald%Sk_sin(imode) + sk_sin

               end if
            end do ! imode
            !$acc end loop
            !$acc end parallel
         end do
      end do

      do itype = 1, num_elec_types
         num_blocks = 0
         if (electrodes(itype)%count > 0) then
            num_blocks = (electrodes(itype)%count-1)/block_vector_size + 1
         end if
         iend_type = electrodes(itype)%offset + electrodes(itype)%count

         do iblock = 1, num_blocks
            istart_block = (iblock-1)*block_vector_size + 1 + electrodes(itype)%offset
            iend_block = min(istart_block+block_vector_size-1,iend_type)

            !$acc parallel
            !$acc loop gang &
            !$acc private(imode, l, m, n, kx, ky, kz, mabs, nabs, sign_m, sign_n, knorm2, &
            !$acc         cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz, cos_kxky, sin_kxky, &
            !$acc         cos_kxkykz, sin_kxkykz, sk_cos, sk_sin, i)
            do imode = 1, num_modes
               call compute_kmode_index(num_pbc, kmax_x, kmax_y, kmax_z, imode+mode_offset, l, m, n)
               ! kx = l * twopi / box%length(1)
               kx = (real(l,wp) * twopi) * box_lengthx_rec
               ! ky = m * twopi / box%length(2)
               mabs = abs(m)
               sign_m = real(sign(1,m),wp)
               ky = (real(m,wp) * twopi) * box_lengthy_rec
               ! kz = zpoint(n)
               nabs = abs(n)
               sign_n = real(sign(1,n),wp)
               kz = sign_n * ewald%zpoint(nabs)

               ! Norm square of the k-mode vector
               knorm2 = kx*kx + ky*ky + kz*kz
               if (knorm2 <= ewald%knorm2_max) then
                  sk_cos = 0.0_wp
                  sk_sin = 0.0_wp
                  ! Atoms contribution to structure factor
                  !$acc loop vector reduction(+: sk_cos, sk_sin)
                  do i = istart_block, iend_block
                     cos_kx = ewald%cos_kx_elec(i,l)
                     sin_kx = ewald%sin_kx_elec(i,l)
                     cos_ky = ewald%cos_ky_elec(i,mabs)
                     sin_ky = ewald%sin_ky_elec(i,mabs) * sign_m
                     cos_kz = ewald%cos_kz_elec(i,nabs)
                     sin_kz = ewald%sin_kz_elec(i,nabs) * sign_n

                     cos_kxky = cos_kx * cos_ky - sin_kx * sin_ky
                     sin_kxky = sin_kx * cos_ky + cos_kx * sin_ky

                     cos_kxkykz = cos_kxky * cos_kz - sin_kxky * sin_kz
                     sin_kxkykz = sin_kxky * cos_kz + cos_kxky * sin_kz

                     sk_cos = sk_cos + q_elec(i)*cos_kxkykz
                     sk_sin = sk_sin + q_elec(i)*sin_kxkykz
                  end do
                  !$acc end loop
                  ewald%Sk_cos(imode) = ewald%Sk_cos(imode) + sk_cos
                  ewald%Sk_sin(imode) = ewald%Sk_sin(imode) + sk_sin
               end if
            end do ! imode
            !$acc end loop
            !$acc end parallel
         end do
      end do

      ! Setup cache blocking parameters
      do itype = 1, num_ion_types
         qi = ions(itype)%charge

         num_blocks = 0
         if (ions(itype)%count > 0) then
            num_blocks = (ions(itype)%count-1)/block_vector_size + 1
         end if
         iend_type = ions(itype)%offset + ions(itype)%count
         do iblock = 1, num_blocks
            istart_block = (iblock-1)*block_vector_size + ions(itype)%offset + 1
            iend_block = min(istart_block+block_vector_size-1,iend_type)

            !$acc parallel
            !$acc loop gang &
            !$acc private(imode, l, m, n, kx, ky, kz, mabs, nabs, sign_m, sign_n, knorm2, Sk_alpha, &
            !$acc         cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz, &
            !$acc         cos_kxky, sin_kxky, cos_kxkykz, sin_kxkykz, i)
            do imode = 1, num_modes
               call compute_kmode_index(num_pbc, kmax_x, kmax_y, kmax_z, imode+mode_offset, l, m, n)
               ! kx = l * twopi / box%length(1)
               kx = (real(l,wp) * twopi) * box_lengthx_rec
               ! ky = m * twopi / box%length(2)
               mabs = abs(m)
               sign_m = real(sign(1,m),wp)
               ky = (real(m,wp) * twopi) * box_lengthy_rec
               ! kz = zpoint(n)
               nabs = abs(n)
               sign_n = real(sign(1,n),wp)
               kz = sign_n * ewald%zpoint(nabs)

               ! Norm square of the k-mode vector
               knorm2 = kx*kx + ky*ky + kz*kz                       !xkk
               if (knorm2 <= ewald%knorm2_max) then

                  Sk_alpha = 2.0_wp * volfactor * ewald%zweight(nabs) * &
                        (exp(alphaconst*knorm2) / knorm2)          ! akk*8pi/V

                  !$acc loop vector
                  do i = istart_block, iend_block

                     cos_kx = ewald%cos_kx_ions(i,l)
                     sin_kx = ewald%sin_kx_ions(i,l)
                     cos_ky = ewald%cos_ky_ions(i,mabs)
                     sin_ky = ewald%sin_ky_ions(i,mabs) * sign_m
                     cos_kz = ewald%cos_kz_ions(i,nabs)
                     sin_kz = ewald%sin_kz_ions(i,nabs) * sign_n

                     cos_kxky = cos_kx * cos_ky - sin_kx * sin_ky
                     sin_kxky = sin_kx * cos_ky + cos_kx * sin_ky

                     cos_kxkykz = cos_kxky * cos_kz - sin_kxky * sin_kz
                     sin_kxkykz = sin_kxky * cos_kz + cos_kxky * sin_kz

                     ! force
                     !$acc atomic update
                     force(i,1) = force(i,1) + qi * kx * Sk_alpha * &
                          (sin_kxkykz*ewald%Sk_cos(imode) - cos_kxkykz*ewald%Sk_sin(imode))
                     !$acc atomic update
                     force(i,2) = force(i,2) + qi * ky * Sk_alpha * &
                          (sin_kxkykz*ewald%Sk_cos(imode) - cos_kxkykz*ewald%Sk_sin(imode))
                     !$acc atomic update
                     force(i,3) = force(i,3) + qi * kz * Sk_alpha * &
                          (sin_kxkykz*ewald%Sk_cos(imode) - cos_kxkykz*ewald%Sk_sin(imode))

                  end do ! ni
                  !$acc end loop
               end if
            end do ! imode
            !$acc end loop
            !$acc end parallel
         end do
      end do

      ! Setup cache blocking parameters
      !$acc parallel
      !$acc loop gang &
      !$acc private(imode, l, m, n, kx, ky, kz, mabs, nabs, sign_m, sign_n, knorm2, Sk_alpha, &
      !$acc         cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz, &
      !$acc         cos_kxky, sin_kxky, cos_kxkykz, sin_kxkykz, i) reduction(+:loc_stress_tensor_xx,&
      !$acc                       loc_stress_tensor_yy,loc_stress_tensor_zz, &
      !$acc                       loc_stress_tensor_xy,loc_stress_tensor_xz, &
      !$acc                       loc_stress_tensor_yz)
      do imode = 1, num_modes
         call compute_kmode_index(num_pbc, kmax_x, kmax_y, kmax_z, imode+mode_offset, l, m, n)
         ! kx = l * twopi / box%length(1)
         kx = (real(l,wp) * twopi) * box_lengthx_rec
         ! ky = m * twopi / box%length(2)
         mabs = abs(m)
         sign_m = real(sign(1,m),wp)
         ky = (real(m,wp) * twopi) * box_lengthy_rec
         ! kz = zpoint(n)
         nabs = abs(n)
         sign_n = real(sign(1,n),wp)
         kz = sign_n * ewald%zpoint(nabs)

         ! Norm square of the k-mode vector
         knorm2 = kx*kx + ky*ky + kz*kz                       !xkk
         if (knorm2 <= ewald%knorm2_max) then

            Sk_alpha = 2.0_wp * volfactor * ewald%zweight(nabs) * &
                  (exp(alphaconst*knorm2) / knorm2)          ! akk*8pi/V

            stfac1 = (4.0_wp*alphasq+knorm2)/(4.0_wp*alphasq*knorm2)
            stfac2 = Sk_alpha * (ewald%Sk_cos(imode)**2.0+ewald%Sk_sin(imode)**2.0)/2.0_wp

            loc_stress_tensor_xx=loc_stress_tensor_xx+ &
                     (1.0_wp-2.0_wp * kx * kx * stfac1)*stfac2
            loc_stress_tensor_yy=loc_stress_tensor_yy+ &
                     (1.0_wp-2.0_wp * ky * ky * stfac1)*stfac2
            loc_stress_tensor_zz=loc_stress_tensor_zz+ &
                     (1.0_wp-2.0_wp * kz * kz * stfac1)*stfac2
            loc_stress_tensor_xy=loc_stress_tensor_xy+ &
                     (-2.0_wp * kx * ky * stfac1)*stfac2
            loc_stress_tensor_xz=loc_stress_tensor_xz+ &
                     (-2.0_wp * kx * kz * stfac1)*stfac2
            loc_stress_tensor_yz=loc_stress_tensor_yz+ &
                     (-2.0_wp * ky * kz * stfac1)*stfac2
         end if
      end do ! imode
      !$acc end loop
      !$acc end parallel

      ! Setup cache blocking parameters
      if (compute_force) then
         do itype = 1, num_elec_types
            num_blocks = 0
            if (electrodes(itype)%count > 0) then
               num_blocks = (electrodes(itype)%count-1)/block_vector_size + 1
            end if
            iend_type = electrodes(itype)%offset + electrodes(itype)%count
            do iblock = 1, num_blocks
               istart_block = (iblock-1)*block_vector_size + electrodes(itype)%offset + 1
               iend_block = min(istart_block+block_vector_size-1,iend_type)

               !$acc parallel
               !$acc loop gang &
               !$acc private(imode, l, m, n, kx, ky, kz, mabs, nabs, sign_m, sign_n, knorm2, Sk_alpha, &
               !$acc         cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz, &
               !$acc         cos_kxky, sin_kxky, cos_kxkykz, sin_kxkykz, i)
               do imode = 1, num_modes
                  call compute_kmode_index(num_pbc, kmax_x, kmax_y, kmax_z, imode+mode_offset, l, m, n)
                  ! kx = l * twopi / box%length(1)
                  kx = (real(l,wp) * twopi) * box_lengthx_rec
                  ! ky = m * twopi / box%length(2)
                  mabs = abs(m)
                  sign_m = real(sign(1,m),wp)
                  ky = (real(m,wp) * twopi) * box_lengthy_rec
                  ! kz = zpoint(n)
                  nabs = abs(n)
                  sign_n = real(sign(1,n),wp)
                  kz = sign_n * ewald%zpoint(nabs)

                  ! Norm square of the k-mode vector
                  knorm2 = kx*kx + ky*ky + kz*kz
                  if (knorm2 <= ewald%knorm2_max) then

                     Sk_alpha = 2.0_wp * volfactor * ewald%zweight(nabs) * &
                           (exp(alphaconst*knorm2) / knorm2)

                     !$acc loop vector
                     do i = istart_block, iend_block

                        cos_kx = ewald%cos_kx_elec(i,l)
                        sin_kx = ewald%sin_kx_elec(i,l)
                        cos_ky = ewald%cos_ky_elec(i,mabs)
                        sin_ky = ewald%sin_ky_elec(i,mabs) * sign_m
                        cos_kz = ewald%cos_kz_elec(i,nabs)
                        sin_kz = ewald%sin_kz_elec(i,nabs) * sign_n

                        cos_kxky = cos_kx * cos_ky - sin_kx * sin_ky
                        sin_kxky = sin_kx * cos_ky + cos_kx * sin_ky

                        cos_kxkykz = cos_kxky * cos_kz - sin_kxky * sin_kz
                        sin_kxkykz = sin_kxky * cos_kz + cos_kxky * sin_kz

                        ! force
                        electrodes(itype)%force_ions(1,6) = electrodes(itype)%force_ions(1,6) + q_elec(i) * kx * Sk_alpha * &
                             (sin_kxkykz*ewald%Sk_cos(imode) - cos_kxkykz*ewald%Sk_sin(imode))
                        electrodes(itype)%force_ions(2,6) = electrodes(itype)%force_ions(2,6) + q_elec(i) * ky * Sk_alpha * &
                             (sin_kxkykz*ewald%Sk_cos(imode) - cos_kxkykz*ewald%Sk_sin(imode))
                        electrodes(itype)%force_ions(3,6) = electrodes(itype)%force_ions(3,6) + q_elec(i) * kz * Sk_alpha * &
                             (sin_kxkykz*ewald%Sk_cos(imode) - cos_kxkykz*ewald%Sk_sin(imode))

                     end do ! ni
                     !$acc end loop
                  end if
               end do ! imode
               !$acc end loop
               !$acc end parallel
            end do
         end do
      end if

      !$acc end data
      stress_tensor(1,1) = loc_stress_tensor_xx
      stress_tensor(2,2) = loc_stress_tensor_yy
      stress_tensor(3,3) = loc_stress_tensor_zz
      stress_tensor(1,2) = loc_stress_tensor_xy
      stress_tensor(1,3) = loc_stress_tensor_xz
      stress_tensor(2,3) = loc_stress_tensor_yz

   end subroutine melt_forces

   !================================================================================
   ! Compute the contibution to the energy from long-range Coulomb interaction
   subroutine energy(localwork, ewald, box, ions, &
         electrodes, q_elec, h)
      implicit none

      ! Parameters in
      ! -------------
      type(MW_localwork_t), intent(in) :: localwork       !< Local work assignment
      type(MW_ewald_t),     intent(in) :: ewald           !< Ewald summation parameters
      type(MW_box_t),       intent(in) :: box             !< Simulation box parameters
      type(MW_ion_t),       intent(in) :: ions(:)         !< ions parameters
      type(MW_electrode_t), intent(in) :: electrodes(:)   !< electrodes parameters
      real(wp),             intent(in) :: q_elec(:)       !< Electrode atoms charge

      ! Parameters out
      ! --------------
      real(wp), intent(inout) :: h !< energy

      ! Local
      ! -----
      integer :: num_ion_types, num_elec_types
      integer :: i, itype, iion
      integer :: l, m, n, mabs, nabs
      integer :: kmax_x, kmax_y, kmax_z
      real(wp) :: sign_m, sign_n
      real(wp) :: qi
      real(wp) :: kx, ky, kz, knorm2, knorm2_max
      real(wp) :: Sk_cos, Sk_sin, Sk_alpha , Sk_cos_type, Sk_sin_type !< Structure factor coefficients
      real(wp) :: cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz
      real(wp) :: cos_kxky, sin_kxky, cos_kxkykz, sin_kxkykz
      real(wp) :: volfactor
      real(wp) :: alpha, alphasq, alphaconst
      real(wp) :: box_lengthx_rec, box_lengthy_rec
      integer :: imode, num_modes, mode_offset
      integer :: num_pbc

      num_ion_types = size(ions,1)
      num_elec_types = size(electrodes,1)

      ! Precompute some factors
      ! -----------------------
      alpha = ewald%alpha
      alphasq = alpha*alpha
      alphaconst = - 1.0_wp/(4.0_wp*alphasq)

      num_pbc = ewald%num_pbc
      box_lengthx_rec = 1.0_wp / box%length(1)
      box_lengthy_rec = 1.0_wp / box%length(2)

      knorm2_max = ewald%knorm2_max
      kmax_x = ewald%kmax_x
      kmax_y = ewald%kmax_y
      kmax_z = ewald%kmax_z

      num_modes = localwork%ewald_num_mode_local
      mode_offset = localwork%ewald_local_mode_offset


      !$acc data &
      !$acc present(ewald, ewald%zpoint, ewald%zweight, ions(:), electrodes(:), &
      !$acc        ewald%cos_kx_elec(:,0:kmax_x), ewald%sin_kx_elec(:,0:kmax_x), &
      !$acc        ewald%cos_ky_elec(:,0:kmax_y), ewald%sin_ky_elec(:,0:kmax_y), &
      !$acc        ewald%cos_kz_elec(:,0:kmax_z), ewald%sin_kz_elec(:,0:kmax_z), &
      !$acc        ewald%cos_kx_ions(:,0:kmax_x), ewald%sin_kx_ions(:,0:kmax_x), &
      !$acc        ewald%cos_ky_ions(:,0:kmax_y), ewald%sin_ky_ions(:,0:kmax_y), &
      !$acc        ewald%cos_kz_ions(:,0:kmax_z), ewald%sin_kz_ions(:,0:kmax_z), &
      !$acc        q_elec(:)) copy(h)

      ! Long range contribution is computed in reciprocal space
      ! -------------------------------------------------------
      ! The sum over k-modes is symmetric
      !   -> we loop only on half of them and mulitply by 2.0
      ! Total number of modes
      !    (2*kmax_x+1)*(2*kmax_y+1)*nz
      ! Num modes executed globally
      !    (2*kmax_x*kmax_y + kmax_x + kmax_y)*nz
      ! Num modes executed by the local process (approx.)
      !    (2*kmax_x*kmax_y + kmax_x + kmax_y)*nz / num_rank
      volfactor = 1.0_wp / box%area(3)

      !$acc parallel
      !$acc loop gang &
      !$acc private(imode, l, m, n, kx, ky, kz, mabs, nabs, sign_m, sign_n, knorm2, &
      !$acc         cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz, cos_kxky, sin_kxky, &
      !$acc         cos_kxkykz, sin_kxkykz, sk_cos, sk_sin, i, qi, Sk_alpha) &
      !$acc reduction(+:h)

      do imode = 1, num_modes
         call compute_kmode_index(num_pbc, kmax_x, kmax_y, kmax_z, imode+mode_offset, l, m, n)
         ! kx = l * twopi / box%length(1)
         kx = (real(l,wp) * twopi) * box_lengthx_rec
         ! ky = m * twopi / box%length(2)
         mabs = abs(m)
         sign_m = real(sign(1,m),wp)
         ky = (real(m,wp) * twopi) * box_lengthy_rec
         ! kz = zpoint(n)
         nabs = abs(n)
         sign_n = real(sign(1,n),wp)
         kz = sign_n * ewald%zpoint(nabs)

         ! Norm square of the k-mode vector
         knorm2 = kx*kx + ky*ky + kz*kz
         if (knorm2 <= ewald%knorm2_max) then

            Sk_cos = 0.0_wp
            Sk_sin = 0.0_wp

            ! Ions contribution to structure factor
            !$acc loop seq
            do itype = 1, num_ion_types
               qi = ions(itype)%charge
               Sk_cos_type = 0.0_wp
               Sk_sin_type = 0.0_wp
               !$acc loop vector reduction(+: Sk_cos_type, Sk_sin_type)
               do i = 1, ions(itype)%count
                  iion = ions(itype)%offset + i
                  cos_kx = ewald%cos_kx_ions(iion,l)
                  sin_kx = ewald%sin_kx_ions(iion,l)
                  cos_ky = ewald%cos_ky_ions(iion,mabs)
                  sin_ky = ewald%sin_ky_ions(iion,mabs) * sign_m
                  cos_kz = ewald%cos_kz_ions(iion,nabs)
                  sin_kz = ewald%sin_kz_ions(iion,nabs) * sign_n

                  cos_kxky = cos_kx * cos_ky - sin_kx * sin_ky
                  sin_kxky = sin_kx * cos_ky + cos_kx * sin_ky

                  cos_kxkykz = cos_kxky * cos_kz - sin_kxky * sin_kz
                  sin_kxkykz = sin_kxky * cos_kz + cos_kxky * sin_kz

                  Sk_cos_type = Sk_cos_type + qi*cos_kxkykz
                  Sk_sin_type = Sk_sin_type + qi*sin_kxkykz
               end do
               !$acc end loop
               Sk_cos = Sk_cos + Sk_cos_type
               Sk_sin = Sk_sin + Sk_sin_type
            end do
            !$acc end loop

            ! Atoms contribution to structure factor
            !$acc loop seq
            do itype = 1, num_elec_types
               Sk_cos_type = 0.0_wp
               Sk_sin_type = 0.0_wp
               !$acc loop vector reduction(+: Sk_cos_type, Sk_sin_type)
               do i = 1, electrodes(itype)%count
                  iion = electrodes(itype)%offset + i
                  cos_kx = ewald%cos_kx_elec(iion,l)
                  sin_kx = ewald%sin_kx_elec(iion,l)
                  cos_ky = ewald%cos_ky_elec(iion,mabs)
                  sin_ky = ewald%sin_ky_elec(iion,mabs) * sign_m
                  cos_kz = ewald%cos_kz_elec(iion,nabs)
                  sin_kz = ewald%sin_kz_elec(iion,nabs) * sign_n

                  cos_kxky = cos_kx * cos_ky - sin_kx * sin_ky
                  sin_kxky = sin_kx * cos_ky + cos_kx * sin_ky

                  cos_kxkykz = cos_kxky * cos_kz - sin_kxky * sin_kz
                  sin_kxkykz = sin_kxky * cos_kz + cos_kxky * sin_kz

                  Sk_cos_type = Sk_cos_type + q_elec(iion)*cos_kxkykz
                  Sk_sin_type = Sk_sin_type + q_elec(iion)*sin_kxkykz
               end do
               !$acc end loop
               Sk_cos = Sk_cos + Sk_cos_type
               Sk_sin = Sk_sin + Sk_sin_type
            end do
            !$acc end loop
            Sk_alpha = 2.0_wp * volfactor * ewald%zweight(nabs) * &
                  (exp(alphaconst*knorm2) / knorm2)
            h = h + Sk_alpha * (Sk_cos*Sk_cos + Sk_sin*Sk_sin)
         end if
      end do ! imode
      !$acc end loop
      !$acc end parallel
      !$acc end data
   end subroutine energy

   !=========================================================================================
   ! Compute the electric field gradient felt by each melt ion due to other melt ions charges
   subroutine melt_efg(localwork, ewald, box, ions, efg)
      implicit none

      ! Parameters in
      ! -------------
      type(MW_localwork_t), intent(in)    :: localwork       !< Local work assignment
      type(MW_box_t),       intent(in)    :: box             !< Simulation box parameters
      type(MW_ion_t),       intent(in)    :: ions(:)         !< ions parameters

      ! Parameters out
      ! --------------
      type(MW_ewald_t),     intent(inout) :: ewald           !< Ewald summation parameters
      real(wp),             intent(inout) :: efg(:,:)        !< Electric field on ions

      ! Local
      ! -----
      integer :: num_ion_types
      integer :: i, itype
      logical :: itype_needs_efg
      integer :: l, m, n, mabs, nabs
      integer :: kmax_x, kmax_y, kmax_z
      real(wp) :: sign_m, sign_n
      real(wp) :: qi
      real(wp) :: kx, ky, kz, knorm2, knorm2_max
      real(wp) :: Sk_alpha !< Structure factor coefficients
      real(wp) :: cos_kx, sin_kx, cos_ky, sin_ky, cos_kz, sin_kz
      real(wp) :: cos_kxky, sin_kxky, cos_kxkykz, sin_kxkykz
      real(wp) :: volfactor
      real(wp) :: alpha, alphasq, alphaconst
      real(wp) :: box_lengthx_rec, box_lengthy_rec
      real(wp) :: sk_cos, sk_sin
      real(wp) :: efg_imode

      integer :: imode, num_modes, mode_offset
      integer :: iblock, num_blocks, istart_block, iend_block, iend_type
      integer :: num_pbc

      num_ion_types = size(ions,1)

      ! Precompute some factors
      ! -----------------------
      alpha = ewald%alpha
      alphasq = alpha*alpha
      alphaconst = -1.0_wp/(4.0_wp*alphasq)

      num_pbc = ewald%num_pbc
      box_lengthx_rec = 1.0_wp/box%length(1)
      box_lengthy_rec = 1.0_wp/box%length(2)

      knorm2_max = ewald%knorm2_max
      kmax_x = ewald%kmax_x
      kmax_y = ewald%kmax_y
      kmax_z = ewald%kmax_z

      num_modes = localwork%ewald_num_mode_local
      mode_offset = localwork%ewald_local_mode_offset

      ! Zero the arrays for sums of sin and cos before the computation.
      ewald%Sk_cos(:) = 0.0_wp
      ewald%Sk_sin(:) = 0.0_wp

      ! Long range contribution is computed in reciprocal space
      ! -------------------------------------------------------
      ! The sum over k-modes is symmetric
      !   -> we loop only on half of them and mulitply by 2.0
      ! Total number of modes
      !    (2*kmax_x+1)*(2*kmax_y+1)*nz
      ! Num modes executed globally
      !    (2*kmax_x*kmax_y + kmax_x + kmax_y)*nz
      ! Num modes executed by the local process (approx.)
      !    (2*kmax_x*kmax_y + kmax_x + kmax_y)*nz / num_rank
      volfactor = 2.0_wp/box%area(3)

      ! Ions: cache thu sums over sin and cos.
      ! Setup cache blocking parameters
      do itype = 1, num_ion_types
         qi = ions(itype)%charge
         num_blocks = 0
         if (ions(itype)%count > 0) then
            num_blocks = (ions(itype)%count-1)/block_vector_size + 1
         end if
         iend_type = ions(itype)%offset + ions(itype)%count
         do iblock = 1, num_blocks
            istart_block = (iblock-1)*block_vector_size + ions(itype)%offset + 1
            iend_block = min(istart_block+block_vector_size-1,iend_type)

            ! Each processor works on its part of modes in parallel.
            do imode = 1, num_modes
               call compute_kmode_index(num_pbc, kmax_x, kmax_y, kmax_z, imode+mode_offset, l, m, n)
               ! kx = l * twopi / box%length(1)
               kx = (real(l,wp)*twopi)*box_lengthx_rec
               ! ky = m * twopi / box%length(2)
               mabs = abs(m)
               sign_m = real(sign(1,m),wp)
               ky = (real(m,wp)*twopi)*box_lengthy_rec
               ! kz = zpoint(n)
               nabs = abs(n)
               sign_n = real(sign(1,n),wp)
               kz = sign_n*ewald%zpoint(nabs)

               ! Norm square of the k-mode vector
               knorm2 = kx*kx + ky*ky + kz*kz
               if (knorm2 <= knorm2_max) then

                  ! Ions contribution to structure factor
                  sk_cos = 0.0_wp
                  sk_sin = 0.0_wp
                  do i = istart_block, iend_block

                     cos_kx = ewald%cos_kx_ions(i,l)
                     sin_kx = ewald%sin_kx_ions(i,l)
                     cos_ky = ewald%cos_ky_ions(i,mabs)
                     sin_ky = ewald%sin_ky_ions(i,mabs)*sign_m
                     cos_kz = ewald%cos_kz_ions(i,nabs)
                     sin_kz = ewald%sin_kz_ions(i,nabs)*sign_n

                     cos_kxky = cos_kx*cos_ky - sin_kx*sin_ky
                     sin_kxky = sin_kx*cos_ky + cos_kx*sin_ky

                     cos_kxkykz = cos_kxky*cos_kz - sin_kxky*sin_kz
                     sin_kxkykz = sin_kxky*cos_kz + cos_kxky*sin_kz

                     sk_cos = sk_cos + qi*cos_kxkykz
                     sk_sin = sk_sin + qi*sin_kxkykz
                  end do
                  ewald%Sk_cos(imode) = ewald%Sk_cos(imode) + sk_cos
                  ewald%Sk_sin(imode) = ewald%Sk_sin(imode) + sk_sin

               end if
            end do ! imode
         end do
      end do

      ! Compute the contribution to the electric field gradient on ion positions.
      ! Setup cache blocking parameters
      do itype = 1, num_ion_types
         qi = ions(itype)%charge
         itype_needs_efg = ions(itype)%dump_efg

         ! Run the computation for selected ion types only
         if (itype_needs_efg) then
            num_blocks = 0
            if (ions(itype)%count > 0) then
               num_blocks = (ions(itype)%count-1)/block_vector_size + 1
            end if
            iend_type = ions(itype)%offset + ions(itype)%count
            do iblock = 1, num_blocks
               istart_block = (iblock-1)*block_vector_size + ions(itype)%offset + 1
               iend_block = min(istart_block+block_vector_size-1,iend_type)

               do imode = 1, num_modes
                  call compute_kmode_index(num_pbc, kmax_x, kmax_y, kmax_z, imode+mode_offset, l, m, n)
                  ! kx = l * twopi / box%length(1)
                  kx = (real(l,wp)*twopi)*box_lengthx_rec
                  ! ky = m*twopi / box%length(2)
                  mabs = abs(m)
                  sign_m = real(sign(1,m),wp)
                  ky = (real(m,wp)*twopi)*box_lengthy_rec
                  ! kz = zpoint(n)
                  nabs = abs(n)
                  sign_n = real(sign(1,n),wp)
                  kz = sign_n*ewald%zpoint(nabs)

                  ! Norm square of the k-mode vector
                  knorm2 = kx*kx + ky*ky + kz*kz
                  if (knorm2 <= ewald%knorm2_max) then

                     Sk_alpha = 2.0_wp*volfactor*ewald%zweight(nabs)*(exp(alphaconst*knorm2)/knorm2)

                     do i = istart_block, iend_block
                        cos_kx = ewald%cos_kx_ions(i,l)
                        sin_kx = ewald%sin_kx_ions(i,l)
                        cos_ky = ewald%cos_ky_ions(i,mabs)
                        sin_ky = ewald%sin_ky_ions(i,mabs)*sign_m
                        cos_kz = ewald%cos_kz_ions(i,nabs)
                        sin_kz = ewald%sin_kz_ions(i,nabs)*sign_n

                        cos_kxky = cos_kx*cos_ky - sin_kx*sin_ky
                        sin_kxky = sin_kx*cos_ky + cos_kx*sin_ky

                        cos_kxkykz = cos_kxky*cos_kz - sin_kxky*sin_kz
                        sin_kxkykz = sin_kxky*cos_kz + cos_kxky*sin_kz

                        ! The efg prefactor for a fixed k-vector
                        efg_imode = Sk_alpha*(sin_kxkykz*ewald%Sk_sin(imode) + &
                                              cos_kxkykz*ewald%Sk_cos(imode))

                        ! Electric field gradient components
                        efg(i,1) = efg(i,1) + kx*kx*efg_imode ! xx
                        efg(i,2) = efg(i,2) + kx*ky*efg_imode ! xy
                        efg(i,3) = efg(i,3) + kx*kz*efg_imode ! xz
                        efg(i,4) = efg(i,4) + ky*ky*efg_imode ! yy
                        efg(i,5) = efg(i,5) + ky*kz*efg_imode ! yz
                        efg(i,6) = efg(i,6) + kz*kz*efg_imode ! zz

                     end do ! ni
                  end if
               end do ! imode
            end do
         end if ! itype_needs_efg
      end do

   end subroutine melt_efg

   include 'update_kmode_index.inc'

end module MW_coulomb_lr
