ddx 0.6.0
Libary for domain-decomposition methods for polarizable continuum models
ddx_lpb_core.f90
1
9
12! Get the core-routines
13use ddx_core
14!
15contains
16
27subroutine wghpot_f(params, constants, workspace, gradphi, f, ddx_error)
28 !! Inputs
29 type(ddx_params_type), intent(in) :: params
30 type(ddx_constants_type), intent(in) :: constants
31 real(dp), intent(in) :: gradphi(3, constants % ncav)
32 !! Temporary buffers
33 type(ddx_workspace_type), intent(inout) :: workspace
34 type(ddx_error_type), intent(inout) :: ddx_error
35 !! Outputs
36 real(dp), intent(out) :: f(params % ngrid, params % nsph)
37 !! Local variables
38 integer :: isph, ig, ic, ind, ind0, jsph
39 real(dp) :: nderphi, sumSijn, sumSijn_pre
40 real(dp), dimension(3) :: vij, vtij
41 real(dp), allocatable :: SK_rijn(:), DK_rijn(:), c0(:,:), c1(:,:)
42 integer :: l0, icav, istatus, indl, inode
43 complex(dp) :: work_complex(constants % lmax0 + 1)
44 real(dp) :: work(constants % lmax0 + 1)
45
46
47 allocate(sk_rijn(0:constants % lmax0), dk_rijn(0:constants % lmax0), &
48 & c0(constants % nbasis0, params % nsph), &
49 & c1(constants % nbasis0, params % nsph), stat=istatus)
50 if (istatus.ne.0) then
51 call update_error(ddx_error, 'Allocation in wghpot_f failed')
52 end if
53
54 ic = 0
55 f = zero
56 c0 = zero
57 c1 = zero
58
59 ! Compute c0 Eq.(98) QSM19.SISC
60 do isph = 1, params % nsph
61 do ig = 1, params % ngrid
62 if (constants % ui(ig, isph) .ne. zero) then
63 ic = ic + 1
64 nderphi = dot_product(gradphi(:, ic), constants % cgrid(:,ig))
65 c0(:, isph) = c0(:, isph) + &
66 & constants % wgrid(ig)*constants % ui(ig,isph)*&
67 & nderphi*constants % vgrid(1:constants % nbasis0,ig)
68 do l0 = 0, constants % lmax0
69 ind0 = l0*l0 + 1
70 ind = ind0 + 2*l0
71 c1(ind0:ind, isph) = constants % C_ik(l0, isph) * &
72 & c0(ind0:ind, isph)
73 end do
74 end if
75 end do
76 end do
77
78 ! Computation of F0 using above terms
79 ! icav: External grid poitns
80 if (params % fmm .eq. 0) then
81 icav = 0
82 do isph = 1, params % nsph
83 do ig = 1, params % ngrid
84 if (constants % ui(ig,isph).gt.zero) then
85 icav = icav + 1
86 sumsijn = zero
87 ! Loop to compute Sijn
88 do jsph = 1, params % nsph
89 sumsijn_pre = sumsijn
90 vij = params % csph(:,isph) + &
91 & params % rsph(isph)*constants % cgrid(:,ig) - &
92 & params % csph(:,jsph)
93 vtij = vij*params % kappa
94 call fmm_m2p_bessel_work(vtij, &
95 & constants % lmax0, constants % vscales, &
96 & constants % SK_ri(:, jsph), one, &
97 & c1(:, jsph), one, sumsijn, work_complex, work)
98 end do
99 ! Here Intermediate value of F_0 is computed Eq. (99)
100 ! Mutilplication with Y_lm and weights will happen afterwards
101 !write(6,*) sumSijn, epsp, eps, ddx_data % constants % ui(ig,isph)
102 f(ig,isph) = -(params % epsp/params % eps)*constants % ui(ig,isph) * sumsijn
103 end if
104 end do
105 end do
106 else
107 ! Load input harmonics into tree data
108 workspace % tmp_node_m = zero
109 workspace % tmp_node_l = zero
110 workspace % tmp_sph = zero
111 workspace % tmp_sph(1:constants % nbasis0, :) = c1(:, :)
112 if(constants % lmax0 .lt. params % pm) then
113 do isph = 1, params % nsph
114 inode = constants % snode(isph)
115 workspace % tmp_node_m(1:constants % nbasis0, inode) = &
116 & workspace % tmp_sph(1:constants % nbasis0, isph)
117 workspace % tmp_node_m(constants % nbasis0+1:, inode) = zero
118 end do
119 else
120 indl = (params % pm+1)**2
121 do isph = 1, params % nsph
122 inode = constants % snode(isph)
123 workspace % tmp_node_m(:, inode) = workspace % tmp_sph(1:indl, isph)
124 end do
125 end if
126 ! Do FMM operations
127 call tree_m2m_bessel_rotation(params, constants, workspace % tmp_node_m)
128 call tree_m2l_bessel_rotation(params, constants, workspace % tmp_node_m, &
129 & workspace % tmp_node_l)
130 call tree_l2l_bessel_rotation(params, constants, workspace % tmp_node_l)
131 call tree_l2p_bessel(params, constants, one, workspace % tmp_node_l, zero, &
132 & workspace % tmp_grid)
133 call tree_m2p_bessel(params, constants, constants % lmax0, one, &
134 & params % lmax, workspace % tmp_sph, one, &
135 & workspace % tmp_grid)
136 f = -(params % epsp/params % eps) * constants % ui * workspace % tmp_grid
137 end if
138
139 deallocate(sk_rijn, dk_rijn, c0, c1, stat=istatus)
140 if (istatus.ne.0) then
141 call update_error(ddx_error, 'Deallocation in wghpot_f failed')
142 end if
143
144end subroutine wghpot_f
145
154subroutine calcv2_lpb (params, constants, isph, pot, x)
155 type(ddx_params_type), intent(in) :: params
156 type(ddx_constants_type), intent(in) :: constants
157 integer, intent(in) :: isph
158 real(dp), dimension(constants % nbasis, params % nsph), intent(in) :: x
159 real(dp), dimension(params % ngrid), intent(inout) :: pot
160 complex(dp) :: work_complex(params % lmax+1)
161 real(dp) :: work(params % lmax+1)
162 real(dp), dimension(params % ngrid) :: pot2
163 integer :: its, ij, jsph
164 real(dp) :: vij(3), vtij(3)
165 real(dp) :: vvij, tij, xij, oij
166
167 pot = zero
168 pot2 = zero
169 do its = 1, params % ngrid
170 if (constants % ui(its,isph).lt.one) then
171 do ij = constants % inl(isph), constants % inl(isph+1)-1
172 jsph = constants % nl(ij)
173
174 ! compute geometrical variables
175 vij = params % csph(:,isph) + params % rsph(isph)*constants % cgrid(:,its) - params % csph(:,jsph)
176 vvij = sqrt(dot_product(vij,vij))
177 tij = vvij/params % rsph(jsph)
178
179 if ( tij.lt.( one + (params % se+one)/two*params % eta ) ) then
180 xij = fsw(tij, params % se, params % eta)
181 if (constants % fi(its,isph).gt.one) then
182 oij = xij/constants % fi(its, isph)
183 else
184 oij = xij
185 end if
186 vtij = vij*params % kappa
187 call fmm_l2p_bessel_work(vtij, &
188 & params % lmax, constants % vscales, &
189 & constants % SI_ri(:, jsph), oij, x(:, jsph), one, &
190 & pot(its), work_complex, work)
191 end if
192 end do
193 end if
194 end do
195endsubroutine calcv2_lpb
196
204subroutine convert_ddcosmo(params, constants, direction, vector)
205 !! Inputs
206 type(ddx_params_type), intent(in) :: params
207 type(ddx_constants_type), intent(in) :: constants
208 integer, intent(in) :: direction
209 !! Outputs
210 real(dp), intent(inout) :: vector(constants % nbasis, params % nsph)
211 !! Local variables
212 integer :: isph, l, m, ind
213 real(dp) :: fac
214 !! The code
215 do isph = 1, params % nsph
216 do l = 0, params % lmax
217 ind = l*l + l + 1
218 fac = fourpi / (two*dble(l) + one)
219 if (direction .eq. -1) fac = one / fac
220 do m = -l, l
221 vector(ind+m, isph) = fac*vector(ind+m, isph)
222 end do
223 end do
224 end do
225end subroutine convert_ddcosmo
226
227
239subroutine inthsp(params, constants, rijn, isph, basloc, fac_hsp, work)
240 implicit none
241 type(ddx_params_type), intent(in) :: params
242 type(ddx_constants_type), intent(in) :: constants
243 integer, intent(in) :: isph
244 real(dp), intent(in) :: rijn
245 real(dp), dimension(constants % nbasis), intent(in) :: basloc
246 real(dp), dimension(constants % nbasis), intent(inout) :: fac_hsp
247 complex(dp), intent(out) :: work(max(2, params % lmax+1))
248 real(dp), dimension(0:params % lmax) :: SI_rijn, DI_rijn
249 integer :: l, m, ind
250 si_rijn = 0
251 di_rijn = 0
252 fac_hsp = 0
253 ! Computation of modified spherical Bessel function values
254 call modified_spherical_bessel_first_kind(params % lmax, &
255 & rijn*params % kappa, si_rijn, di_rijn, work)
256 do l = 0, params % lmax
257 do m = -l, l
258 ind = l*l + l + 1 + m
259 fac_hsp(ind) = si_rijn(l)/constants % SI_ri(l,isph)*basloc(ind)
260 end do
261 end do
262endsubroutine inthsp
263
264
276subroutine adjrhs_lpb(params, constants, isph, xi, vlm, basloc, &
277 & vplm, vcos, vsin, tmp_bessel)
278 implicit none
279 !! input/output
280 type(ddx_params_type), intent(in) :: params
281 type(ddx_constants_type), intent(in) :: constants
282 real(dp), dimension(params % ngrid, params % nsph), intent(in) :: xi
283 real(dp), dimension((params % lmax+1)**2), intent(out) :: vlm
284 real(dp), dimension((params % lmax+1)**2), intent(out) :: basloc, vplm
285 real(dp), dimension(params % lmax+1), intent(out) :: vcos, vsin
286 complex(dp), dimension(max(2, params % lmax+1)), intent(out) :: tmp_bessel
287 integer, intent(in) :: isph
288 !! local
289 integer :: ij, jsph, ig, l, ind, m
290 real(dp) :: vji(3), vvji, tji, sji(3), xji, oji, fac
291 real(dp) :: rho, ctheta, stheta, cphi, sphi
292 real(dp), dimension(constants % nbasis) :: fac_hsp
293
294 !loop over neighbors of i-sphere
295 do ij = constants % inl(isph), constants % inl(isph+1)-1
296 !j-sphere is neighbor
297 jsph = constants % nl(ij)
298 !loop over integration points
299 do ig = 1, params % ngrid
300 !compute t_n^ji = | r_j + \rho_j s_n - r_i | / \rho_i
301 vji = params % csph(:,jsph) + params % rsph(jsph)* &
302 & constants % cgrid(:,ig) - params % csph(:,isph)
303 vvji = sqrt(dot_product(vji,vji))
304 tji = vvji/params % rsph(isph)
305 !point is INSIDE i-sphere (+ transition layer)
306 if ( tji.lt.( one + (params % se+one)/two*params % eta ) ) then
307 !compute s_n^ji
308 if (tji.ne.zero) then
309 sji = vji/vvji
310 else
311 sji = one
312 end if
313 call ylmbas(sji, rho, ctheta, stheta, cphi, &
314 & sphi, params % lmax, &
315 & constants % vscales, basloc, &
316 & vplm, vcos, vsin)
317 call inthsp_adj(params, constants, vvji, isph, basloc, fac_hsp, &
318 & tmp_bessel)
319 !compute \chi( t_n^ji )
320 xji = fsw( tji, params % se, params % eta )
321 !compute W_n^ji
322 if ( constants % fi(ig,jsph).gt.one ) then
323 oji = xji/ constants % fi(ig,jsph)
324 else
325 oji = xji
326 endif
327 !compute w_n * xi(n,j) * W_n^ji
328 fac = constants % wgrid(ig) * xi(ig,jsph) * oji
329 !loop over l
330 do l = 0, params % lmax
331 ind = l*l + l + 1
332 !loop over m
333 do m = -l,l
334 vlm(ind+m) = vlm(ind+m) + fac*fac_hsp(ind+m)
335 enddo
336 enddo
337 endif
338 enddo
339 enddo
340end subroutine adjrhs_lpb
341
342
352subroutine inthsp_adj(params, constants, rjin, jsph, basloc, &
353 & fac_hsp, work)
354 implicit none
355 !! Inputs
356 type(ddx_params_type), intent(in) :: params
357 type(ddx_constants_type), intent(in) :: constants
358 integer, intent(in) :: jsph
359 real(dp), intent(in) :: rjin
360 real(dp), dimension(constants % nbasis), intent(in) :: basloc
361 real(dp), dimension(constants % nbasis), intent(inout) :: fac_hsp
362 complex(dp), intent(out) :: work(max(2, params % lmax+1))
363 real(dp), dimension(0:params % lmax) :: SI_rjin, DI_rjin
364 integer :: l, m, ind
365
366 si_rjin = 0
367 di_rjin = 0
368 fac_hsp = 0
369
370 ! Computation of modified spherical Bessel function values
371 call modified_spherical_bessel_first_kind(params % lmax, &
372 & rjin*params % kappa, si_rjin, di_rjin, work)
373
374 do l = 0, params % lmax
375 do m = -l, l
376 ind = l*l + l + 1 + m
377 fac_hsp(ind) = si_rjin(l)/constants % SI_ri(l,jsph)*basloc(ind)
378 end do
379 end do
380endsubroutine inthsp_adj
381end module ddx_lpb_core
Core routines and parameters of the ddX software.
Definition: ddx_core.f90:13
subroutine tree_l2p_bessel(params, constants, alpha, node_l, beta, grid_v)
TODO.
Definition: ddx_core.f90:2291
subroutine tree_m2l_bessel_rotation(params, constants, node_m, node_l)
Transfer multipole local coefficients into local over a tree.
Definition: ddx_core.f90:2095
subroutine tree_m2p_bessel(params, constants, p, alpha, sph_p, sph_m, beta, grid_v)
TODO.
Definition: ddx_core.f90:2451
subroutine tree_l2l_bessel_rotation(params, constants, node_l)
Transfer local coefficients over a tree.
Definition: ddx_core.f90:1913
subroutine tree_m2m_bessel_rotation(params, constants, node_m)
Transfer multipole coefficients over a tree.
Definition: ddx_core.f90:1717
Core routines and parameters specific to ddLPB.