! Module to compute short range electrostatic potential
module MW_coulomb_sr_pim
   use MW_kinds, only: wp
   use MW_errors, only: MW_errors_allocate_error => allocate_error
   use MW_ewald, only: MW_ewald_t
   use MW_box, only: MW_box_t
   use MW_damping, only: MW_damping_t
   use MW_electrode, only: MW_electrode_t
   use MW_ion, only: MW_ion_t
   use MW_multipole_tensors, only: MW_multipole_tensors_tij_ab => tij_ab, &
                                   MW_multipole_tensors_tij_abc => tij_abc
   use MW_localwork, only: MW_localwork_t
   use MW_constants, only: sqrtpi
   implicit none
   private

   ! Public subroutines
   ! ------------------
   public :: gradQelec_electricfield !grad_Q [grad_mu [U^sr_muQ]]
   public :: gradmumelt_electricfield !grad_mu [grad_mu [U^sr_mumu]]
   public :: mumelt2Qelec_potential !grad_Q [U^sr_muQ]
   public :: qmelt2mumelt_electricfield !-grad_mu [U^sr_qmu]
   public :: mumelt2mumelt_electricfield !-grad_mu [U^sr_mumu]
   public :: Qelec2mumelt_electricfield !-grad_mu [U^sr_muQ]
   public :: melt_efg !-grad_r grad_r [(U^sr_qq) + (U^sr_qmu) + (U^sr_mumu)] 
   public :: melt_forces !-grad_r [(U^sr_qq + U^sr_qmu + U^sr_mumu) + (U^sr_QQ) + (U^sr_qQ + U^sr_muQ)]
   public :: energy !(U^sr_qq + U^sr_qmu + U^sr_mumu) + (U^sr_QQ) + (U^sr_qQ + U^sr_muQ)

