ddx 1.0.2
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 integer :: its, ij, jsph
163 real(dp) :: vij(3), vtij(3)
164 real(dp) :: vvij, tij, xij, oij, thigh
165 thigh = one + (params % se+one)/two*params % eta
166 pot = zero
167 if (params%switching.eq.0) then
168 do its = 1, params % ngrid
169 if (constants % ui(its,isph).lt.one) then
170 do ij = constants % inl(isph), constants % inl(isph+1)-1
171 jsph = constants % nl(ij)
172
173 ! compute geometrical variables
174 vij = params % csph(:,isph) + params % rsph(isph) &
175 & *constants % cgrid(:,its) - params % csph(:,jsph)
176 vvij = sqrt(dot_product(vij,vij))
177 tij = vvij/params % rsph(jsph)
178
179 if (tij.lt.thigh) 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
195 else
196 ! loop over grid points
197 do its = 1, params % ngrid
198 ! contribution from integration point present
199 if (constants%ui(its,isph).lt.one) then
200 d_i = constants%switching%d_ni(its,isph)
201 f_i = constants%switching%f_ni(its,isph)
202 ! loop over neighbors of i-sphere
203 do ij = constants % inl(isph), constants % inl(isph+1)-1
204 jsph = constants % nl(ij)
205
206 vij = params % csph(:,isph) + params % rsph(isph)* &
207 & constants % cgrid(:,its) - params % csph(:,jsph)
208 vvij = sqrt(vij(1)*vij(1) + vij(2)*vij(2) + vij(3)*vij(3))
209 tij = vvij / params % rsph(jsph)
210
211 if (tij.lt.thigh) then
212 xij = fsw(tij, params % se, params % eta)
213 oij = xij/(d_i + f_i)
214 vtij = vij*params % kappa
215 call fmm_l2p_bessel_work(vtij, &
216 & params % lmax, constants % vscales, &
217 & constants % SI_ri(:, jsph), oij, x(:, jsph), one, &
218 & pot(its), work_complex, work)
219 end if
220 end do
221 end if
222 end do
223 end if
224end subroutine calcv2_lpb
225
233subroutine convert_ddcosmo(params, constants, direction, vector)
234 !! Inputs
235 type(ddx_params_type), intent(in) :: params
236 type(ddx_constants_type), intent(in) :: constants
237 integer, intent(in) :: direction
238 !! Outputs
239 real(dp), intent(inout) :: vector(constants % nbasis, params % nsph)
240 !! Local variables
241 integer :: isph, l, m, ind
242 real(dp) :: fac
243 !! The code
244 do isph = 1, params % nsph
245 do l = 0, params % lmax
246 ind = l*l + l + 1
247 fac = fourpi / (two*dble(l) + one)
248 if (direction .eq. -1) fac = one / fac
249 do m = -l, l
250 vector(ind+m, isph) = fac*vector(ind+m, isph)
251 end do
252 end do
253 end do
254end subroutine convert_ddcosmo
255
256
268subroutine inthsp(params, constants, rijn, isph, basloc, fac_hsp, work)
269 implicit none
270 type(ddx_params_type), intent(in) :: params
271 type(ddx_constants_type), intent(in) :: constants
272 integer, intent(in) :: isph
273 real(dp), intent(in) :: rijn
274 real(dp), dimension(constants % nbasis), intent(in) :: basloc
275 real(dp), dimension(constants % nbasis), intent(inout) :: fac_hsp
276 complex(dp), intent(out) :: work(max(2, params % lmax+1))
277 real(dp), dimension(0:params % lmax) :: SI_rijn, DI_rijn
278 integer :: l, m, ind
279 si_rijn = 0
280 di_rijn = 0
281 fac_hsp = 0
282 ! Computation of modified spherical Bessel function values
283 call modified_spherical_bessel_first_kind(params % lmax, &
284 & rijn*params % kappa, si_rijn, di_rijn, work)
285 do l = 0, params % lmax
286 do m = -l, l
287 ind = l*l + l + 1 + m
288 fac_hsp(ind) = si_rijn(l)/constants % SI_ri(l,isph)*basloc(ind)
289 end do
290 end do
291endsubroutine inthsp
292
293
305subroutine adjrhs_lpb(params, constants, isph, xi, vlm, basloc, &
306 & vplm, vcos, vsin, tmp_bessel)
307 implicit none
308 !! input/output
309 type(ddx_params_type), intent(in) :: params
310 type(ddx_constants_type), intent(in) :: constants
311 real(dp), dimension(params % ngrid, params % nsph), intent(in) :: xi
312 real(dp), dimension((params % lmax+1)**2), intent(out) :: vlm
313 real(dp), dimension((params % lmax+1)**2), intent(out) :: basloc, vplm
314 real(dp), dimension(params % lmax+1), intent(out) :: vcos, vsin
315 complex(dp), dimension(max(2, params % lmax+1)), intent(out) :: tmp_bessel
316 integer, intent(in) :: isph
317 !! local
318 integer :: ij, jsph, ig, l, ind, m
319 real(dp) :: vji(3), vvji, tji, sji(3), xji, oji, fac
320 real(dp) :: rho, ctheta, stheta, cphi, sphi
321 real(dp), dimension(constants % nbasis) :: fac_hsp
322 real(dp) :: thigh, d_j, f_j
323 thigh = one + (params % se+one)/two*params % eta
324
325 if (params%switching.eq.0) then
326 !loop over neighbors of i-sphere
327 do ij = constants % inl(isph), constants % inl(isph+1)-1
328 !j-sphere is neighbor
329 jsph = constants % nl(ij)
330 !loop over integration points
331 do ig = 1, params % ngrid
332 !compute t_n^ji = | r_j + \rho_j s_n - r_i | / \rho_i
333 vji = params % csph(:,jsph) + params % rsph(jsph)* &
334 & constants % cgrid(:,ig) - params % csph(:,isph)
335 vvji = sqrt(dot_product(vji,vji))
336 tji = vvji/params % rsph(isph)
337 !point is INSIDE i-sphere (+ transition layer)
338 if (tji.lt.thigh) then
339 !compute s_n^ji
340 if (tji.ne.zero) then
341 sji = vji/vvji
342 else
343 sji = one
344 end if
345 call ylmbas(sji, rho, ctheta, stheta, cphi, &
346 & sphi, params % lmax, &
347 & constants % vscales, basloc, &
348 & vplm, vcos, vsin)
349 call inthsp_adj(params, constants, vvji, isph, basloc, fac_hsp, &
350 & tmp_bessel)
351 !compute \chi( t_n^ji )
352 xji = fsw(tji, params % se, params % eta)
353 !compute W_n^ji
354 if ( constants % fi(ig,jsph).gt.one ) then
355 oji = xji/ constants % fi(ig,jsph)
356 else
357 oji = xji
358 end if
359 !compute w_n * xi(n,j) * W_n^ji
360 fac = constants % wgrid(ig) * xi(ig,jsph) * oji
361 !loop over l
362 do l = 0, params % lmax
363 ind = l*l + l + 1
364 !loop over m
365 do m = -l,l
366 vlm(ind+m) = vlm(ind+m) + fac*fac_hsp(ind+m)
367 end do
368 end do
369 end if
370 end do
371 end do
372 else
373 do ij = constants % inl(isph), constants % inl(isph+1)-1
374 jsph = constants % nl(ij)
375 do ig = 1, params % ngrid
376 vji = params % csph(:,jsph) + params % rsph(jsph)* &
377 & constants % cgrid(:,ig) - params % csph(:,isph)
378 vvji = sqrt(dot_product(vji,vji))
379 tji = vvji/params % rsph(isph)
380 if (tji.lt.thigh) then
381 if (tji.ne.zero) then
382 sji = vji/vvji
383 else
384 sji = one
385 end if
386
387 call ylmbas(sji, rho, ctheta, stheta, cphi, &
388 & sphi, params % lmax, &
389 & constants % vscales, basloc, &
390 & vplm, vcos, vsin)
391 call inthsp_adj(params, constants, vvji, isph, &
392 & basloc, fac_hsp, tmp_bessel)
393
394 d_j = constants%switching%d_ni(ig,jsph)
395 f_j = constants%switching%f_ni(ig,jsph)
396 xji = fsw(tji, params % se, params % eta)
397 oji = xji/(d_j+f_j)
398
399 fac = constants % wgrid(ig) * xi(ig,jsph) * oji
400 do l = 0, params % lmax
401 ind = l*l + l + 1
402 do m = -l,l
403 vlm(ind+m) = vlm(ind+m) + fac*fac_hsp(ind+m)
404 end do
405 end do
406 end if
407 end do
408 end do
409 end if
410end subroutine adjrhs_lpb
411
412
422subroutine inthsp_adj(params, constants, rjin, jsph, basloc, &
423 & fac_hsp, work)
424 implicit none
425 !! Inputs
426 type(ddx_params_type), intent(in) :: params
427 type(ddx_constants_type), intent(in) :: constants
428 integer, intent(in) :: jsph
429 real(dp), intent(in) :: rjin
430 real(dp), dimension(constants % nbasis), intent(in) :: basloc
431 real(dp), dimension(constants % nbasis), intent(inout) :: fac_hsp
432 complex(dp), intent(out) :: work(max(2, params % lmax+1))
433 real(dp), dimension(0:params % lmax) :: SI_rjin, DI_rjin
434 integer :: l, m, ind
435
436 si_rjin = 0
437 di_rjin = 0
438 fac_hsp = 0
439
440 ! Computation of modified spherical Bessel function values
441 call modified_spherical_bessel_first_kind(params % lmax, &
442 & rjin*params % kappa, si_rjin, di_rjin, work)
443
444 do l = 0, params % lmax
445 do m = -l, l
446 ind = l*l + l + 1 + m
447 fac_hsp(ind) = si_rjin(l)/constants % SI_ri(l,jsph)*basloc(ind)
448 end do
449 end do
450endsubroutine inthsp_adj
451end 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:2362
subroutine tree_m2l_bessel_rotation(params, constants, node_m, node_l)
Transfer multipole local coefficients into local over a tree.
Definition: ddx_core.f90:2166
subroutine tree_m2p_bessel(params, constants, p, alpha, sph_p, sph_m, beta, grid_v)
TODO.
Definition: ddx_core.f90:2522
subroutine tree_l2l_bessel_rotation(params, constants, node_l)
Transfer local coefficients over a tree.
Definition: ddx_core.f90:1984
subroutine tree_m2m_bessel_rotation(params, constants, node_m)
Transfer multipole coefficients over a tree.
Definition: ddx_core.f90:1788
Core routines and parameters specific to ddLPB.