! ==============================================================================
! Compute daim forces felt by melt ions
subroutine melt_forces_@PBC@(localwork, daim, box, ions, xyz_ions, &
      electrodes, xyz_atoms, force,stress_tensor,delta,epsilon)
   implicit none

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

   type(MW_ion_t), intent(in) :: ions(:)        !< ions parameters
   real(wp),       intent(in) :: xyz_ions(:,:)  !< ions xyz positions

   type(MW_electrode_t), intent(inout) :: electrodes(:)  !< electrode parameters
   real(wp),             intent(in) :: xyz_atoms(:,:)  !< electrode atoms xyz positions
   real(wp),             intent(in) :: delta(:)  !<  Deltas of ions
   real(wp),             intent(in) :: epsilon(:,:)  !< Epsilons of ions

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

   ! Locals
   ! ------
   integer :: num_ion_types, num_elec
   integer :: itype, jtype, i, j
   real(wp) :: a, b, c
   real(wp) :: drnorm2, dx, dy, dz
   real(wp), dimension(3) :: ft_ij
   real(wp) :: deltai,deltaj
   real(wp) :: epsilonix,epsiloniy,epsiloniz
   real(wp) :: epsilonjx,epsilonjy,epsilonjz
   real(wp) :: eta1_ij, B1_ij
   real(wp) :: eta2_ij, B2_ij
   real(wp) :: eta3_ij, B3_ij
   real(wp) :: C_ij, D_ij, damp_dd_ij, damp_dq_ij
   real(wp) :: fx_melt2ele, fy_melt2ele, fz_melt2ele
   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
   integer :: num_block_diag, num_block_full
   integer :: iblock, iblock_offset, istart, iend, jstart, jend
   integer :: count_n, offset_n, count_m, offset_m

   call MW_timers_start(TIMER_VAN_DER_WAALS_MELT_FORCES)

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

   a = box%length(1)
   b = box%length(2)
   c = box%length(3)

   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 

   !$acc data present(xyz_ions(:,:), xyz_atoms(:,:), force(:,:), delta(:), epsilon(:,:), &
   !$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           fx_melt2ele, fy_melt2ele, fz_melt2ele)   

   ! Blocks on the diagonal compute only half of the pair interactions
   do itype = 1, num_ion_types
      count_n = ions(itype)%count
      offset_n = ions(itype)%offset
      do jtype = 1, itype - 1
         count_m = ions(jtype)%count
         offset_m = ions(jtype)%offset
         eta1_ij = daim%eta1(itype, jtype)
         eta2_ij = daim%eta2(itype, jtype)
         eta3_ij = daim%eta3(itype, jtype)
         B1_ij = daim%B1(itype, jtype)
         B2_ij = daim%B2(itype, jtype)
         B3_ij = daim%B3(itype, jtype)
         C_ij = daim%C(itype, jtype)
         D_ij = daim%D(itype, jtype)
         damp_dd_ij = daim%damp_dd(itype, jtype)
         damp_dq_ij = daim%damp_dq(itype, jtype)
         ! Number of blocks with full ion2ion interactions
         num_block_full = localwork%pair_ion2ion_num_block_full_local(itype, jtype)
         iblock_offset = localwork%pair_ion2ion_full_iblock_offset(itype, jtype)
         do iblock = 1, num_block_full
            call update_other_block_boundaries(iblock_offset+iblock, &
                  offset_n, count_n, offset_m, count_m, &
                  istart, iend, jstart, jend)
            !$acc parallel loop  &
            !$acc reduction(+: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)            
            do i = istart, iend
               !$acc loop private(dx, dy, dz, drnorm2, deltai, deltaj, epsilonix, epsiloniy, epsiloniz, &
               !$acc         epsilonjx, epsilonjy, epsilonjz, ft_ij(:)) &
               !$acc reduction(+: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)            
               do j = jstart, jend
                  call minimum_image_displacement_@PBC@(a, b, c, &
                        xyz_ions(i,1), xyz_ions(i,2), xyz_ions(i,3), &
                        xyz_ions(j,1), xyz_ions(j,2), xyz_ions(j,3), &
                        dx, dy, dz, drnorm2)
                  if (drnorm2 < daim%rcutsq) then
                     deltai=delta(i)
                     deltaj=delta(j)
                     epsilonix=epsilon(i,1)
                     epsiloniy=epsilon(i,2)
                     epsiloniz=epsilon(i,3)
                     epsilonjx=epsilon(j,1)
                     epsilonjy=epsilon(j,2)
                     epsilonjz=epsilon(j,3)
                     ft_ij = force_ij(dx,dy,dz,drnorm2,deltai, deltaj, &
                        epsilonix,epsiloniy,epsiloniz,epsilonjx,epsilonjy,epsilonjz, &
                        eta1_ij, eta2_ij, eta3_ij, B1_ij, B2_ij, B3_ij, &
                        C_ij, D_ij, damp_dd_ij, damp_dq_ij)

                     !$acc atomic update                        
                     force(i,1) = force(i,1) +  ft_ij(1)
                     !$acc atomic update                        
                     force(i,2) = force(i,2) +  ft_ij(2)
                     !$acc atomic update                        
                     force(i,3) = force(i,3) +  ft_ij(3)

                     !$acc atomic update                        
                     force(j,1) = force(j,1) -  ft_ij(1)
                     !$acc atomic update                        
                     force(j,2) = force(j,2) -  ft_ij(2)
                     !$acc atomic update                        
                     force(j,3) = force(j,3) -  ft_ij(3)

                     loc_stress_tensor_xx = loc_stress_tensor_xx - dx * ft_ij(1)
                     loc_stress_tensor_yy = loc_stress_tensor_yy - dy * ft_ij(2)
                     loc_stress_tensor_zz = loc_stress_tensor_zz - dz * ft_ij(3)
                     loc_stress_tensor_xy = loc_stress_tensor_xy - dx * ft_ij(2)
                     loc_stress_tensor_xz = loc_stress_tensor_xz - dx * ft_ij(3)
                     loc_stress_tensor_yz = loc_stress_tensor_yz - dy * ft_ij(3)                     

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

      eta1_ij = daim%eta1(itype, itype)
      eta2_ij = daim%eta2(itype, itype)
      eta3_ij = daim%eta3(itype, itype)
      B1_ij = daim%B1(itype, itype)
      B2_ij = daim%B2(itype, itype)
      B3_ij = daim%B3(itype, itype)
      C_ij = daim%C(itype, itype)
      D_ij = daim%D(itype, itype)
      damp_dd_ij = daim%damp_dd(itype, itype)
      damp_dq_ij = daim%damp_dq(itype, itype)

      num_block_diag = localwork%pair_ion2ion_num_block_diag_local(itype)
      iblock_offset = localwork%pair_ion2ion_diag_iblock_offset(itype)
      do iblock = 1, num_block_diag
         call update_diag_block_boundaries(iblock_offset+iblock, &
               offset_n, count_n, istart, iend)
         !$acc parallel loop  &
         !$acc reduction(+: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)            
         do i = istart, iend
            !$acc loop private(dx, dy, dz, drnorm2, deltai, deltaj, epsilonix, epsiloniy, epsiloniz, &
            !$acc         epsilonjx, epsilonjy, epsilonjz, ft_ij(:)) &
            !$acc reduction(+: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)            
            do j = istart, iend
               call minimum_image_displacement_@PBC@(a, b, c, &
                     xyz_ions(i,1), xyz_ions(i,2), xyz_ions(i,3), &
                     xyz_ions(j,1), xyz_ions(j,2), xyz_ions(j,3), &
                     dx, dy, dz, drnorm2)
               if ((drnorm2 > 0.0_wp) .and. (drnorm2 < daim%rcutsq)) then
                  deltai=delta(i)
                  deltaj=delta(j)
                  epsilonix=epsilon(i,1)
                  epsiloniy=epsilon(i,2)
                  epsiloniz=epsilon(i,3)
                  epsilonjx=epsilon(j,1)
                  epsilonjy=epsilon(j,2)
                  epsilonjz=epsilon(j,3)
                  ft_ij = force_ij(dx,dy,dz,drnorm2,deltai, deltaj, &
                     epsilonix,epsiloniy,epsiloniz,epsilonjx,epsilonjy,epsilonjz, &
                     eta1_ij, eta2_ij, eta3_ij, B1_ij, B2_ij, B3_ij, &
                     C_ij, D_ij, damp_dd_ij, damp_dq_ij)

                  !$acc atomic update                        
                  force(j,1) = force(j,1) - ft_ij(1)
                  !$acc atomic update                        
                  force(j,2) = force(j,2) - ft_ij(2)
                  !$acc atomic update                        
                  force(j,3) = force(j,3) - ft_ij(3)

                  loc_stress_tensor_xx = loc_stress_tensor_xx - 0.5_wp * dx * ft_ij(1)
                  loc_stress_tensor_yy = loc_stress_tensor_yy - 0.5_wp * dy * ft_ij(2)
                  loc_stress_tensor_zz = loc_stress_tensor_zz - 0.5_wp * dz * ft_ij(3)
                  loc_stress_tensor_xy = loc_stress_tensor_xy - 0.5_wp * dx * ft_ij(2)
                  loc_stress_tensor_xz = loc_stress_tensor_xz - 0.5_wp * dx * ft_ij(3)
                  loc_stress_tensor_yz = loc_stress_tensor_yz - 0.5_wp * dy * ft_ij(3)

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

      ! Number of blocks with full ion2ion interactions
      num_block_full = localwork%pair_ion2ion_num_block_full_local(itype,itype)
      iblock_offset = localwork%pair_ion2ion_full_iblock_offset(itype,itype)
      do iblock = 1, num_block_full
         call update_tri_block_boundaries(iblock_offset+iblock, offset_n, count_n, &
               istart, iend, jstart, jend)
         !$acc parallel loop  &
         !$acc reduction(+: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)            
         do i = istart, iend
            !$acc loop private(dx, dy, dz, drnorm2, deltai, deltaj, epsilonix, epsiloniy, epsiloniz, &
            !$acc         epsilonjx, epsilonjy, epsilonjz, ft_ij(:)) &
            !$acc reduction(+: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)            
            do j = jstart, jend
               call minimum_image_displacement_@PBC@(a, b, c, &
                     xyz_ions(i,1), xyz_ions(i,2), xyz_ions(i,3), &
                     xyz_ions(j,1), xyz_ions(j,2), xyz_ions(j,3), &
                     dx, dy, dz, drnorm2)
               if (drnorm2 < daim%rcutsq) then
                  deltai=delta(i)
                  deltaj=delta(j)
                  epsilonix=epsilon(i,1)
                  epsiloniy=epsilon(i,2)
                  epsiloniz=epsilon(i,3)
                  epsilonjx=epsilon(j,1)
                  epsilonjy=epsilon(j,2)
                  epsilonjz=epsilon(j,3)
                  ft_ij = force_ij(dx,dy,dz,drnorm2,deltai, deltaj, &
                     epsilonix,epsiloniy,epsiloniz,epsilonjx,epsilonjy,epsilonjz, &
                     eta1_ij, eta2_ij, eta3_ij, B1_ij, B2_ij, B3_ij, &
                     C_ij, D_ij, damp_dd_ij, damp_dq_ij)
                  
                  !$acc atomic update                        
                  force(i,1) = force(i,1) +  ft_ij(1)
                  !$acc atomic update                        
                  force(i,2) = force(i,2) +  ft_ij(2)
                  !$acc atomic update                        
                  force(i,3) = force(i,3) +  ft_ij(3)

                  !$acc atomic update                        
                  force(j,1) = force(j,1) -  ft_ij(1)
                  !$acc atomic update                        
                  force(j,2) = force(j,2) -  ft_ij(2)
                  !$acc atomic update                        
                  force(j,3) = force(j,3) -  ft_ij(3)

                  loc_stress_tensor_xx = loc_stress_tensor_xx - dx * ft_ij(1)
                  loc_stress_tensor_yy = loc_stress_tensor_yy - dy * ft_ij(2)
                  loc_stress_tensor_zz = loc_stress_tensor_zz - dz * ft_ij(3)
                  loc_stress_tensor_xy = loc_stress_tensor_xy - dx * ft_ij(2)
                  loc_stress_tensor_xz = loc_stress_tensor_xz - dx * ft_ij(3)
                  loc_stress_tensor_yz = loc_stress_tensor_yz - dy * ft_ij(3)
                  
               end if
            end do
            !$acc end loop
         end do
         !$acc end parallel loop
      end do

      do jtype = 1, num_elec
         count_m = electrodes(jtype)%count
         offset_m = electrodes(jtype)%offset

         eta1_ij = daim%eta1(itype, jtype+num_ion_types)
         eta2_ij = daim%eta2(itype, jtype+num_ion_types)
         eta3_ij = daim%eta3(itype, jtype+num_ion_types)
         B1_ij = daim%B1(itype, jtype+num_ion_types)
         B2_ij = daim%B2(itype, jtype+num_ion_types)
         B3_ij = daim%B3(itype, jtype+num_ion_types)
         C_ij = daim%C(itype, jtype+num_ion_types)
         D_ij = daim%D(itype, jtype+num_ion_types)
         damp_dd_ij = daim%damp_dd(itype, jtype+num_ion_types)
         damp_dq_ij = daim%damp_dq(itype, jtype+num_ion_types)

         fx_melt2ele = 0.0_wp
         fy_melt2ele = 0.0_wp
         fz_melt2ele = 0.0_wp

         ! Number of blocks with full atom2ions interactions
         num_block_full = localwork%pair_atom2ion_num_block_full_local(itype, jtype)
         iblock_offset = localwork%pair_atom2ion_full_iblock_offset(itype, jtype)
         do iblock = 1, num_block_full
            call update_other_block_boundaries(iblock_offset+iblock, &
                  offset_n, count_n, offset_m, count_m, &
                  istart, iend, jstart, jend)
            !$acc parallel loop  &
            !$acc reduction(+: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             fx_melt2ele, fy_melt2ele, fz_melt2ele)            
            do i = istart, iend
               !$acc loop private(dx, dy, dz, drnorm2, deltai, deltaj, epsilonix, epsiloniy, epsiloniz, &
               !$acc         epsilonjx, epsilonjy, epsilonjz, ft_ij(:)) &
               !$acc reduction(+: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             fx_melt2ele, fy_melt2ele, fz_melt2ele)            
               do j = jstart, jend
                  call minimum_image_displacement_@PBC@(a, b, c, &
                        xyz_ions(i,1), xyz_ions(i,2), xyz_ions(i,3), &
                        xyz_atoms(j,1), xyz_atoms(j,2), xyz_atoms(j,3), &
                        dx, dy, dz, drnorm2)
                  if (drnorm2 < daim%rcutsq) then
                     deltai=delta(i)
                     epsilonix=epsilon(i,1)
                     epsiloniy=epsilon(i,2)
                     epsiloniz=epsilon(i,3)
                     ft_ij = force_ij(dx,dy,dz,drnorm2,deltai, 0.0_wp, &
                        epsilonix,epsiloniy,epsiloniz,0.0_wp,0.0_wp, 0.0_wp, &
                        eta1_ij, eta2_ij, eta3_ij, B1_ij, B2_ij, B3_ij, &
                        C_ij, D_ij, damp_dd_ij, damp_dq_ij)

                     !$acc atomic update                        
                     force(i,1) = force(i,1) +  ft_ij(1)
                     !$acc atomic update                        
                     force(i,2) = force(i,2) +  ft_ij(2)
                     !$acc atomic update                        
                     force(i,3) = force(i,3) +  ft_ij(3)

                     ! Is this meaningful?
                     loc_stress_tensor_xx = loc_stress_tensor_xx - dx * ft_ij(1)
                     loc_stress_tensor_yy = loc_stress_tensor_yy - dy * ft_ij(2)
                     loc_stress_tensor_zz = loc_stress_tensor_zz - dz * ft_ij(3)
                     loc_stress_tensor_xy = loc_stress_tensor_xy - dx * ft_ij(2)
                     loc_stress_tensor_xz = loc_stress_tensor_xz - dx * ft_ij(3)
                     loc_stress_tensor_yz = loc_stress_tensor_yz - dy * ft_ij(3)

                     fx_melt2ele = fx_melt2ele - ft_ij(1)
                     fy_melt2ele = fy_melt2ele - ft_ij(2)
                     fz_melt2ele = fz_melt2ele - ft_ij(3)
                  end if
               end do
               !$acc end loop
            end do
            !$acc end parallel loop
         end do
         electrodes(jtype)%force_ions(1,10) = electrodes(jtype)%force_ions(1,10) + fx_melt2ele
         electrodes(jtype)%force_ions(2,10) = electrodes(jtype)%force_ions(2,10) + fy_melt2ele
         electrodes(jtype)%force_ions(3,10) = electrodes(jtype)%force_ions(3,10) + fz_melt2ele
      end do
   end do
   !$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   
   call MW_timers_stop(TIMER_VAN_DER_WAALS_MELT_FORCES)
