Computes the electric field of a trial set of induced point dipoles at polarizable sites. This is intended to be used as matrix-vector routine in the solution of the linear system.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
type(ommp_electrostatics_type), | intent(in) | :: | eel |
Data structure for electrostatic part of the system |
||
real(kind=rp), | intent(in) | :: | ext_ipd(3,eel%pol_atoms) |
External induced point dipoles at polarizable sites |
||
real(kind=rp), | intent(inout) | :: | E(3,eel%pol_atoms) |
Electric field (results will be added) |
subroutine field_extD2D(eel, ext_ipd, E)
!! Computes the electric field of a trial set of induced point dipoles
!! at polarizable sites. This is intended to be used as matrix-vector
!! routine in the solution of the linear system.
implicit none
type(ommp_electrostatics_type), intent(in) :: eel
!! Data structure for electrostatic part of the system
real(rp), intent(in) :: ext_ipd(3, eel%pol_atoms)
!! External induced point dipoles at polarizable sites
real(rp), intent(inout) :: E(3, eel%pol_atoms)
!! Electric field (results will be added)
integer(ip) :: i, j, ipol, jpol, ij, idx
logical :: to_scale, to_do
real(rp) :: kernel(5), dr(3), tmpV, tmpE(3), tmpEgr(6), tmpHE(10), scalf
type(fmm_type), allocatable :: fmm_ipd
if(eel%use_fmm) then
allocate(fmm_ipd)
call fmm_init(fmm_ipd, eel%fmm_maxl_pol, eel%tree)
call prepare_fmm_ext_ipd(eel, fmm_ipd, ext_ipd)
!$omp parallel do default(shared) schedule(dynamic) &
!$omp private(i,j,ij,ipol,jpol,idx,dr,kernel,to_do,to_scale,scalf,tmpV,tmpE,tmpEgr,tmpHE)
do ipol=1, eel%pol_atoms
i = eel%polar_mm(ipol)
tmpE = 0.0
call cart_propfar_at_ipart(fmm_ipd, i, &
.false., tmpV, &
.true. , tmpE, &
.false., tmpEgr, &
.false., tmpHE)
E(:, ipol) = tmpE
end do
!$omp parallel do default(shared) schedule(dynamic) &
!$omp private(i,j,ij,ipol,jpol,idx,dr,kernel,to_do,to_scale,scalf,tmpV,tmpE,tmpEgr,tmpHE)
do ipol=1, eel%pol_atoms
i = eel%polar_mm(ipol)
! Near field is computed internally because dumped kernel is required
do ij=eel%fmm_near_field_list%ri(i), eel%fmm_near_field_list%ri(i+1)-1
j = eel%fmm_near_field_list%ci(ij)
jpol = eel%mm_polar(j)
! If the atom is not polarizable, skip
if(jpol < 1) cycle
!loop on target
to_do = .true.
to_scale = .false.
scalf = 1.0
! Check if the element should be scaled
do idx=eel%list_P_P%ri(ipol), eel%list_P_P%ri(ipol+1)-1
if(eel%list_P_P%ci(idx) == jpol) then
to_scale = .true.
exit
end if
end do
!If it should set the correct variables
if(to_scale) then
to_do = eel%todo_P_P(idx)
scalf = eel%scalef_P_P(idx)
end if
if(to_do) then
call damped_coulomb_kernel(eel, j, i,&
2, kernel(1:3), dr)
tmpE = 0.0_rp
call mu_elec_prop(ext_ipd(:,jpol), dr, kernel, .false., tmpV, &
.true., tmpE, .false., tmpEgr, &
.false., tmpHE)
if(to_scale) then
E(:, ipol) = E(:, ipol) + tmpE * scalf
else
E(:, ipol) = E(:, ipol) + tmpE
end if
end if
end do
end do
if(allocated(eel%list_P_P_fmm_far)) then
! Now remove screened interactions from far-field
do ipol=1, eel%pol_atoms
i = eel%polar_mm(ipol)
do idx=eel%list_P_P_fmm_far%ri(ipol), eel%list_P_P_fmm_far%ri(ipol+1)-1
jpol = eel%list_P_P_fmm_far%ci(idx)
j = eel%polar_mm(jpol)
scalf = 1.0 - eel%scalef_P_P_fmm_far(idx)
call damped_coulomb_kernel(eel, j, i,&
2, kernel(1:3), dr)
tmpE = 0.0_rp
call mu_elec_prop(ext_ipd(:,jpol), dr, kernel, .false., tmpV, &
.true., tmpE, .false., tmpEgr, &
.false., tmpHE)
E(:, ipol) = E(:, ipol) - tmpE * scalf
end do
end do
end if
deallocate(fmm_ipd%multipoles)
deallocate(fmm_ipd%local_expansion)
deallocate(fmm_ipd)
else
!$omp parallel do default(shared) schedule(dynamic) &
!$omp private(i,j,to_do,to_scale,scalf,idx,tmpV,tmpE,tmpEgr,tmpHE,kernel,dr)
do j=1, eel%pol_atoms
do i=1, eel%pol_atoms
if(j == i) cycle
!loop on target
to_do = .true.
to_scale = .false.
scalf = 1.0
! Check if the element should be scaled
do idx=eel%list_P_P%ri(i), eel%list_P_P%ri(i+1)-1
if(eel%list_P_P%ci(idx) == j) then
to_scale = .true.
exit
end if
end do
!If it should set the correct variables
if(to_scale) then
to_do = eel%todo_P_P(idx)
scalf = eel%scalef_P_P(idx)
end if
if(to_do) then
call damped_coulomb_kernel(eel, eel%polar_mm(i), &
eel%polar_mm(j),&
2, kernel(1:3), dr)
tmpE = 0.0_rp
call mu_elec_prop(ext_ipd(:,i), dr, kernel, .false., tmpV, &
.true., tmpE, .false., tmpEgr, &
.false., tmpHE)
if(to_scale) then
E(:, j) = E(:, j) + tmpE * scalf
else
E(:, j) = E(:, j) + tmpE
end if
end if
end do
end do
end if
end subroutine field_extD2D