contains

   subroutine gradQelec_electricfield(num_PBC, localwork, ewald, box, ions, xyz_ions, &
      electrodes, xyz_atoms, gradQ_efield)
      implicit none

      ! Parameters in
      ! -------------
      integer,              intent(in)    :: num_PBC !< number of periodic boundary conditions
      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
      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

      ! Parameters out
      ! --------------
      real(wp),             intent(inout) :: gradQ_efield(:,:) !< Coulomb force on ions

      select case (num_PBC)
      case(2)
         call gradQelec_electricfield_2DPBC(localwork, ewald, box, ions, xyz_ions, &
         electrodes, xyz_atoms, gradQ_efield)
      case(3)
         call gradQelec_electricfield_3DPBC(localwork, ewald, box, ions, xyz_ions, &
         electrodes, xyz_atoms, gradQ_efield)
      end select

   end subroutine gradQelec_electricfield

   !================================================================================
   ! Compute the gradient of the electric field for each ion in the melt with respect
   ! to variations of other dipoles in the melt
   subroutine gradmumelt_electricfield(num_PBC, localwork, ewald, box, ions, xyz_ions, &
      gradmu_efield)
      implicit none

      ! Parameters in
      ! -------------
      integer,               intent(in)    :: num_PBC !< number of periodic boundary conditions
      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
      real(wp),              intent(in)    :: xyz_ions(:,:)     !< ions xyz positions

      ! Parameters out
      ! --------------
      real(wp),              intent(inout) :: gradmu_efield(:,:) !< matrix containing the
      ! gradient of the field

      select case (num_PBC)
      case(2)
         call gradmumelt_electricfield_2DPBC(localwork, ewald, box, ions, xyz_ions, &
         gradmu_efield)
      case(3)
         call gradmumelt_electricfield_3DPBC(localwork, ewald, box, ions, xyz_ions, &
         gradmu_efield)
      end select
   end subroutine gradmumelt_electricfield

   !================================================================================
   ! Compute the Coulomb potential felt by each electrode atoms due to all melt ions
   subroutine mumelt2Qelec_potential(num_PBC, localwork, ewald, box, &
              ions, xyz_ions, electrodes, xyz_atoms, dipoles, type_electrode_atoms, V)
      implicit none

      ! Parameters in
      ! -------------
      integer,              intent(in)    :: num_PBC !< Number of periodic boundary conditions
      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
      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)    :: dipoles(:,:)
      integer,              intent(in)    :: type_electrode_atoms(:)

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

      select case (num_PBC)
      case(2)
         call mumelt2Qelec_potential_2DPBC(localwork, ewald, box, &
         ions, xyz_ions, electrodes, xyz_atoms, dipoles, type_electrode_atoms, V)
      case(3)
         call mumelt2Qelec_potential_3DPBC(localwork, ewald, box, &
         ions, xyz_ions, electrodes, xyz_atoms, dipoles, type_electrode_atoms, V)
      end select
   end subroutine mumelt2Qelec_potential

   !================================================================================
   ! Compute the electric fields felt by each melt ions due to other melt ion
   ! charges
   subroutine qmelt2mumelt_electricfield(num_PBC, localwork, ewald, box, ions, xyz_ions, &
                   type_ions, efield, tt)
      implicit none

      ! Parameters in
      ! -------------
      integer,              intent(in)    :: num_PBC !< number of periodic boundary conditions
      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
      real(wp),             intent(in)    :: xyz_ions(:,:)  !< ions xyz positions
      integer,              intent(in)    :: type_ions(:)
      type(MW_damping_t),   intent(in)    :: tt  ! Damping parameters

      ! Parameters out
      ! --------------
      real(wp),             intent(inout) :: efield(:,:) !< Coulomb force on ions

      select case (num_PBC)
      case(2)
         call qmelt2mumelt_electricfield_2DPBC(localwork, ewald, box, ions, xyz_ions, &
                 type_ions, efield, tt)
      case(3)
         call qmelt2mumelt_electricfield_3DPBC(localwork, ewald, box, ions, xyz_ions, &
                 type_ions, efield, tt)
      end select

   end subroutine qmelt2mumelt_electricfield

   !================================================================================
   ! Compute the electric fields felt by each melt ions due to other melt ions
   subroutine mumelt2mumelt_electricfield(num_PBC, localwork, ewald, box, ions, xyz_ions, &
         efield, dipoles)
      implicit none

      ! Parameters in
      ! -------------
      integer,              intent(in)    :: num_PBC !< number of periodic boundary conditions
      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
      real(wp),             intent(in)    :: xyz_ions(:,:)  !< ions xyz positions
      real(wp),             intent(in)    :: dipoles(:,:)      !< ions dipoles

      ! Parameters out
      ! --------------
      real(wp),             intent(inout) :: efield(:,:) !< Coulomb force on ions

      select case (num_PBC)
      case(2)
         call mumelt2mumelt_electricfield_2DPBC(localwork, ewald, box, ions, xyz_ions, &
            efield, dipoles)
      case(3)
         call mumelt2mumelt_electricfield_3DPBC(localwork, ewald, box, ions, xyz_ions, &
            efield, dipoles)
      end select
   end subroutine mumelt2mumelt_electricfield

   !================================================================================
   ! Compute the electric fields felt by each melt ions due to other melt ion
   ! charges
   subroutine Qelec2mumelt_electricfield(num_PBC, localwork, ewald, box, ions, xyz_ions, &
      electrodes, xyz_atoms, q_elec, type_electrode_atoms, efield)
      implicit none

      ! Parameters in
      ! -------------
      integer,              intent(in)    :: num_PBC !< number of periodic boundary conditions
      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
      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)    :: q_elec(:)      !< Electrode atoms charge
      integer,              intent(in)    :: type_electrode_atoms(:)

      ! Parameters out
      ! --------------
      real(wp),             intent(inout) :: efield(:,:) !< Coulomb force on ions

      select case (num_PBC)
      case(2)
         call Qelec2mumelt_electricfield_2DPBC(localwork, ewald, box, ions, xyz_ions, &
         electrodes, xyz_atoms, q_elec, type_electrode_atoms, efield)
      case(3)
         call Qelec2mumelt_electricfield_3DPBC(localwork, ewald, box, ions, xyz_ions, &
         electrodes, xyz_atoms, q_elec, type_electrode_atoms, efield)
      end select

   end subroutine Qelec2mumelt_electricfield

   !==============================================================================
   ! Compute the electric field gradient felt by melt ions due to point charges 
   ! and point dipoles of melt ions.
   subroutine melt_efg(num_PBC, localwork, ewald, box, ions, xyz_ions, dipoles, efg)
      implicit none

      ! Parameters in
      ! -------------
      integer,              intent(in)    :: num_PBC        !< number of periodic boundary conditions
      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
      real(wp),             intent(in)    :: xyz_ions(:,:)  !< ions xyz positions
      real(wp),             intent(in)    :: dipoles(:,:)   !< ions dipoles

      ! Parameters out
      ! --------------
      real(wp),             intent(inout) :: efg(:,:) !< the EFG on ions

      select case (num_PBC)
      case(2)
         call melt_efg_pim_2DPBC(localwork, ewald, box, ions, xyz_ions, dipoles, efg)
      case(3)
         call melt_efg_pim_3DPBC(localwork, ewald, box, ions, xyz_ions, dipoles, efg)
      end select

   end subroutine melt_efg

   !================================================================================
   ! Compute the Coulomb forces felt by each melt ions due to other melt ions
   subroutine melt_forces(num_PBC, localwork, ewald, box, ions, xyz_ions, type_ions, &
      electrodes, xyz_atoms, type_electrode_atoms, q_elec, force,stress_tensor, dipoles, tt)
      implicit none

      ! Parameters in
      ! -------------
      integer,              intent(in)    :: num_PBC         !< Number of periodic boundary conditions
      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
      real(wp),             intent(in)    :: xyz_ions(:,:)   !< Ions xyz positions
      integer,              intent(in)    :: type_ions(:)    !< Ion types
      type(MW_electrode_t), intent(in)    :: electrodes(:)   !< Electrode parameters
      real(wp),             intent(in)    :: xyz_atoms(:,:)  !< Electrode atoms xyz positions
      integer,              intent(in)    :: type_electrode_atoms(:) !< Electrode atoms types
      real(wp),             intent(in)    :: q_elec(:)       !< Electrode atoms charge
      real(wp),             intent(in)    :: dipoles(:,:)    !< Ions dipoles
      type(MW_damping_t),   intent(in)    :: tt              ! Damping parameters

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

      select case (num_PBC)
      case(2)
         call melt_forces_pim_2DPBC(localwork, ewald, box, ions, xyz_ions, type_ions, &
         electrodes, xyz_atoms, type_electrode_atoms, q_elec, force,stress_tensor, dipoles, tt)
      case(3)
         call melt_forces_pim_3DPBC(localwork, ewald, box, ions, xyz_ions, type_ions, &
         electrodes, xyz_atoms, type_electrode_atoms, q_elec, force,stress_tensor, dipoles, tt)
      end select

   end subroutine melt_forces

   !================================================================================
   ! Compute the Energy due to Coulomb interactions
   subroutine energy(num_PBC, localwork, ewald, box, ions, xyz_ions, &
      electrodes, xyz_atoms, q_elec, h, dipoles, tt)
      implicit none

      ! Parameters in
      ! -------------
      integer,              intent(in)    :: num_PBC !< number of periodic boundary conditions
      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
      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)    :: q_elec(:)      !< Electrode atoms charge
      real(wp),             intent(in)    :: dipoles(:,:)      !< ions dipoles
      type(MW_damping_t),   intent(in)    :: tt  ! Damping parameters

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

      select case (num_PBC)
      case(2)
         call energy_pim_2DPBC(localwork, ewald, box, ions, xyz_ions, &
         electrodes, xyz_atoms, q_elec, h, dipoles, tt)
      case(3)
         call energy_pim_3DPBC(localwork, ewald, box, ions, xyz_ions, &
         electrodes, xyz_atoms, q_elec, h, dipoles, tt)
      end select
   end subroutine energy

   !Functions=============================

   function gradmumelt_elec_ij(drnorm2, dx, dy, dz, &
      alpha, alphasq, alphapi) result(gmu_et_ij)
      implicit none
      ! Passed in
      ! ---------
      real(wp), intent(in)   :: drnorm2
      real(wp), intent(in)   :: dx,dy,dz
      real(wp), intent(in)   :: alpha
      real(wp), intent(in)   :: alphasq
      real(wp), intent(in)   :: alphapi

      ! Result
      ! ------
      real(wp), dimension(6) :: gmu_et_ij

      ! Local
      ! -----
      real(wp) :: drnorm, drnormrec, drnorm2rec
      real(wp) :: drnorm3rec, drnorm5rec
      real(wp) :: erfc_alpha, exp_alpha
      real(wp) :: gmuet_ij_xx, gmuet_ij_yy, gmuet_ij_zz
      real(wp) :: gmuet_ij_yx, gmuet_ij_zx, gmuet_ij_zy
      real(wp) :: efact1, efact2

      drnorm = sqrt(drnorm2)
      drnormrec = 1.0_wp/drnorm
      drnorm2rec = drnormrec*drnormrec
      drnorm3rec = drnormrec*drnorm2rec
      drnorm5rec = drnorm3rec*drnorm2rec

      erfc_alpha = erfc(alpha*drnorm)*drnormrec
      exp_alpha = exp(-alphasq*drnorm2)*alphapi

      efact1 = exp_alpha*drnorm + erfc(alpha*drnorm)   ! efact in pimaim
      efact2 = 2.0_wp*alphasq*drnorm2rec*exp_alpha

      gmuet_ij_xx = (+drnorm3rec &
      -3.0_wp*drnorm5rec*dx*dx)*efact1 &
      -dx*dx*efact2
      gmuet_ij_yx = (-3.0_wp*drnorm5rec*dy*dx)*efact1 &
      -dy*dx*efact2
      gmuet_ij_zx = (-3.0_wp*drnorm5rec*dz*dx)*efact1 &
      -dz*dx*efact2

      gmuet_ij_yy = (drnorm3rec &
      -3.0_wp*drnorm5rec*dy*dy)*efact1 &
      -dy*dy*efact2
      gmuet_ij_zy = (-3.0_wp*drnorm5rec*dz*dy)*efact1 &
      -dz*dy*efact2

      gmuet_ij_zz = (drnorm3rec &
      -3.0_wp*drnorm5rec*dz*dz)*efact1 &
      -dz*dz*efact2

      gmu_et_ij(1) = gmuet_ij_xx
      gmu_et_ij(2) = gmuet_ij_yx
      gmu_et_ij(3) = gmuet_ij_zx
      gmu_et_ij(4) = gmuet_ij_yy
      gmu_et_ij(5) = gmuet_ij_zy
      gmu_et_ij(6) = gmuet_ij_zz

   end function gradmumelt_elec_ij

   function pot_mumelt2Qelec_ij(drnorm2, dx, dy, dz, alpha, alphasq, alphapi, &
      eta, etasq, etapi, mux, muy, muz) result(pt_ij)
      implicit none
      !$acc routine seq

      ! Passed in
      ! ---------
      real(wp), intent(in) :: drnorm2
      real(wp), intent(in) :: dx, dy, dz
      real(wp), intent(in) :: alpha
      real(wp), intent(in) :: alphasq
      real(wp), intent(in) :: alphapi
      real(wp), intent(in) :: eta
      real(wp), intent(in) :: etasq
      real(wp), intent(in) :: etapi
      real(wp), intent(in) :: mux, muy, muz

      ! Result
      ! ------
      real(wp) :: pt_ij

      ! Local
      ! -----
      real(wp) :: drnorm, drnormrec, drnorm2rec
      real(wp) :: erfc_alpha, exp_alpha
      real(wp) :: erfc_eta, exp_eta
      real(wp) :: rdotmu
      real(wp) :: pot_ij

      drnorm = sqrt(drnorm2)
      drnormrec = 1.0_wp/drnorm
      drnorm2rec = drnormrec*drnormrec
      ! Change erfc to 1-erf because of underflows
      erfc_alpha = erfc(alpha*drnorm)*drnormrec
      exp_alpha = exp(-alphasq*drnorm2)*alphapi
      erfc_eta = erfc(eta*drnorm)*drnormrec
      exp_eta = exp(-etasq*drnorm2)*etapi
      pot_ij =  drnorm2rec * ((erfc_alpha + exp_alpha) - (erfc_eta + exp_eta))
      rdotmu = dx*mux + dy*muy + dz*muz !In the energy this scalar product is computed with the minus

      pt_ij = +pot_ij*rdotmu !The minus from the scalar product is compesated here

   end function pot_mumelt2Qelec_ij

   function elec_qmelt2mumelt_ij(drnorm2, alpha, alphasq, alphapi) &
      result(et_ij)
      implicit none
      ! Passed in
      ! ---------
      real(wp), intent(in) :: drnorm2
      real(wp), intent(in) :: alpha
      real(wp), intent(in) :: alphasq
      real(wp), intent(in) :: alphapi

      ! Result
      ! ------
      real(wp) :: et_ij

      ! Local
      ! -----
      real(wp) :: drnorm, drnormrec, drnorm2rec
      real(wp) :: erfc_alpha, exp_alpha

      drnorm = sqrt(drnorm2)
      drnormrec = 1.0_wp/drnorm
      drnorm2rec = drnormrec*drnormrec
      erfc_alpha = erfc(alpha*drnorm)*drnormrec
      exp_alpha = exp(-alphasq*drnorm2)*alphapi

      et_ij = (erfc_alpha + exp_alpha)*drnorm2rec

   end function elec_qmelt2mumelt_ij

   function elec_mumelt2mumelt_ij(drnorm2, dx, dy, dz, &
      alpha, alphasq, alphapi, muix, muiy, muiz, mujx, mujy, mujz) &
      result(et_ij)
      implicit none
      ! Passed in
      ! ---------
      real(wp), intent(in) :: drnorm2
      real(wp), intent(in) :: dx,dy,dz
      real(wp), intent(in) :: alpha
      real(wp), intent(in) :: alphasq
      real(wp), intent(in) :: alphapi
      real(wp), intent(in) :: muix,muiy,muiz
      real(wp), intent(in) :: mujx,mujy,mujz

      ! Result
      ! ------
      real(wp),dimension(6) :: et_ij

      ! Local
      ! -----
      real(wp) :: drnorm, drnormrec, drnorm2rec
      real(wp) :: drnorm3rec, drnorm5rec
      real(wp) :: erfc_alpha, exp_alpha
      real(wp) :: muidotrij, mujdotrij
      real(wp) :: etqmu_ijx, etqmu_ijy, etqmu_ijz
      real(wp) :: etqmu_jix, etqmu_jiy, etqmu_jiz
      real(wp) :: efact1, efact2

      drnorm = sqrt(drnorm2)
      drnormrec = 1.0_wp/drnorm
      drnorm2rec = drnormrec*drnormrec
      drnorm3rec = drnormrec*drnorm2rec
      drnorm5rec = drnorm3rec*drnorm2rec

      erfc_alpha = erfc(alpha*drnorm)*drnormrec
      exp_alpha = exp(-alphasq*drnorm2)*alphapi

      muidotrij = -muix*dx - muiy*dy - muiz*dz ! xmuidotrij in pimaim Warning sens vecteur dr
      mujdotrij = -mujx*dx - mujy*dy - mujz*dz ! xmujdotrij in pimaim


      efact1 = exp_alpha*drnorm + erfc(alpha*drnorm)   ! efact in pimaim
      efact2 = 2.0_wp*alphasq*drnorm2rec*exp_alpha

      etqmu_ijx = -(muix*drnorm3rec &
      +3.0_wp*dx*drnorm5rec*muidotrij)*efact1 &
      -dx*muidotrij*efact2
      etqmu_ijy = -(muiy*drnorm3rec &
      +3.0_wp*dy*drnorm5rec*muidotrij)*efact1 &
      -dy*muidotrij*efact2
      etqmu_ijz = -(muiz*drnorm3rec &
      +3.0_wp*dz*drnorm5rec*muidotrij)*efact1 &
      -dz*muidotrij*efact2

      etqmu_jix = -(mujx*drnorm3rec &
      +3.0_wp*dx*drnorm5rec*mujdotrij)*efact1 &
      -dx*mujdotrij*efact2
      etqmu_jiy = -(mujy*drnorm3rec &
      +3.0_wp*dy*drnorm5rec*mujdotrij)*efact1 &
      -dy*mujdotrij*efact2
      etqmu_jiz = -(mujz*drnorm3rec &
      +3.0_wp*dz*drnorm5rec*mujdotrij)*efact1 &
      -dz*mujdotrij*efact2

      et_ij(1) = etqmu_ijx
      et_ij(2) = etqmu_ijy
      et_ij(3) = etqmu_ijz
      et_ij(4) = etqmu_jix
      et_ij(5) = etqmu_jiy
      et_ij(6) = etqmu_jiz

   end function elec_mumelt2mumelt_ij

   function elec_Qelec2mumelt_ij(drnorm2, dx, dy, dz, &
      alpha, alphasq, alphapi, eta, etasq, etapi, Q_j) result(et_ij)
      implicit none
      ! Passed in
      ! ---------
      real(wp), intent(in) :: drnorm2
      real(wp), intent(in) :: dx, dy, dz
      real(wp), intent(in) :: alpha
      real(wp), intent(in) :: alphasq
      real(wp), intent(in) :: alphapi
      real(wp), intent(in) :: eta
      real(wp), intent(in) :: etasq
      real(wp), intent(in) :: etapi
      real(wp), intent(in) :: Q_j

      ! Result
      ! ------
      real(wp), dimension(3) :: et_ij

      ! Local
      ! -----
      real(wp) :: drnorm, drnormrec, drnorm2rec
      real(wp) :: erfc_alpha, exp_alpha
      real(wp) :: erfc_eta, exp_eta
      real(wp) :: eij

      drnorm = sqrt(drnorm2)
      drnormrec = 1.0_wp/drnorm
      drnorm2rec = drnormrec*drnormrec
      ! Change erfc to 1-erf because of underflows
      erfc_alpha = erfc(alpha*drnorm)*drnormrec
      exp_alpha = exp(-alphasq*drnorm2)*alphapi
      erfc_eta = erfc(eta*drnorm)*drnormrec
      exp_eta = exp(-etasq*drnorm2)*etapi

      eij = drnorm2rec*((erfc_alpha + exp_alpha) - (erfc_eta + exp_eta))

      et_ij(1) = eij*Q_j*dx
      et_ij(2) = eij*Q_j*dy
      et_ij(3) = eij*Q_j*dz

   end function elec_Qelec2mumelt_ij

   function force_melt2melt_ij(drnorm2, dx, dy, dz, &
      alpha, alphasq, alphapi, qi, qj, &
      muix, muiy, muiz, mujx, mujy, mujz, &
      bij, bji, orderij, orderji, cij, cji) &
      result(ft_ij)
      implicit none
      ! Passed in
      ! ---------
      integer,  intent(in) :: orderij, orderji
      real(wp), intent(in) :: drnorm2
      real(wp), intent(in) :: dx, dy, dz
      real(wp), intent(in) :: alpha
      real(wp), intent(in) :: alphasq
      real(wp), intent(in) :: alphapi
      real(wp), intent(in) :: qi
      real(wp), intent(in) :: qj
      real(wp), intent(in) :: muix, muiy, muiz
      real(wp), intent(in) :: mujx, mujy, mujz
      real(wp), intent(in) :: bij, bji, cij, cji

      ! Result
      ! ------
      real(wp),dimension(3) :: ft_ij

      ! Local
      ! -----
      integer  :: kk
      real(wp) :: drnorm, drnormrec, drnorm2rec, drnorm7rec
      real(wp) :: drnorm3rec
      real(wp) :: erfc_alpha, exp_alpha
      real(wp) :: muidotrij, mujdotrij
      real(wp) :: ftqq_ij, ftqq_ijx, ftqq_ijy, ftqq_ijz
      real(wp) :: ftqmu_ijx, ftqmu_ijy, ftqmu_ijz
      real(wp) :: ftqmu_jix, ftqmu_jiy, ftqmu_jiz
      real(wp) :: ftqmusr_ijx, ftqmusr_ijy, ftqmusr_ijz
      real(wp) :: ftqmusr_jix, ftqmusr_jiy, ftqmusr_jiz
      real(wp) :: ftmumu_ijx, ftmumu_ijy, ftmumu_ijz
      real(wp) :: efact1, efact2, efact3
      real(wp) :: qjdotmuix, qjdotmuiy, qjdotmuiz
      real(wp) :: minusqidotmujx, minusqidotmujy, minusqidotmujz
      real(wp) :: qmuengij, qmuengji, qmueng
      real(wp) :: muidotSx, muidotSy, muidotSz, muidotSdotmuj
      real(wp) :: sxx, sxy, sxz, syy, syz, szz
      real(wp) :: txxx, txxy, txyy, txxz, txzz, tyyy, tyyz, tyzz, tzzz, txyz
      real(wp) :: mujdotTdotmuix, mujdotTdotmuiy, mujdotTdotmuiz
      real(wp) :: xf, factorial
      real(wp) :: dampsumfi, dampexpi, dampfunci, dampfuncdiffi, diprfunci
      real(wp) :: dampsumfj, dampexpj, dampfuncj, dampfuncdiffj, diprfuncj
      real(wp) :: bjidrnorm, bijdrnorm

      drnorm = sqrt(drnorm2)
      drnormrec = 1.0_wp/drnorm
      drnorm2rec = drnormrec*drnormrec
      drnorm3rec = drnormrec*drnorm2rec
      drnorm7rec = drnorm3rec*drnorm2rec*drnorm2rec

      erfc_alpha = erfc(alpha*drnorm)*drnormrec
      exp_alpha = exp(-alphasq*drnorm2)*alphapi

      ftqq_ij = qi*qj*(erfc_alpha + exp_alpha)*drnorm2rec
      ftqq_ijx = -dx*ftqq_ij
      ftqq_ijy = -dy*ftqq_ij
      ftqq_ijz = -dz*ftqq_ij

      muidotrij = -muix*dx - muiy*dy - muiz*dz ! xmuidotrij in pimaim Warning sens vecteur dr
      mujdotrij = -mujx*dx - mujy*dy - mujz*dz ! xmujdotrij in pimaim

      efact1 = exp_alpha*drnorm + erfc(alpha*drnorm)   ! efact in pimaim
      efact2 = 2.0_wp*alphasq*drnorm2rec*exp_alpha
      efact3 = 2.0_wp*efact2*(drnorm2rec + alphasq)

      qmuengij = (qj*muidotrij)*drnorm3rec  !chgdipengij
      qmuengji = -(qi*mujdotrij)*drnorm3rec !chgdipengji
      qmueng = (qmuengij + qmuengji)*efact1   !chgdipeng

      qjdotmuix = qj*muix  ! qdotmuxij in pimaim
      qjdotmuiy = qj*muiy  ! qdotmuyij in pimaim
      qjdotmuiz = qj*muiz  ! qdotmuzij in pimaim

      minusqidotmujx = -qi*mujx ! qdotmuxji in pimaim
      minusqidotmujy = -qi*mujy ! qdotmuyji in pimaim
      minusqidotmujz = -qi*mujz ! qdotmuzji in pimaim

      ftqmu_ijx = (qjdotmuix*drnorm3rec &
      +3.0_wp*dx*drnorm2rec*qmuengij)*efact1 &
      +dx*muidotrij*qj*efact2
      ftqmu_ijy = (qjdotmuiy*drnorm3rec &
      +3.0_wp*dy*drnorm2rec*qmuengij)*efact1 &
      +dy*muidotrij*qj*efact2
      ftqmu_ijz = (qjdotmuiz*drnorm3rec &
      +3.0_wp*dz*drnorm2rec*qmuengij)*efact1 &
      +dz*muidotrij*qj*efact2

      ftqmu_jix = (minusqidotmujx*drnorm3rec &
      +3.0_wp*dx*drnorm2rec*qmuengji)*efact1 &
      -dx*mujdotrij*qi*efact2
      ftqmu_jiy = (minusqidotmujy*drnorm3rec &
      +3.0_wp*dy*drnorm2rec*qmuengji)*efact1 &
      -dy*mujdotrij*qi*efact2
      ftqmu_jiz = (minusqidotmujz*drnorm3rec &
      +3.0_wp*dz*drnorm2rec*qmuengji)*efact1 &
      -dz*mujdotrij*qi*efact2

      dampsumfi = 1.0_wp
      xf = 1.0_wp
      factorial = 1.0_wp
      bjidrnorm = bji*drnorm
      do kk = 1, orderji
         xf = xf*bjidrnorm
         factorial = factorial*float(kk)
         dampsumfi = dampsumfi + (xf/factorial)
      enddo
      dampexpi = dexp(-bji*drnorm)
      dampfunci = -dampsumfi*dampexpi*cji
      dampfuncdiffi = bji*dampexpi*cji*((bjidrnorm)**orderji)/factorial
      diprfunci = qmuengij*drnormrec*(-3.0_wp*dampfunci*drnormrec + dampfuncdiffi)

      ftqmusr_ijx = qjdotmuix*dampfunci*drnorm3rec - dx*diprfunci
      ftqmusr_ijy = qjdotmuiy*dampfunci*drnorm3rec - dy*diprfunci
      ftqmusr_ijz = qjdotmuiz*dampfunci*drnorm3rec - dz*diprfunci

      dampsumfj = 1.0_wp
      xf = 1.0_wp
      factorial = 1.0_wp
      bijdrnorm = bij*drnorm
      do kk = 1, orderij
         xf = xf*bijdrnorm
         factorial = factorial*float(kk)
         dampsumfj = dampsumfj + (xf/factorial)
      enddo
      dampexpj = dexp(-bij*drnorm)
      dampfuncj = -dampsumfj*dampexpj*cij
      dampfuncdiffj = bij*dampexpj*cij*((bijdrnorm)**orderij)/factorial
      diprfuncj = -qmuengji*drnormrec*(-3.0_wp*dampfuncj*drnormrec + dampfuncdiffj)

      ftqmusr_jix = minusqidotmujx*dampfuncj*drnorm3rec + dx*diprfuncj
      ftqmusr_jiy = minusqidotmujy*dampfuncj*drnorm3rec + dy*diprfuncj
      ftqmusr_jiz = minusqidotmujz*dampfuncj*drnorm3rec + dz*diprfuncj

      sxx = 1.0_wp - 3.0_wp*dx*dx*drnorm2rec ! sxx in pimaim
      syy = 1.0_wp - 3.0_wp*dy*dy*drnorm2rec
      szz = 1.0_wp - 3.0_wp*dz*dz*drnorm2rec
      sxy = -3.0_wp*dx*dy*drnorm2rec
      sxz = -3.0_wp*dx*dz*drnorm2rec
      syz = -3.0_wp*dy*dz*drnorm2rec

      muidotSx = muix*sxx + muiy*sxy + muiz*sxz  ! xmuidotT in pimaim
      muidotSy = muix*sxy + muiy*syy + muiz*syz  ! ymuidotT in pimaim
      muidotSz = muix*sxz + muiy*syz + muiz*szz  ! zmuidotT in pimaim

      muidotSdotmuj = muidotSx*mujx + muidotSy*mujy + muidotSz*mujz ! dipdipeng in pimaim

      txxx = -(15.0_wp*dx**3.0    - 9.0_wp*dx*drnorm2)*drnorm7rec
      tyyy = -(15.0_wp*dy**3.0    - 9.0_wp*dy*drnorm2)*drnorm7rec
      tzzz = -(15.0_wp*dz**3.0    - 9.0_wp*dz*drnorm2)*drnorm7rec
      txxy = -(15.0_wp*dy*dx**2.0 - 3.0_wp*dy*drnorm2)*drnorm7rec
      txyy = -(15.0_wp*dx*dy**2.0 - 3.0_wp*dx*drnorm2)*drnorm7rec
      txxz = -(15.0_wp*dz*dx**2.0 - 3.0_wp*dz*drnorm2)*drnorm7rec
      txzz = -(15.0_wp*dx*dz**2.0 - 3.0_wp*dx*drnorm2)*drnorm7rec
      tyyz = -(15.0_wp*dz*dy**2.0 - 3.0_wp*dz*drnorm2)*drnorm7rec
      tyzz = -(15.0_wp*dy*dz**2.0 - 3.0_wp*dy*drnorm2)*drnorm7rec
      txyz = -(15.0_wp*dx*dy*dz                     )*drnorm7rec

      mujdotTdotmuix = (mujx*(muix*txxx + muiy*txxy + muiz*txxz)) &  !fmumux in pimaim
      +(mujy*(muix*txxy + muiy*txyy + muiz*txyz)) &
      +(mujz*(muix*txxz + muiy*txyz + muiz*txzz))
      mujdotTdotmuiy = (mujx*(muix*txxy + muiy*txyy + muiz*txyz)) &  !fmumuy in pimaim
      +(mujy*(muix*txyy + muiy*tyyy + muiz*tyyz)) &
      +(mujz*(muix*txyz + muiy*tyyz + muiz*tyzz))
      mujdotTdotmuiz = (mujx*(muix*txxz + muiy*txyz + muiz*txzz)) &  !fmumuz in pimaim
      +(mujy*(muix*txyz + muiy*tyyz + muiz*tyzz)) &
      +(mujz*(muix*txzz + muiy*tyzz + muiz*tzzz))

      ftmumu_ijx = -mujdotTdotmuix*efact1 - muidotSdotmuj*efact2*dx + muix*mujdotrij*efact2 &
      +mujx*muidotrij*efact2 + muidotrij*mujdotrij*dx*efact3
      ftmumu_ijy = -mujdotTdotmuiy*efact1 - muidotSdotmuj*efact2*dy + muiy*mujdotrij*efact2 &
      +mujy*muidotrij*efact2 + muidotrij*mujdotrij*dy*efact3
      ftmumu_ijz = -mujdotTdotmuiz*efact1 - muidotSdotmuj*efact2*dz + muiz*mujdotrij*efact2 &
      +mujz*muidotrij*efact2 + muidotrij*mujdotrij*dz*efact3

      !     ft_ij(1) = ftqmu_ijx+ftqmu_jix
      !     ft_ij(2) = ftqmu_ijy+ftqmu_jiy
      !     ft_ij(3) = ftqmu_ijz+ftqmu_jiz
      ft_ij(1) = ftqq_ijx + ftqmu_ijx + ftqmu_jix + ftqmusr_ijx + ftqmusr_jix + ftmumu_ijx
      ft_ij(2) = ftqq_ijy + ftqmu_ijy + ftqmu_jiy + ftqmusr_ijy + ftqmusr_jiy + ftmumu_ijy
      ft_ij(3) = ftqq_ijz + ftqmu_ijz + ftqmu_jiz + ftqmusr_ijz + ftqmusr_jiz + ftmumu_ijz

   end function force_melt2melt_ij

   function force_elec2melt_ij(drnorm2, dx, dy, dz, &
      alpha, alphasq, alphapi, eta, etasq, etapi, &
      qi, Q_j, muix, muiy, muiz) result(ft_ij)
      implicit none
      !$acc routine seq

      real(wp), intent(in) :: drnorm2
      real(wp), intent(in) :: dx, dy, dz
      real(wp), intent(in) :: alpha
      real(wp), intent(in) :: alphasq
      real(wp), intent(in) :: alphapi
      real(wp), intent(in) :: eta
      real(wp), intent(in) :: etasq
      real(wp), intent(in) :: etapi
      real(wp), intent(in) :: qi
      real(wp), intent(in) :: Q_j
      real(wp), intent(in) :: muix, muiy, muiz

      ! Result
      ! ------
      real(wp), dimension(3) :: ft_ij

      ! Local
      ! -----
      real(wp) :: drnorm, drnormrec, drnorm2rec
      real(wp) :: drnorm3rec
      real(wp) :: erfc_alpha, exp_alpha
      real(wp) :: erfc_eta, exp_eta
      real(wp) :: fijqq
      real(wp) :: muidotrij
      real(wp) :: efact_alpha_1, efact_alpha_2
      real(wp) :: efact_eta_1, efact_eta_2
      real(wp) :: Qmueng
      real(wp) :: Qjdotmuix, Qjdotmuiy, Qjdotmuiz

      drnorm = sqrt(drnorm2)
      drnormrec = 1.0_wp/drnorm
      drnorm2rec = drnormrec*drnormrec
      drnorm3rec = drnorm2rec*drnormrec

      ! Change erfc to 1-erf because of underflows
      erfc_alpha = erfc(alpha*drnorm)*drnormrec
      exp_alpha = exp(-alphasq*drnorm2)*alphapi
      erfc_eta = erfc(eta*drnorm)*drnormrec
      exp_eta = exp(-etasq*drnorm2)*etapi

      fijqq = qi*Q_j*drnorm2rec*((erfc_alpha + exp_alpha) - (erfc_eta + exp_eta))

      ft_ij(1) = -fijqq*dx
      ft_ij(2) = -fijqq*dy
      ft_ij(3) = -fijqq*dz

      muidotrij = muix*dx + muiy*dy + muiz*dz ! xmuidotrij in pimaim Warning sens vecteur dr

      efact_alpha_1 = exp_alpha*drnorm + erfc(alpha*drnorm)   ! efact in pimaim
      efact_alpha_2 = 2.0_wp*alphasq*drnorm2rec*exp_alpha

      efact_eta_1 = exp_eta*drnorm + erfc(eta*drnorm)   ! efact in pimaim
      efact_eta_2 = 2.0_wp*etasq*drnorm2rec*exp_eta

      Qmueng = (Q_j*muidotrij)*drnorm3rec  !chgdipengij

      Qjdotmuix = Q_j*muix  ! qdotmuxij in pimaim
      Qjdotmuiy = Q_j*muiy  ! qdotmuyij in pimaim
      Qjdotmuiz = Q_j*muiz  ! qdotmuzij in pimaim

      ft_ij(1) = ft_ij(1) + &
         ((Qjdotmuix*drnorm3rec - 3.0_wp*dx*drnorm2rec*Qmueng)*efact_alpha_1 &
         - dx*muidotrij*Q_j*efact_alpha_2) - &
         ((Qjdotmuix*drnorm3rec - 3.0_wp*dx*drnorm2rec*Qmueng)*efact_eta_1 &
         - dx*muidotrij*Q_j*efact_eta_2)
      ft_ij(2) = ft_ij(2) + &
         ((Qjdotmuiy*drnorm3rec - 3.0_wp*dy*drnorm2rec*Qmueng)*efact_alpha_1 &
         - dy*muidotrij*Q_j*efact_alpha_2) - &
         ((Qjdotmuiy*drnorm3rec - 3.0_wp*dy*drnorm2rec*Qmueng)*efact_eta_1 &
         - dy*muidotrij*Q_j*efact_eta_2)
      ft_ij(3) = ft_ij(3) + &
         ((Qjdotmuiz*drnorm3rec - 3.0_wp*dz*drnorm2rec*Qmueng)*efact_alpha_1 &
         - dz*muidotrij*Q_j*efact_alpha_2) - &
         ((Qjdotmuiz*drnorm3rec - 3.0_wp*dz*drnorm2rec*Qmueng)*efact_eta_1 &
         - dz*muidotrij*Q_j*efact_eta_2)

   end function force_elec2melt_ij

   function energy_melt2melt_ij(drnorm2, dx, dy, dz, &
      alpha, alphasq, alphapi, qi, qj, &
      muix, muiy, muiz, mujx, mujy, mujz, &
      bij, bji, orderij, orderji, cij, cji) &
      result(enerij)
      implicit none
      ! Passed in
      ! ---------
      integer,  intent(in) :: orderij, orderji
      real(wp), intent(in) :: drnorm2
      real(wp), intent(in) :: dx, dy, dz
      real(wp), intent(in) :: alpha
      real(wp), intent(in) :: alphasq
      real(wp), intent(in) :: alphapi
      real(wp), intent(in) :: qi
      real(wp), intent(in) :: qj
      real(wp), intent(in) :: muix, muiy, muiz
      real(wp), intent(in) :: mujx, mujy, mujz
      real(wp), intent(in) :: bij, bji, cij, cji

      ! Result
      ! ------
      real(wp) :: enerij

      ! Local
      ! -----
      integer  :: kk
      real(wp) :: drnorm, drnormrec, drnorm2rec
      real(wp) :: drnorm3rec
      real(wp) :: erfc_alpha, exp_alpha
      real(wp) :: muidotrij, mujdotrij
      real(wp) :: efact1, efact2
      real(wp) :: qmuengij, qmuengji, qmueng
      real(wp) :: muidotSx, muidotSy, muidotSz, muidotSdotmuj
      real(wp) :: sxx, sxy, sxz, syy, syz, szz
      real(wp) :: xf, factorial
      real(wp) :: dampsumfi, dampexpi, dampfunci
      real(wp) :: dampsumfj, dampexpj, dampfuncj
      real(wp) :: bjidrnorm, bijdrnorm

      drnorm = sqrt(drnorm2)
      drnormrec = 1.0_wp/drnorm
      drnorm2rec = drnormrec*drnormrec
      drnorm3rec = drnormrec*drnorm2rec

      erfc_alpha = erfc(alpha*drnorm)*drnormrec
      exp_alpha = exp(-alphasq*drnorm2)*alphapi

      enerij = qi*qj*erfc_alpha

      muidotrij = -muix*dx - muiy*dy - muiz*dz ! xmuidotrij in pimaim Warning sens vecteur dr
      mujdotrij = -mujx*dx - mujy*dy - mujz*dz ! xmujdotrij in pimaim

      efact1 = exp_alpha*drnorm + erfc(alpha*drnorm)   ! efact in pimaim
      efact2 = 2.0_wp*alphasq*drnorm2rec*exp_alpha

      qmuengij = (qj*muidotrij)*drnorm3rec  !chgdipengij
      qmuengji = -(qi*mujdotrij)*drnorm3rec !chgdipengji
      qmueng = (qmuengij + qmuengji)*efact1   !chgdipeng
      enerij = enerij - qmueng

      dampsumfi = 1.0_wp
      xf = 1.0_wp
      factorial = 1.0_wp
      bjidrnorm = bji*drnorm
      do kk = 1, orderji
         xf = xf*bjidrnorm
         factorial = factorial*float(kk)
         dampsumfi = dampsumfi + (xf/factorial)
      enddo
      dampexpi = dexp(-bji*drnorm)
      dampfunci = -dampsumfi*dampexpi*cji*drnorm3rec
      enerij = enerij - qj*muidotrij*dampfunci

      dampsumfj = 1.0_wp
      xf = 1.0_wp
      factorial = 1.0_wp
      bijdrnorm = bij*drnorm
      do kk = 1, orderij
         xf = xf*bijdrnorm
         factorial = factorial*float(kk)
         dampsumfj = dampsumfj + (xf/factorial)
      enddo
      dampexpj = dexp(-bij*drnorm)
      dampfuncj = -dampsumfj*dampexpj*cij*drnorm3rec
      enerij = enerij + qi*mujdotrij*dampfuncj

      sxx = 1.0_wp - 3.0_wp*dx*dx*drnorm2rec ! sxx in pimaim
      syy = 1.0_wp - 3.0_wp*dy*dy*drnorm2rec
      szz = 1.0_wp - 3.0_wp*dz*dz*drnorm2rec
      sxy = -3.0_wp*dx*dy*drnorm2rec
      sxz = -3.0_wp*dx*dz*drnorm2rec
      syz = -3.0_wp*dy*dz*drnorm2rec

      muidotSx = muix*sxx + muiy*sxy + muiz*sxz  ! xmuidotT in pimaim
      muidotSy = muix*sxy + muiy*syy + muiz*syz  ! ymuidotT in pimaim
      muidotSz = muix*sxz + muiy*syz + muiz*szz  ! zmuidotT in pimaim

      muidotSdotmuj = muidotSx*mujx + muidotSy*mujy + muidotSz*mujz ! dipdipeng in pimaim (1st occurence)

      enerij = enerij + muidotSdotmuj*efact1*drnorm3rec - muidotrij*mujdotrij*efact2

   end function energy_melt2melt_ij

   function energy_elec2melt_ij(drnorm2, dx, dy, dz, &
      alpha, alphasq, alphapi, eta, etasq, etapi,&
      qi, Q_j, muix, muiy, muiz) &
      result(enerij)
      implicit none
      ! Passed in
      ! ---------
      real(wp), intent(in) :: drnorm2
      real(wp), intent(in) :: dx,dy,dz
      real(wp), intent(in) :: alpha
      real(wp), intent(in) :: alphasq
      real(wp), intent(in) :: alphapi
      real(wp), intent(in) :: eta
      real(wp), intent(in) :: etasq
      real(wp), intent(in) :: etapi
      real(wp), intent(in) :: qi
      real(wp), intent(in) :: Q_j
      real(wp), intent(in) :: muix,muiy,muiz

      ! Result
      ! ------
      real(wp) :: enerij

      ! Local
      ! -----
      real(wp) :: drnorm, drnormrec, drnorm2rec
      real(wp) :: drnorm3rec
      real(wp) :: erfc_alpha, exp_alpha
      real(wp) :: erfc_eta, exp_eta
      real(wp) :: eij
      real(wp) :: muidotrij
      real(wp) :: Qmueng

      drnorm = sqrt(drnorm2)
      drnormrec = 1.0_wp/drnorm
      drnorm2rec = drnormrec*drnormrec
      drnorm3rec = drnormrec*drnorm2rec

      erfc_alpha = erfc(alpha*drnorm)*drnormrec
      erfc_eta = erfc(eta*drnorm)*drnormrec

      enerij = qi*Q_j*(erfc_alpha - erfc_eta) !energy due to charges qQ

      exp_alpha = exp(-alphasq*drnorm2)*alphapi
      exp_eta = exp(-etasq*drnorm2)*etapi

      eij =  drnorm2rec*((erfc_alpha + exp_alpha) - (erfc_eta + exp_eta))

      muidotrij = muix*dx + muiy*dy + muiz*dz ! xmuidotrij in pimaim Warning sens vecteur dr

      Qmueng =  (Q_j*muidotrij)*eij         !chgdipengij
      enerij = enerij + Qmueng !energy due to dipoles and electrodes charges muQ

   end function energy_elec2melt_ij

   ! ================================================================================
   include 'coulomb_sr_pim_2DPBC.inc'
   include 'coulomb_sr_pim_3DPBC.inc'
   ! ================================================================================
   include 'minimum_image_displacement_2DPBC.inc'
   include 'minimum_image_distance_2DPBC.inc'
   include 'minimum_image_displacement_3DPBC.inc'
   include 'minimum_image_distance_3DPBC.inc'
   ! ================================================================================
   include 'update_diag_block_boundaries.inc'
   include 'update_tri_block_boundaries.inc'
   include 'update_other_block_boundaries.inc'

end module MW_coulomb_sr_pim