end subroutine melt_forces_@PBC@

! ==============================================================================
! Compute daim energy
subroutine energy_@PBC@(localwork, daim, box, ions, xyz_ions, &
      electrodes, xyz_atoms, delta,epsilon,h)
   implicit none

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

   type(MW_ion_t), intent(in) :: ions(:)        !< ions parameters
   real(wp),       intent(in) :: xyz_ions(:,:)  !< ions xyz positions

   type(MW_electrode_t), intent(in) :: electrodes(:)  !< electrode parameters
   real(wp),             intent(in) :: xyz_atoms(:,:)  !< electrode atoms xyz positions
   real(wp),             intent(in) :: delta(:)  !<  Deltas of ions
   real(wp),             intent(in) :: epsilon(:,:)  !< Epsilons of ions

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

   ! Locals
   ! ------
   integer :: num_ion_types, num_elec
   integer :: itype, jtype, i, j
   real(wp) :: a, b, c
   real(wp) :: drnorm2, dx, dy, dz
   real(wp) :: ft_ij
   real(wp) :: deltai,deltaj
   real(wp) :: epsilonix,epsiloniy,epsiloniz
   real(wp) :: epsilonjx,epsilonjy,epsilonjz
   real(wp) :: eta1_ij, B1_ij
   real(wp) :: eta2_ij, B2_ij
   real(wp) :: eta3_ij, B3_ij
   real(wp) :: C_ij, D_ij, damp_dd_ij, damp_dq_ij
   real(wp) :: vi
   integer :: num_block_diag, num_block_full
   integer :: iblock, iblock_offset, istart, iend, jstart, jend
   integer :: count_n, offset_n, count_m, offset_m


   call MW_timers_start(TIMER_VAN_DER_WAALS_MELT_POTENTIAL)
   num_ion_types = size(ions,1)
   num_elec = size(electrodes,1)
   
   a = box%length(1)
   b = box%length(2)
   c = box%length(3)

   h = 0.0_wp
   vi = 0.0_wp

   !$acc data present(xyz_ions(:,:), xyz_atoms(:,:), delta(:), epsilon(:,:)) copy(vi)

   ! Blocks on the diagonal compute only half of the pair interactions
   do itype = 1, num_ion_types
      count_n = ions(itype)%count
      offset_n = ions(itype)%offset
      do jtype = 1, itype - 1
         count_m = ions(jtype)%count
         offset_m = ions(jtype)%offset
         eta1_ij = daim%eta1(itype, jtype)
         eta2_ij = daim%eta2(itype, jtype)
         eta3_ij = daim%eta3(itype, jtype)
         B1_ij = daim%B1(itype, jtype)
         B2_ij = daim%B2(itype, jtype)
         B3_ij = daim%B3(itype, jtype)
         C_ij = daim%C(itype, jtype)
         D_ij = daim%D(itype, jtype)
         damp_dd_ij = daim%damp_dd(itype, jtype)
         damp_dq_ij = daim%damp_dq(itype, jtype)
         ! Number of blocks with full ion2ion interactions
         num_block_full = localwork%pair_ion2ion_num_block_full_local(itype, jtype)
         iblock_offset = localwork%pair_ion2ion_full_iblock_offset(itype, jtype)
         do iblock = 1, num_block_full
            call update_other_block_boundaries(iblock_offset+iblock, &
                  offset_n, count_n, offset_m, count_m, &
                  istart, iend, jstart, jend)

            !$acc parallel loop collapse(2) reduction(+:vi) &
            !$acc private(dx, dy, dz, drnorm2, deltai, deltaj, epsilonix, epsiloniy, epsiloniz, &
            !$acc              epsilonjx, epsilonjy, epsilonjz, ft_ij)
            do i = istart, iend
               do j = jstart, jend
                  call minimum_image_displacement_@PBC@(a, b, c, &
                        xyz_ions(i,1), xyz_ions(i,2), xyz_ions(i,3), &
                        xyz_ions(j,1), xyz_ions(j,2), xyz_ions(j,3), &
                        dx, dy, dz, drnorm2)
                  if (drnorm2 < daim%rcutsq) then
                     deltai=delta(i)
                     deltaj=delta(j)
                     epsilonix=epsilon(i,1)
                     epsiloniy=epsilon(i,2)
                     epsiloniz=epsilon(i,3)
                     epsilonjx=epsilon(j,1)
                     epsilonjy=epsilon(j,2)
                     epsilonjz=epsilon(j,3)
                     ft_ij = potential_ij(dx,dy,dz,drnorm2,deltai, deltaj, &
                        epsilonix,epsiloniy,epsiloniz,epsilonjx,epsilonjy,epsilonjz, &
                        eta1_ij, eta2_ij, eta3_ij, B1_ij, B2_ij, B3_ij, &
                        C_ij, D_ij, damp_dd_ij, damp_dq_ij)

                     vi=vi+ft_ij

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

      eta1_ij = daim%eta1(itype, itype)
      eta2_ij = daim%eta2(itype, itype)
      eta3_ij = daim%eta3(itype, itype)
      B1_ij = daim%B1(itype, itype)
      B2_ij = daim%B2(itype, itype)
      B3_ij = daim%B3(itype, itype)
      C_ij = daim%C(itype, itype)
      D_ij = daim%D(itype, itype)
      damp_dd_ij = daim%damp_dd(itype, itype)
      damp_dq_ij = daim%damp_dq(itype, itype)

      num_block_diag = localwork%pair_ion2ion_num_block_diag_local(itype)
      iblock_offset = localwork%pair_ion2ion_diag_iblock_offset(itype)
      do iblock = 1, num_block_diag
         call update_diag_block_boundaries(iblock_offset+iblock, &
               offset_n, count_n, istart, iend)
         !$acc parallel loop collapse(2) reduction(+:vi) &
         !$acc private(dx, dy, dz, drnorm2, deltai, deltaj, epsilonix, epsiloniy, epsiloniz, &
         !$acc              epsilonjx, epsilonjy, epsilonjz, ft_ij)
         do i = istart, iend
            do j = istart, iend
               call minimum_image_displacement_@PBC@(a, b, c, &
                     xyz_ions(i,1), xyz_ions(i,2), xyz_ions(i,3), &
                     xyz_ions(j,1), xyz_ions(j,2), xyz_ions(j,3), &
                     dx, dy, dz, drnorm2)
               if ((drnorm2 > 0.0_wp) .and. (drnorm2 < daim%rcutsq)) then
                  deltai=delta(i)
                  deltaj=delta(j)
                  epsilonix=epsilon(i,1)
                  epsiloniy=epsilon(i,2)
                  epsiloniz=epsilon(i,3)
                  epsilonjx=epsilon(j,1)
                  epsilonjy=epsilon(j,2)
                  epsilonjz=epsilon(j,3)
                  ft_ij = potential_ij(dx,dy,dz,drnorm2,deltai, deltaj, &
                     epsilonix,epsiloniy,epsiloniz,epsilonjx,epsilonjy,epsilonjz, &
                     eta1_ij, eta2_ij, eta3_ij, B1_ij, B2_ij, B3_ij, &
                     C_ij, D_ij, damp_dd_ij, damp_dq_ij)

                  vi=vi+0.5_wp*ft_ij
               end if
            end do
         end do
         !$acc end parallel loop            
      end do

      ! Number of blocks with full ion2ion interactions
      num_block_full = localwork%pair_ion2ion_num_block_full_local(itype,itype)
      iblock_offset = localwork%pair_ion2ion_full_iblock_offset(itype,itype)
      do iblock = 1, num_block_full
         call update_tri_block_boundaries(iblock_offset+iblock, offset_n, count_n, &
               istart, iend, jstart, jend)
         !$acc parallel loop collapse(2) reduction(+:vi) &
         !$acc private(dx, dy, dz, drnorm2, deltai, deltaj, epsilonix, epsiloniy, epsiloniz, &
         !$acc              epsilonjx, epsilonjy, epsilonjz, ft_ij)
         do i = istart, iend
            do j = jstart, jend
               call minimum_image_displacement_@PBC@(a, b, c, &
                     xyz_ions(i,1), xyz_ions(i,2), xyz_ions(i,3), &
                     xyz_ions(j,1), xyz_ions(j,2), xyz_ions(j,3), &
                     dx, dy, dz, drnorm2)
               if (drnorm2 < daim%rcutsq) then
                  deltai=delta(i)
                  deltaj=delta(j)
                  epsilonix=epsilon(i,1)
                  epsiloniy=epsilon(i,2)
                  epsiloniz=epsilon(i,3)
                  epsilonjx=epsilon(j,1)
                  epsilonjy=epsilon(j,2)
                  epsilonjz=epsilon(j,3)
                  ft_ij = potential_ij(dx,dy,dz,drnorm2,deltai, deltaj, &
                     epsilonix,epsiloniy,epsiloniz,epsilonjx,epsilonjy,epsilonjz, &
                     eta1_ij, eta2_ij, eta3_ij, B1_ij, B2_ij, B3_ij, &
                     C_ij, D_ij, damp_dd_ij, damp_dq_ij)
                  
                  vi=vi+ft_ij
               end if
            end do
         end do
         !$acc end parallel loop            
      end do

      do jtype = 1, num_elec
         count_m = electrodes(jtype)%count
         offset_m = electrodes(jtype)%offset

         eta1_ij = daim%eta1(itype, jtype+num_ion_types)
         eta2_ij = daim%eta2(itype, jtype+num_ion_types)
         eta3_ij = daim%eta3(itype, jtype+num_ion_types)
         B1_ij = daim%B1(itype, jtype+num_ion_types)
         B2_ij = daim%B2(itype, jtype+num_ion_types)
         B3_ij = daim%B3(itype, jtype+num_ion_types)
         C_ij = daim%C(itype, jtype+num_ion_types)
         D_ij = daim%D(itype, jtype+num_ion_types)
         damp_dd_ij = daim%damp_dd(itype, jtype+num_ion_types)
         damp_dq_ij = daim%damp_dq(itype, jtype+num_ion_types)

         ! Number of blocks with full atom2ions interactions
         num_block_full = localwork%pair_atom2ion_num_block_full_local(itype, jtype)
         iblock_offset = localwork%pair_atom2ion_full_iblock_offset(itype, jtype)
         do iblock = 1, num_block_full
            call update_other_block_boundaries(iblock_offset+iblock, &
                  offset_n, count_n, offset_m, count_m, &
                  istart, iend, jstart, jend)

            !$acc parallel loop collapse(2) reduction(+:vi) &
            !$acc private(dx, dy, dz, drnorm2, deltai, deltaj, epsilonix, epsiloniy, epsiloniz, &
            !$acc              epsilonjx, epsilonjy, epsilonjz, ft_ij)
            do i = istart, iend
               do j = jstart, jend
                  call minimum_image_displacement_@PBC@(a, b, c, &
                        xyz_ions(i,1), xyz_ions(i,2), xyz_ions(i,3), &
                        xyz_atoms(j,1), xyz_atoms(j,2), xyz_atoms(j,3), &
                        dx, dy, dz, drnorm2)
                  if (drnorm2 < daim%rcutsq) then
                     deltai=delta(i)
                     epsilonix=epsilon(i,1)
                     epsiloniy=epsilon(i,2)
                     epsiloniz=epsilon(i,3)
                     ft_ij = potential_ij(dx,dy,dz,drnorm2,deltai, 0.0_wp, &
                        epsilonix,epsiloniy,epsiloniz,0.0_wp,0.0_wp, 0.0_wp, &
                        eta1_ij, eta2_ij, eta3_ij, B1_ij, B2_ij, B3_ij, &
                        C_ij, D_ij, damp_dd_ij, damp_dq_ij)
                     vi=vi+ft_ij
                  end if
               end do
            end do
            !$acc end parallel loop            
         end do
      end do
   end do
   !$acc end data
   h = vi
   call MW_timers_stop(TIMER_VAN_DER_WAALS_MELT_POTENTIAL)
end subroutine energy_@PBC@

! ==============================================================================
! Compute daim potential felt by melt ions
subroutine repulsionenergy_@PBC@(localwork, daim, box, ions, xyz_ions, &
      electrodes, xyz_atoms,delta,epsilon, h)
   implicit none

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

   type(MW_ion_t), intent(in) :: ions(:)        !< ions parameters
   real(wp),       intent(in) :: xyz_ions(:,:)  !< ions xyz positions
   real(wp),             intent(in) :: delta(:)  !<  Deltas of ions
   real(wp),             intent(in) :: epsilon(:,:)  !< Epsilons of ions

   type(MW_electrode_t), intent(in) :: electrodes(:)  !< electrode parameters
   real(wp),             intent(in) :: xyz_atoms(:,:)  !< electrode atoms xyz positions

   ! Parameters out
   ! --------------
   real(wp), intent(inout) :: h       !< Potential energy due to L-J interactions

   ! Locals
   ! ------
   integer :: num_ion_types, num_elec
   integer :: itype, jtype, i, j
   real(wp) :: a, b, c
   real(wp) :: dx, dy,dz 
   real(wp) :: drnorm2, rcutsq
   real(wp) :: vi
   integer :: iblock, iblock_offset, istart, iend, jstart, jend
   integer :: num_block_diag, num_block_full
   integer :: count_n, offset_n, count_m, offset_m
   real(wp) :: ft_ij
   real(wp) :: deltai,deltaj
   real(wp) :: epsilonix,epsiloniy,epsiloniz
   real(wp) :: epsilonjx,epsilonjy,epsilonjz
   real(wp) :: eta2_ij, B2_ij
   real(wp) :: eta3_ij, B3_ij
   real(wp) :: deformabilityi,deformabilityj



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

   a = box%length(1)
   b = box%length(2)
   c = box%length(3)

   rcutsq = daim%rcutsq
   h = 0.0_wp
   vi = 0.0_wp

   !$acc data present(xyz_ions(:,:), xyz_atoms(:,:), delta(:), epsilon(:,:)) copy(vi)   

   ! Blocks on the diagonal compute only half of the pair interactions
   do itype = 1, num_ion_types
      count_n = ions(itype)%count
      offset_n = ions(itype)%offset
      deformabilityi=0.0_wp
      if(ions(itype)%selfdaimD>0.0_wp)then
         deformabilityi=1.0_wp
      endif
      do jtype = 1, itype - 1
         count_m = ions(jtype)%count
         offset_m = ions(jtype)%offset
         eta2_ij = daim%eta2(itype, jtype)
         eta3_ij = daim%eta3(itype, jtype)
         B2_ij = daim%B2(itype, jtype)
         B3_ij = daim%B3(itype, jtype)
         deformabilityj=0.0_wp
         if(ions(jtype)%selfdaimD>0.0_wp)then
            deformabilityj=1.0_wp
         endif
         if((deformabilityi.eq.0.0_wp).and.(deformabilityj.eq.0.0_wp)) cycle 
         ! Number of blocks with full ion2ion interactions
         num_block_full = localwork%pair_ion2ion_num_block_full_local(itype, jtype)
         iblock_offset = localwork%pair_ion2ion_full_iblock_offset(itype, jtype)

         do iblock = 1, num_block_full
            call update_other_block_boundaries(iblock+iblock_offset, &
                  offset_n, count_n, offset_m, count_m, &
                  istart, iend, jstart, jend)
            !$acc parallel loop collapse(2) reduction(+:vi) &
            !$acc private(dx, dy, dz, drnorm2, deltai, deltaj, epsilonix, epsiloniy, epsiloniz, &
            !$acc              epsilonjx, epsilonjy, epsilonjz, ft_ij)
            do i = istart, iend
               do j = jstart, jend
                  call minimum_image_displacement_@PBC@(a, b, c, &
                        xyz_ions(i,1), xyz_ions(i,2), xyz_ions(i,3), &
                        xyz_ions(j,1), xyz_ions(j,2), xyz_ions(j,3), &
                        dx, dy, dz, drnorm2)
                  if (drnorm2 < rcutsq) then
                     deltai=delta(i)
                     deltaj=delta(j)
                     epsilonix=epsilon(i,1)
                     epsiloniy=epsilon(i,2)
                     epsiloniz=epsilon(i,3)
                     epsilonjx=epsilon(j,1)
                     epsilonjy=epsilon(j,2)
                     epsilonjz=epsilon(j,3)
                     ft_ij = reppotential_ij(dx,dy,dz,drnorm2,deltai, deltaj, &
                        epsilonix,epsiloniy,epsiloniz,epsilonjx,epsilonjy,epsilonjz, &
                         eta2_ij, eta3_ij,  B2_ij, B3_ij)
                     vi = vi + ft_ij
                  end if
               end do
            end do
            !$acc end parallel loop
         end do
      end do

      eta2_ij = daim%eta2(itype, itype)
      eta3_ij = daim%eta3(itype, itype)
      B2_ij = daim%B2(itype, itype)
      B3_ij = daim%B3(itype, itype)
      
      if(deformabilityi.eq.0.0_wp) cycle 

      num_block_diag = localwork%pair_ion2ion_num_block_diag_local(itype)
      iblock_offset = localwork%pair_ion2ion_diag_iblock_offset(itype)
      do iblock = 1, num_block_diag
         call update_diag_block_boundaries(iblock_offset+iblock, offset_n, count_n, istart, iend)
         !$acc parallel loop collapse(2) reduction(+:vi) &
         !$acc private(dx, dy, dz, drnorm2, deltai, deltaj, epsilonix, epsiloniy, epsiloniz, &
         !$acc              epsilonjx, epsilonjy, epsilonjz, ft_ij)
         do i = istart, iend
            do j = istart, iend
               call minimum_image_displacement_@PBC@(a, b, c, &
                     xyz_ions(i,1), xyz_ions(i,2), xyz_ions(i,3), &
                     xyz_ions(j,1), xyz_ions(j,2), xyz_ions(j,3), &
                     dx, dy, dz, drnorm2)
               if ((drnorm2 > 0.0_wp) .and. (drnorm2 < rcutsq)) then
                  deltai=delta(i)
                  deltaj=delta(j)
                  epsilonix=epsilon(i,1)
                  epsiloniy=epsilon(i,2)
                  epsiloniz=epsilon(i,3)
                  epsilonjx=epsilon(j,1)
                  epsilonjy=epsilon(j,2)
                  epsilonjz=epsilon(j,3)
                  ft_ij = reppotential_ij(dx,dy,dz,drnorm2,deltai, deltaj, &
                        epsilonix,epsiloniy,epsiloniz,epsilonjx,epsilonjy,epsilonjz, &
                        eta2_ij, eta3_ij,  B2_ij, B3_ij)
                  vi = vi + 0.5_wp * ft_ij
               end if
            end do
         end do
         !$acc end parallel loop
      end do

      ! Number of blocks with full ion2ion interactions
      num_block_full = localwork%pair_ion2ion_num_block_full_local(itype,itype)
      iblock_offset = localwork%pair_ion2ion_full_iblock_offset(itype,itype)
      do iblock = 1, num_block_full
         call update_tri_block_boundaries(iblock_offset+iblock, offset_n, count_n, &
               istart, iend, jstart, jend)
         !$acc parallel loop collapse(2) reduction(+:vi) &
         !$acc private(dx, dy, dz, drnorm2, deltai, deltaj, epsilonix, epsiloniy, epsiloniz, &
         !$acc              epsilonjx, epsilonjy, epsilonjz, ft_ij)
         do i = istart, iend
            do j = jstart, jend
               call minimum_image_displacement_@PBC@(a, b, c, &
                     xyz_ions(i,1), xyz_ions(i,2), xyz_ions(i,3), &
                     xyz_ions(j,1), xyz_ions(j,2), xyz_ions(j,3), &
                     dx, dy, dz, drnorm2)
               if (drnorm2 < rcutsq) then
                  deltai=delta(i)
                  deltaj=delta(j)
                  epsilonix=epsilon(i,1)
                  epsiloniy=epsilon(i,2)
                  epsiloniz=epsilon(i,3)
                  epsilonjx=epsilon(j,1)
                  epsilonjy=epsilon(j,2)
                  epsilonjz=epsilon(j,3)
                  ft_ij = reppotential_ij(dx,dy,dz,drnorm2,deltai, deltaj, &
                        epsilonix,epsiloniy,epsiloniz,epsilonjx,epsilonjy,epsilonjz, &
                        eta2_ij, eta3_ij,  B2_ij, B3_ij)
                  vi = vi + ft_ij  
               end if
            end do
         end do
         !$acc end parallel loop
      end do

      do jtype = 1, num_elec
         count_m = electrodes(jtype)%count
         offset_m = electrodes(jtype)%offset

         eta2_ij = daim%eta2(itype, jtype+num_ion_types)
         eta3_ij = daim%eta3(itype, jtype+num_ion_types)
         B2_ij = daim%B2(itype, jtype+num_ion_types)
         B3_ij = daim%B3(itype, jtype+num_ion_types)

         ! Number of blocks with full ion2ion interactions
         num_block_full = localwork%pair_atom2ion_num_block_full_local(itype, jtype)
         iblock_offset = localwork%pair_atom2ion_full_iblock_offset(itype, jtype)

         do iblock = 1, num_block_full
            call update_other_block_boundaries(iblock+iblock_offset, &
                  offset_n, count_n, offset_m, count_m, &
                  istart, iend, jstart, jend)
            !$acc parallel loop collapse(2) reduction(+:vi) &
            !$acc private(dx, dy, dz, drnorm2, deltai, deltaj, epsilonix, epsiloniy, epsiloniz, &
            !$acc              epsilonjx, epsilonjy, epsilonjz, ft_ij)
            do i = istart, iend
               do j = jstart, jend
                  call minimum_image_displacement_@PBC@(a, b, c, &
                        xyz_ions(i,1), xyz_ions(i,2), xyz_ions(i,3), &
                        xyz_atoms(j,1), xyz_atoms(j,2), xyz_atoms(j,3), &
                        dx, dy, dz, drnorm2)
                  if (drnorm2 < rcutsq) then
                     deltai=delta(i)
                     epsilonix=epsilon(i,1)
                     epsiloniy=epsilon(i,2)
                     epsiloniz=epsilon(i,3)
                     ft_ij = reppotential_ij(dx,dy,dz,drnorm2,deltai, 0.0_wp, &
                           epsilonix,epsiloniy,epsiloniz,0.0_wp,0.0_wp, 0.0_wp, &
                           eta2_ij, eta3_ij,  B2_ij, B3_ij)
                     vi = vi + ft_ij
                  end if
               end do
            end do
            !$acc end parallel loop
         end do
      end do
   end do
  !$acc end data   
   h = vi
end subroutine repulsionenergy_@PBC@


! ==============================================================================
! Compute daim potential felt by melt ions
subroutine diffrepulsionenergy_@PBC@(localwork, daim, box, ions, xyz_ions, &
      electrodes, xyz_atoms,delta,epsilon, h,xi)
   implicit none

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

   type(MW_ion_t), intent(in) :: ions(:)        !< ions parameters
   real(wp),       intent(in) :: xyz_ions(:,:)  !< ions xyz positions
   real(wp),             intent(in) :: delta(:)  !<  Deltas of ions
   real(wp),             intent(in) :: epsilon(:,:)  !< Epsilons of ions

   type(MW_electrode_t), intent(in) :: electrodes(:)  !< electrode parameters
   real(wp),             intent(in) :: xyz_atoms(:,:)  !< electrode atoms xyz positions

   ! Parameters out
   ! --------------
   real(wp), intent(inout) :: h       !< Potential energy due to L-J interactions
   real(wp), intent(inout) :: xi(:)       !< Derivative of the energy w.r.t. the d.o.f.

   ! Locals
   ! ------
   integer :: num_ion_types, num_elec,num
   integer :: itype, jtype, i, j
   real(wp) :: a, b, c
   real(wp) :: dx, dy,dz 
   real(wp) :: drnorm2, rcutsq
   real(wp) :: vi
   integer :: iblock, iblock_offset, istart, iend, jstart, jend
   integer :: num_block_diag, num_block_full
   integer :: count_n, offset_n, count_m, offset_m
   real(wp), dimension(5) :: ft_ij
   real(wp) :: deltai,deltaj
   real(wp) :: epsilonix,epsiloniy,epsiloniz
   real(wp) :: epsilonjx,epsilonjy,epsilonjz
   real(wp) :: eta2_ij, B2_ij
   real(wp) :: eta3_ij, B3_ij
   real(wp) :: deformabilityi,deformabilityj


   num_ion_types = size(ions,1)
   num_elec = size(electrodes,1)
   num=size(xi,1)/4

   a = box%length(1)
   b = box%length(2)
   c = box%length(3)

   rcutsq = daim%rcutsq
   h = 0.0_wp
   vi = 0.0_wp

   !$acc data present(xyz_ions(:,:), xyz_atoms(:,:), delta(:), epsilon(:,:),xi(:)) copy(vi)

   ! Blocks on the diagonal compute only half of the pair interactions
   do itype = 1, num_ion_types
      count_n = ions(itype)%count
      offset_n = ions(itype)%offset
      deformabilityi=0.0_wp
      if(ions(itype)%selfdaimD>0.0_wp)then
         deformabilityi=1.0_wp
      endif
      do jtype = 1, itype - 1
         count_m = ions(jtype)%count
         offset_m = ions(jtype)%offset
         deformabilityj=0.0_wp
         if(ions(jtype)%selfdaimD>0.0_wp)then
            deformabilityj=1.0_wp
         endif
         if((deformabilityi.eq.0.0_wp).and.(deformabilityj.eq.0.0_wp)) cycle 
         eta2_ij = daim%eta2(itype, jtype)
         eta3_ij = daim%eta3(itype, jtype)
         B2_ij = daim%B2(itype, jtype)
         B3_ij = daim%B3(itype, jtype)
         ! Number of blocks with full ion2ion interactions
         num_block_full = localwork%pair_ion2ion_num_block_full_local(itype, jtype)
         iblock_offset = localwork%pair_ion2ion_full_iblock_offset(itype, jtype)

         do iblock = 1, num_block_full
            call update_other_block_boundaries(iblock+iblock_offset, &
                  offset_n, count_n, offset_m, count_m, &
                  istart, iend, jstart, jend)
            !$acc parallel loop collapse(2) reduction(+:vi) &
            !$acc private(dx, dy, dz, drnorm2, deltai, deltaj, epsilonix, epsiloniy, epsiloniz, &
            !$acc           epsilonjx, epsilonjy, epsilonjz, ft_ij(:))
            do i = istart, iend
               do j = jstart, jend
                  call minimum_image_displacement_@PBC@(a, b, c, &
                        xyz_ions(i,1), xyz_ions(i,2), xyz_ions(i,3), &
                        xyz_ions(j,1), xyz_ions(j,2), xyz_ions(j,3), &
                        dx, dy, dz, drnorm2)
                  if (drnorm2 < rcutsq) then
                     deltai=delta(i)
                     deltaj=delta(j)
                     epsilonix=epsilon(i,1)
                     epsiloniy=epsilon(i,2)
                     epsiloniz=epsilon(i,3)
                     epsilonjx=epsilon(j,1)
                     epsilonjy=epsilon(j,2)
                     epsilonjz=epsilon(j,3)
                     ft_ij = diffreppotential_ij(dx,dy,dz,drnorm2,deltai, deltaj, &
                           epsilonix,epsiloniy,epsiloniz,epsilonjx,epsilonjy,epsilonjz, &
                           eta2_ij, eta3_ij, B2_ij, B3_ij)

                     !$acc atomic update 
                     xi(i)       = xi(i)      +ft_ij(1)*deformabilityi
                     !$acc atomic update 
                     xi(num+i)   = xi(num+i)  +ft_ij(2)*deformabilityi
                     !$acc atomic update 
                     xi(2*num+i) = xi(2*num+i)+ft_ij(3)*deformabilityi
                     !$acc atomic update 
                     xi(3*num+i) = xi(3*num+i)+ft_ij(4)*deformabilityi
                     !$acc atomic update 
                     xi(j)       = xi(j)      +ft_ij(1)*deformabilityj
                     !$acc atomic update 
                     xi(num+j)   = xi(num+j)  +ft_ij(2)*deformabilityj
                     !$acc atomic update 
                     xi(2*num+j) = xi(2*num+j)+ft_ij(3)*deformabilityj
                     !$acc atomic update 
                     xi(3*num+j) = xi(3*num+j)+ft_ij(4)*deformabilityj

                     vi = vi + ft_ij(5)
                  end if
               end do
            end do
            !$acc end parallel loop
         end do
      end do

      if(deformabilityi.eq.0.0_wp) cycle 

      eta2_ij = daim%eta2(itype, itype)
      eta3_ij = daim%eta3(itype, itype)
      B2_ij = daim%B2(itype, itype)
      B3_ij = daim%B3(itype, itype)

      num_block_diag = localwork%pair_ion2ion_num_block_diag_local(itype)
      iblock_offset = localwork%pair_ion2ion_diag_iblock_offset(itype)
      do iblock = 1, num_block_diag
         call update_diag_block_boundaries(iblock_offset+iblock, offset_n, count_n, istart, iend)
         !$acc parallel loop collapse(2) reduction(+:vi) &
         !$acc private(dx, dy, dz, drnorm2, deltai, deltaj, epsilonix, epsiloniy, epsiloniz, &
         !$acc           epsilonjx, epsilonjy, epsilonjz, ft_ij(:))
         do i = istart, iend
            do j = istart, iend
               call minimum_image_displacement_@PBC@(a, b, c, &
                     xyz_ions(i,1), xyz_ions(i,2), xyz_ions(i,3), &
                     xyz_ions(j,1), xyz_ions(j,2), xyz_ions(j,3), &
                     dx, dy, dz, drnorm2)
               if ((drnorm2 > 0.0_wp) .and. (drnorm2 < rcutsq)) then
                  deltai=delta(i)
                  deltaj=delta(j)
                  epsilonix=epsilon(i,1)
                  epsiloniy=epsilon(i,2)
                  epsiloniz=epsilon(i,3)
                  epsilonjx=epsilon(j,1)
                  epsilonjy=epsilon(j,2)
                  epsilonjz=epsilon(j,3)
                  ft_ij = diffreppotential_ij(dx,dy,dz,drnorm2,deltai, deltaj, &
                        epsilonix,epsiloniy,epsiloniz,epsilonjx,epsilonjy,epsilonjz, &
                        eta2_ij, eta3_ij,  B2_ij, B3_ij)

                  !$acc atomic update 
                  xi(i)       = xi(i)      +ft_ij(1)
                  !$acc atomic update 
                  xi(num+i)   = xi(num+i)  +ft_ij(2)
                  !$acc atomic update 
                  xi(2*num+i) = xi(2*num+i)+ft_ij(3)
                  !$acc atomic update 
                  xi(3*num+i) = xi(3*num+i)+ft_ij(4)

                  vi = vi + 0.5_wp * ft_ij(5)
               end if
            end do
         end do
         !$acc end parallel loop
      end do

      ! Number of blocks with full ion2ion interactions
      num_block_full = localwork%pair_ion2ion_num_block_full_local(itype,itype)
      iblock_offset = localwork%pair_ion2ion_full_iblock_offset(itype,itype)
      do iblock = 1, num_block_full
         call update_tri_block_boundaries(iblock_offset+iblock, offset_n, count_n, &
               istart, iend, jstart, jend)
         !$acc parallel loop collapse(2) reduction(+:vi) &
         !$acc private(dx, dy, dz, drnorm2, deltai, deltaj, epsilonix, epsiloniy, epsiloniz, &
         !$acc           epsilonjx, epsilonjy, epsilonjz, ft_ij(:))
         do i = istart, iend
            do j = jstart, jend
               call minimum_image_displacement_@PBC@(a, b, c, &
                     xyz_ions(i,1), xyz_ions(i,2), xyz_ions(i,3), &
                     xyz_ions(j,1), xyz_ions(j,2), xyz_ions(j,3), &
                     dx, dy, dz, drnorm2)
               if (drnorm2 < rcutsq) then
                  deltai=delta(i)
                  deltaj=delta(j)
                  epsilonix=epsilon(i,1)
                  epsiloniy=epsilon(i,2)
                  epsiloniz=epsilon(i,3)
                  epsilonjx=epsilon(j,1)
                  epsilonjy=epsilon(j,2)
                  epsilonjz=epsilon(j,3)
                  ft_ij = diffreppotential_ij(dx,dy,dz,drnorm2,deltai, deltaj, &
                        epsilonix,epsiloniy,epsiloniz,epsilonjx,epsilonjy,epsilonjz, &
                        eta2_ij, eta3_ij,  B2_ij, B3_ij)

                  !$acc atomic update 
                  xi(i)       = xi(i)      +ft_ij(1)
                  !$acc atomic update 
                  xi(num+i)   = xi(num+i)  +ft_ij(2)
                  !$acc atomic update 
                  xi(2*num+i) = xi(2*num+i)+ft_ij(3)
                  !$acc atomic update 
                  xi(3*num+i) = xi(3*num+i)+ft_ij(4)
                  !$acc atomic update 
                  xi(j)       = xi(j)      +ft_ij(1)
                  !$acc atomic update 
                  xi(num+j)   = xi(num+j)  +ft_ij(2)
                  !$acc atomic update 
                  xi(2*num+j) = xi(2*num+j)+ft_ij(3)
                  !$acc atomic update 
                  xi(3*num+j) = xi(3*num+j)+ft_ij(4)

                  vi = vi + ft_ij(5)
               end if
            end do
         end do
         !$acc end parallel loop
      end do

      do jtype = 1, num_elec
         count_m = electrodes(jtype)%count
         offset_m = electrodes(jtype)%offset

         eta2_ij = daim%eta2(itype, jtype+num_ion_types)
         eta3_ij = daim%eta3(itype, jtype+num_ion_types)
         B2_ij = daim%B2(itype, jtype+num_ion_types)
         B3_ij = daim%B3(itype, jtype+num_ion_types)

         ! Number of blocks with full ion2ion interactions
         num_block_full = localwork%pair_atom2ion_num_block_full_local(itype, jtype)
         iblock_offset = localwork%pair_atom2ion_full_iblock_offset(itype, jtype)

         do iblock = 1, num_block_full
            call update_other_block_boundaries(iblock+iblock_offset, &
                  offset_n, count_n, offset_m, count_m, &
                  istart, iend, jstart, jend)
            !$acc parallel loop collapse(2) reduction(+:vi) &
            !$acc private(dx, dy, dz, drnorm2, deltai, deltaj, epsilonix, epsiloniy, epsiloniz, &
            !$acc           epsilonjx, epsilonjy, epsilonjz, ft_ij(:))
            do i = istart, iend
               do j = jstart, jend
                  call minimum_image_displacement_@PBC@(a, b, c, &
                        xyz_ions(i,1), xyz_ions(i,2), xyz_ions(i,3), &
                        xyz_atoms(j,1), xyz_atoms(j,2), xyz_atoms(j,3), &
                        dx, dy, dz, drnorm2)
                  if (drnorm2 < rcutsq) then
                     deltai=delta(i)
                     epsilonix=epsilon(i,1)
                     epsiloniy=epsilon(i,2)
                     epsiloniz=epsilon(i,3)
                     ft_ij = diffreppotential_ij(dx,dy,dz,drnorm2,deltai, 0.0_wp, &
                           epsilonix,epsiloniy,epsiloniz,0.0_wp,0.0_wp, 0.0_wp, &
                           eta2_ij, eta3_ij,  B2_ij, B3_ij)

                     !$acc atomic update 
                     xi(i)       = xi(i)      +ft_ij(1)
                     !$acc atomic update 
                     xi(num+i)   = xi(num+i)  +ft_ij(2)
                     !$acc atomic update 
                     xi(2*num+i) = xi(2*num+i)+ft_ij(3)
                     !$acc atomic update 
                     xi(3*num+i) = xi(3*num+i)+ft_ij(4)

                     vi = vi + ft_ij(5)
                  end if
               end do
            end do
            !$acc end parallel loop
         end do
      end do
   end do
   !$acc end data   
   h = vi
end subroutine diffrepulsionenergy_@PBC@

