34 #include "./base/base_uses.f90"
38 LOGICAL,
PRIVATE,
PARAMETER :: debug_this_module = .false.
39 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'cp_ddapc_methods'
62 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: gfunc
63 REAL(kind=
dp),
DIMENSION(:),
POINTER :: w
64 REAL(kind=
dp),
INTENT(IN) :: gcut
65 TYPE(pw_c1d_gs_type),
INTENT(IN) :: rho_tot_g
66 REAL(kind=
dp),
DIMENSION(:),
POINTER :: radii
68 CHARACTER(len=*),
PARAMETER :: routinen =
'ddapc_eval_gfunc'
70 INTEGER :: e_dim, handle, ig, igauss, s_dim
71 REAL(kind=
dp) :: g2, gcut2, rc, rc2
73 CALL timeset(routinen, handle)
76 s_dim = rho_tot_g%pw_grid%first_gne0
77 e_dim = rho_tot_g%pw_grid%ngpts_cut_local
78 ALLOCATE (gfunc(s_dim:e_dim,
SIZE(radii)))
79 ALLOCATE (w(s_dim:e_dim))
82 DO igauss = 1,
SIZE(radii)
86 g2 = rho_tot_g%pw_grid%gsq(ig)
88 gfunc(ig, igauss) = exp(-g2*rc2/4.0_dp)
92 g2 = rho_tot_g%pw_grid%gsq(ig)
94 w(ig) =
fourpi*(g2 - gcut2)**2/(g2*gcut2)
113 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: bv
114 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: gfunc
115 REAL(kind=
dp),
DIMENSION(:),
POINTER :: w
116 TYPE(particle_type),
DIMENSION(:),
POINTER :: particle_set
117 REAL(kind=
dp),
DIMENSION(:),
POINTER :: radii
118 TYPE(pw_c1d_gs_type),
INTENT(IN) :: rho_tot_g
119 REAL(kind=
dp),
INTENT(IN) :: gcut
121 CHARACTER(len=*),
PARAMETER :: routinen =
'build_b_vector'
123 COMPLEX(KIND=dp) :: phase
124 INTEGER :: e_dim, handle, idim, ig, igauss, igmax, &
126 REAL(kind=
dp) :: arg, g2, gcut2, gvec(3), rvec(3)
127 REAL(kind=
dp),
DIMENSION(:),
POINTER :: my_bv, my_bvw
129 CALL timeset(routinen, handle)
130 NULLIFY (my_bv, my_bvw)
132 s_dim = rho_tot_g%pw_grid%first_gne0
133 e_dim = rho_tot_g%pw_grid%ngpts_cut_local
136 g2 = rho_tot_g%pw_grid%gsq(ig)
140 IF (igmax .GE. s_dim)
THEN
141 ALLOCATE (my_bv(s_dim:igmax))
142 ALLOCATE (my_bvw(s_dim:igmax))
144 DO iparticle = 1,
SIZE(particle_set)
145 rvec = particle_set(iparticle)%r
148 gvec = rho_tot_g%pw_grid%g(:, ig)
149 arg = dot_product(gvec, rvec)
150 phase = cmplx(cos(arg), -sin(arg), kind=
dp)
151 my_bv(ig) = w(ig)*real(conjg(rho_tot_g%array(ig))*phase, kind=
dp)
153 DO igauss = 1,
SIZE(radii)
154 idim = (iparticle - 1)*
SIZE(radii) + igauss
156 my_bvw(ig) = my_bv(ig)*gfunc(ig, igauss)
158 bv(idim) = accurate_sum(my_bvw)
164 DO iparticle = 1,
SIZE(particle_set)
165 DO igauss = 1,
SIZE(radii)
166 idim = (iparticle - 1)*
SIZE(radii) + igauss
171 CALL timestop(handle)
190 SUBROUTINE build_a_matrix(Am, gfunc, w, particle_set, radii, rho_tot_g, gcut, g_dot_rvec_sin, g_dot_rvec_cos)
191 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: am
192 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: gfunc
193 REAL(kind=
dp),
DIMENSION(:),
POINTER :: w
194 TYPE(particle_type),
DIMENSION(:),
POINTER :: particle_set
195 REAL(kind=
dp),
DIMENSION(:),
POINTER :: radii
196 TYPE(pw_c1d_gs_type),
INTENT(IN) :: rho_tot_g
197 REAL(kind=
dp),
INTENT(IN) :: gcut
198 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: g_dot_rvec_sin, g_dot_rvec_cos
200 CHARACTER(len=*),
PARAMETER :: routinen =
'build_A_matrix'
202 INTEGER :: e_dim, handle, idim1, idim2, ig, &
203 igauss1, igauss2, igmax, iparticle1, &
204 iparticle2, istart_g, s_dim
205 REAL(kind=
dp) :: g2, gcut2, tmp
206 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: my_am, my_amw
207 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: gfunc_sq(:, :, :)
211 CALL timeset(routinen, handle)
213 s_dim = rho_tot_g%pw_grid%first_gne0
214 e_dim = rho_tot_g%pw_grid%ngpts_cut_local
217 g2 = rho_tot_g%pw_grid%gsq(ig)
221 IF (igmax .GE. s_dim)
THEN
222 ALLOCATE (my_am(s_dim:igmax))
223 ALLOCATE (my_amw(s_dim:igmax))
224 ALLOCATE (gfunc_sq(s_dim:igmax,
SIZE(radii),
SIZE(radii)))
226 DO igauss1 = 1,
SIZE(radii)
227 DO igauss2 = 1,
SIZE(radii)
228 gfunc_sq(s_dim:igmax, igauss1, igauss2) = w(s_dim:igmax)*gfunc(s_dim:igmax, igauss1)*gfunc(s_dim:igmax, igauss2)
232 DO iparticle1 = 1,
SIZE(particle_set)
233 DO iparticle2 = iparticle1,
SIZE(particle_set)
236 my_am(ig) = (g_dot_rvec_cos(ig - s_dim + 1, iparticle1)*g_dot_rvec_cos(ig - s_dim + 1, iparticle2) + &
237 g_dot_rvec_sin(ig - s_dim + 1, iparticle1)*g_dot_rvec_sin(ig - s_dim + 1, iparticle2))
239 DO igauss1 = 1,
SIZE(radii)
240 idim1 = (iparticle1 - 1)*
SIZE(radii) + igauss1
242 IF (iparticle2 == iparticle1) istart_g = igauss1
243 DO igauss2 = istart_g,
SIZE(radii)
244 idim2 = (iparticle2 - 1)*
SIZE(radii) + igauss2
245 my_amw(s_dim:igmax) = my_am(s_dim:igmax)*gfunc_sq(s_dim:igmax, igauss1, igauss2)
249 am(idim2, idim1) = tmp
250 am(idim1, idim2) = tmp
255 DEALLOCATE (gfunc_sq)
259 CALL timestop(handle)
277 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: dbv
278 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: gfunc
279 REAL(kind=
dp),
DIMENSION(:),
POINTER :: w
280 TYPE(particle_type),
DIMENSION(:),
POINTER :: particle_set
281 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: radii
282 TYPE(pw_c1d_gs_type),
INTENT(IN) :: rho_tot_g
283 REAL(kind=
dp),
INTENT(IN) :: gcut
284 INTEGER,
INTENT(IN) :: iparticle0
286 CHARACTER(len=*),
PARAMETER :: routinen =
'build_der_b_vector'
288 COMPLEX(KIND=dp) :: dphase
289 INTEGER :: e_dim, handle, idim, ig, igauss, igmax, &
291 REAL(kind=
dp) :: arg, g2, gcut2
292 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: my_dbvw
293 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: my_dbv
294 REAL(kind=
dp),
DIMENSION(3) :: gvec, rvec
296 CALL timeset(routinen, handle)
298 s_dim = rho_tot_g%pw_grid%first_gne0
299 e_dim = rho_tot_g%pw_grid%ngpts_cut_local
302 g2 = rho_tot_g%pw_grid%gsq(ig)
306 IF (igmax .GE. s_dim)
THEN
307 ALLOCATE (my_dbv(3, s_dim:igmax))
308 ALLOCATE (my_dbvw(s_dim:igmax))
309 DO iparticle = 1,
SIZE(particle_set)
310 IF (iparticle /= iparticle0) cycle
311 rvec = particle_set(iparticle)%r
313 gvec = rho_tot_g%pw_grid%g(:, ig)
314 arg = dot_product(gvec, rvec)
315 dphase = -cmplx(sin(arg), cos(arg), kind=
dp)
316 my_dbv(:, ig) = w(ig)*real(conjg(rho_tot_g%array(ig))*dphase, kind=
dp)*gvec(:)
318 DO igauss = 1,
SIZE(radii)
319 idim = (iparticle - 1)*
SIZE(radii) + igauss
321 my_dbvw(ig) = my_dbv(1, ig)*gfunc(ig, igauss)
323 dbv(idim, 1) = accurate_sum(my_dbvw)
325 my_dbvw(ig) = my_dbv(2, ig)*gfunc(ig, igauss)
327 dbv(idim, 2) = accurate_sum(my_dbvw)
329 my_dbvw(ig) = my_dbv(3, ig)*gfunc(ig, igauss)
331 dbv(idim, 3) = accurate_sum(my_dbvw)
337 DO iparticle = 1,
SIZE(particle_set)
338 IF (iparticle /= iparticle0) cycle
339 DO igauss = 1,
SIZE(radii)
340 idim = (iparticle - 1)*
SIZE(radii) + igauss
341 dbv(idim, 1:3) = 0.0_dp
345 CALL timestop(handle)
368 rho_tot_g, gcut, iparticle0, nparticles, g_dot_rvec_sin, g_dot_rvec_cos)
369 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(INOUT) :: dam
370 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: gfunc
371 REAL(kind=
dp),
DIMENSION(:),
POINTER :: w
372 TYPE(particle_type),
DIMENSION(:),
POINTER :: particle_set
373 REAL(kind=
dp),
DIMENSION(:),
POINTER :: radii
374 TYPE(pw_c1d_gs_type),
INTENT(IN) :: rho_tot_g
375 REAL(kind=
dp),
INTENT(IN) :: gcut
376 INTEGER,
INTENT(IN) :: iparticle0, nparticles
377 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: g_dot_rvec_sin, g_dot_rvec_cos
379 CHARACTER(len=*),
PARAMETER :: routinen =
'build_der_A_matrix_rows'
381 INTEGER :: e_dim, handle, ig, igauss2, igmax, &
382 iparticle1, iparticle2, s_dim
383 REAL(kind=
dp) :: g2, gcut2
389 REAL(kind=
dp),
ALLOCATABLE :: lhs(:, :), rhs(:, :)
390 INTEGER :: nr, np, ng, icomp, ipp
392 CALL timeset(routinen, handle)
394 s_dim = rho_tot_g%pw_grid%first_gne0
395 e_dim = rho_tot_g%pw_grid%ngpts_cut_local
398 g2 = rho_tot_g%pw_grid%gsq(ig)
404 np =
SIZE(particle_set)
405 ng = igmax - s_dim + 1
406 IF (igmax .GE. s_dim)
THEN
407 ALLOCATE (lhs(nparticles*nr, ng))
408 ALLOCATE (rhs(ng, np*nr))
412 DO iparticle2 = 1, np
414 rhs(1:ng, (iparticle2 - 1)*nr + igauss2) = g_dot_rvec_sin(1:ng, iparticle2)*gfunc(s_dim:igmax, igauss2)
419 DO ipp = 1, nparticles
420 iparticle1 = iparticle0 + ipp - 1
422 lhs((ipp - 1)*nr + 1:(ipp - 1)*nr + nr, ig - s_dim + 1) = w(ig)*rho_tot_g%pw_grid%g(icomp, ig)* &
423 gfunc(ig, 1:nr)*g_dot_rvec_cos(ig - s_dim + 1, iparticle1)
427 CALL dgemm(
'N',
'N', nparticles*nr, np*nr, ng, 1.0d0, lhs(1, 1), nparticles*nr, rhs(1, 1), &
428 ng, 0.0d0, dam((iparticle0 - 1)*nr + 1, 1, icomp), np*nr)
430 DO ipp = 1, nparticles
431 iparticle1 = iparticle0 + ipp - 1
432 CALL dgemm(
'N',
'N', nr, nr, ng, 1.0d0, lhs((ipp - 1)*nr + 1, 1), nparticles*nr, rhs(1, (iparticle1 - 1)*nr + 1), &
433 ng, 1.0d0, dam((iparticle1 - 1)*nr + 1, (iparticle1 - 1)*nr + 1, icomp), np*nr)
440 DO iparticle2 = 1, np
442 rhs(1:ng, (iparticle2 - 1)*nr + igauss2) = -g_dot_rvec_cos(1:ng, iparticle2)*gfunc(s_dim:igmax, igauss2)
447 DO ipp = 1, nparticles
448 iparticle1 = iparticle0 + ipp - 1
450 lhs((ipp - 1)*nr + 1:(ipp - 1)*nr + nr, ig - s_dim + 1) = w(ig)*rho_tot_g%pw_grid%g(icomp, ig)*gfunc(ig, 1:nr)* &
451 g_dot_rvec_sin(ig - s_dim + 1, iparticle1)
455 CALL dgemm(
'N',
'N', nparticles*nr, np*nr, ng, 1.0d0, lhs(1, 1), nparticles*nr, rhs(1, 1), &
456 ng, 1.0d0, dam((iparticle0 - 1)*nr + 1, 1, icomp), np*nr)
458 DO ipp = 1, nparticles
459 iparticle1 = iparticle0 + ipp - 1
460 CALL dgemm(
'N',
'N', nr, nr, ng, 1.0d0, lhs((ipp - 1)*nr + 1, 1), nparticles*nr, rhs(1, (iparticle1 - 1)*nr + 1), &
461 ng, 1.0d0, dam((iparticle1 - 1)*nr + 1, (iparticle1 - 1)*nr + 1, icomp), np*nr)
468 CALL timestop(handle)
477 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: g_dot_rvec_sin, g_dot_rvec_cos
479 IF (
ALLOCATED(g_dot_rvec_sin))
DEALLOCATE (g_dot_rvec_sin)
480 IF (
ALLOCATED(g_dot_rvec_cos))
DEALLOCATE (g_dot_rvec_cos)
492 TYPE(pw_c1d_gs_type),
INTENT(IN) :: rho_tot_g
493 TYPE(particle_type),
DIMENSION(:),
POINTER :: particle_set
494 REAL(kind=
dp),
INTENT(IN) :: gcut
495 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: g_dot_rvec_sin, g_dot_rvec_cos
497 INTEGER :: e_dim, ig, igmax, iparticle, s_dim
498 REAL(kind=
dp) :: g2, g_dot_rvec, gcut2, rvec(3)
501 s_dim = rho_tot_g%pw_grid%first_gne0
502 e_dim = rho_tot_g%pw_grid%ngpts_cut_local
505 g2 = rho_tot_g%pw_grid%gsq(ig)
510 IF (igmax .GE. s_dim)
THEN
511 ALLOCATE (g_dot_rvec_sin(1:igmax - s_dim + 1,
SIZE(particle_set)))
512 ALLOCATE (g_dot_rvec_cos(1:igmax - s_dim + 1,
SIZE(particle_set)))
514 DO iparticle = 1,
SIZE(particle_set)
515 rvec = particle_set(iparticle)%r
517 g_dot_rvec = dot_product(rho_tot_g%pw_grid%g(:, ig), rvec)
518 g_dot_rvec_sin(ig - s_dim + 1, iparticle) = sin(g_dot_rvec)
519 g_dot_rvec_cos(ig - s_dim + 1, iparticle) = cos(g_dot_rvec)
543 rho_tot_g, radii, iw, Vol)
544 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: gami
545 REAL(kind=
dp),
INTENT(OUT) :: c0
546 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: gfunc
547 REAL(kind=
dp),
DIMENSION(:),
POINTER :: w
548 TYPE(particle_type),
DIMENSION(:),
POINTER :: particle_set
549 REAL(kind=
dp),
INTENT(IN) :: gcut
550 TYPE(pw_c1d_gs_type),
INTENT(IN) :: rho_tot_g
551 REAL(kind=
dp),
DIMENSION(:),
POINTER :: radii
552 INTEGER,
INTENT(IN) :: iw
553 REAL(kind=
dp),
INTENT(IN) :: vol
555 CHARACTER(len=*),
PARAMETER :: routinen =
'ddapc_eval_AmI'
557 INTEGER :: handle, ndim
558 REAL(kind=
dp) :: condition_number, inv_error
559 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: ame, cv
560 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: am, ami, amw, g_dot_rvec_cos, &
565 CALL timeset(routinen, handle)
566 ndim =
SIZE(particle_set)*
SIZE(radii)
567 ALLOCATE (am(ndim, ndim))
568 ALLOCATE (ami(ndim, ndim))
569 ALLOCATE (gami(ndim, ndim))
576 CALL build_a_matrix(am, gfunc, w, particle_set, radii, rho_tot_g, gcut, g_dot_rvec_sin, g_dot_rvec_cos)
578 am(:, :) = am(:, :)/(vol*vol)
579 CALL rho_tot_g%pw_grid%para%group%sum(am)
582 ALLOCATE (amw(ndim, ndim))
586 condition_number = maxval(abs(ame))/minval(abs(ame))
587 WRITE (iw,
'(T3,A)')
" Eigenvalues of Matrix A:"
588 WRITE (iw,
'(T3,4E15.8)') ame
589 WRITE (iw,
'(T3,A,1E15.9)')
" Condition number:", condition_number
590 IF (condition_number > 1.0e12_dp)
THEN
591 WRITE (iw, fmt=
"(/,T2,A)") &
592 "WARNING: high condition number => possibly ill-conditioned matrix"
597 CALL invert_matrix(am, ami, inv_error,
"N", improve=.false.)
599 WRITE (iw,
'(T3,A,F15.9)')
" Error inverting the A matrix: ", inv_error
601 c0 = dot_product(cv, matmul(ami, cv))
606 CALL timestop(handle)
625 RECURSIVE SUBROUTINE ewald_ddapc_pot(cp_para_env, coeff, factor, cell, multipole_section, &
626 particle_set, M, radii)
627 TYPE(mp_para_env_type),
INTENT(IN) :: cp_para_env
628 TYPE(pw_r3d_rs_type),
INTENT(IN),
POINTER :: coeff
629 REAL(kind=
dp),
INTENT(IN) :: factor
630 TYPE(cell_type),
POINTER :: cell
631 TYPE(section_vals_type),
POINTER :: multipole_section
632 TYPE(particle_type),
DIMENSION(:),
POINTER :: particle_set
633 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: m
634 REAL(kind=
dp),
DIMENSION(:),
POINTER :: radii
636 CHARACTER(len=*),
PARAMETER :: routinen =
'ewald_ddapc_pot'
638 INTEGER :: ewmdim, handle, idim, idim1, idim2, idimo, igauss1, igauss2, ip1, ip2, &
639 iparticle1, iparticle2, istart_g, k1, k2, k3, n_rep, ndim, nmax1, nmax2, nmax3, r1, r2, &
640 r3, rmax1, rmax2, rmax3
642 REAL(kind=
dp) :: alpha, eps, ew_neut,
fac, fac3, fs, g_ewald, galpha, gsq, gsqi, ij_fac, &
643 my_val, r, r2tmp, r_ewald, rc1, rc12, rc2, rc22, rcut, rcut2, t1, tol, tol1
644 REAL(kind=
dp),
DIMENSION(3) :: fvec, gvec, ra, rvec
645 REAL(kind=
dp),
DIMENSION(:),
POINTER :: ewm
648 CALL timeset(routinen, handle)
649 cpassert(.NOT.
ASSOCIATED(m))
650 cpassert(
ASSOCIATED(radii))
651 cpassert(cell%orthorhombic)
652 rcut = min(cell%hmat(1, 1), cell%hmat(2, 2), cell%hmat(3, 3))/2.0_dp
661 eps = min(abs(eps), 0.5_dp)
662 tol = sqrt(abs(log(eps*rcut)))
663 alpha = sqrt(abs(log(eps*rcut*tol)))/rcut
664 galpha = 1.0_dp/(4.0_dp*alpha*alpha)
665 tol1 = sqrt(-log(eps*rcut*(2.0_dp*tol*alpha)**2))
666 nmax1 = nint(0.25_dp + cell%hmat(1, 1)*alpha*tol1/
pi)
667 nmax2 = nint(0.25_dp + cell%hmat(2, 2)*alpha*tol1/
pi)
668 nmax3 = nint(0.25_dp + cell%hmat(3, 3)*alpha*tol1/
pi)
670 rmax1 = ceiling(rcut/cell%hmat(1, 1))
671 rmax2 = ceiling(rcut/cell%hmat(2, 2))
672 rmax3 = ceiling(rcut/cell%hmat(3, 3))
673 fac = 1.e0_dp/cell%deth
675 fvec =
twopi/(/cell%hmat(1, 1), cell%hmat(2, 2), cell%hmat(3, 3)/)
676 ew_neut = -
fac*
pi/alpha**2
678 ewmdim =
SIZE(particle_set)*(
SIZE(particle_set) + 1)/2
679 ndim =
SIZE(particle_set)*
SIZE(radii)
680 ALLOCATE (ewm(ewmdim))
681 ALLOCATE (m(ndim, ndim))
686 DO iparticle1 = 1,
SIZE(particle_set)
687 ip1 = (iparticle1 - 1)*
SIZE(radii)
688 DO iparticle2 = 1, iparticle1
690 IF (iparticle1 == iparticle2) ij_fac = 0.5_dp
692 ip2 = (iparticle2 - 1)*
SIZE(radii)
695 IF (mod(iparticle1, cp_para_env%num_pe) /= cp_para_env%mepos) cycle
700 rvec = particle_set(iparticle1)%r - particle_set(iparticle2)%r
702 IF (iparticle1 /= iparticle2)
THEN
704 r2tmp = dot_product(ra, ra)
705 IF (r2tmp <= rcut2)
THEN
711 DO r1 = -rmax1, rmax1
712 DO r2 = -rmax2, rmax2
713 DO r3 = -rmax3, rmax3
714 IF ((r1 == 0) .AND. (r2 == 0) .AND. (r3 == 0)) cycle
715 ra(1) = rvec(1) + cell%hmat(1, 1)*r1
716 ra(2) = rvec(2) + cell%hmat(2, 2)*r2
717 ra(3) = rvec(3) + cell%hmat(3, 3)*r3
718 r2tmp = dot_product(ra, ra)
719 IF (r2tmp <= rcut2)
THEN
722 r_ewald = r_ewald + t1*ij_fac
733 DO k2 = -nmax2, nmax2
734 DO k3 = -nmax3, nmax3
735 IF (k1 == 0 .AND. k2 == 0 .AND. k3 == 0) cycle
736 fs = 2.0_dp;
IF (k1 == 0) fs = 1.0_dp
737 gvec = fvec*(/real(k1, kind=
dp), real(k2, kind=
dp), real(k3, kind=
dp)/)
738 gsq = dot_product(gvec, gvec)
740 t1 =
fac*gsqi*exp(-galpha*gsq)
741 g_ewald = g_ewald + t1*cos(dot_product(gvec, rvec))
751 g_ewald = r_ewald +
fourpi*g_ewald
755 IF (iparticle1 == iparticle2)
THEN
756 g_ewald = g_ewald - 2.0_dp*alpha*
oorootpi
759 IF (iparticle1 /= iparticle2)
THEN
761 r = sqrt(dot_product(ra, ra))
764 ewm(idim) = my_val - factor*g_ewald
768 CALL cp_para_env%sum(ewm)
770 DO iparticle2 = 1,
SIZE(particle_set)
771 ip2 = (iparticle2 - 1)*
SIZE(radii)
772 idimo = (iparticle2 - 1)
773 idimo = idimo*(idimo + 1)/2
774 DO igauss2 = 1,
SIZE(radii)
775 idim2 = ip2 + igauss2
778 DO iparticle1 = 1, iparticle2
779 ip1 = (iparticle1 - 1)*
SIZE(radii)
780 idim = idimo + iparticle1
782 IF (iparticle1 == iparticle2) istart_g = igauss2
783 DO igauss1 = istart_g,
SIZE(radii)
784 idim1 = ip1 + igauss1
787 m(idim1, idim2) = ewm(idim) - factor*ew_neut - factor*fac3*(rc12 + rc22)
788 m(idim2, idim1) = m(idim1, idim2)
794 CALL timestop(handle)
809 TYPE(section_vals_type),
POINTER :: solvation_section
810 TYPE(particle_type),
DIMENSION(:),
POINTER :: particle_set
811 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: m
812 REAL(kind=
dp),
DIMENSION(:),
POINTER :: radii
814 INTEGER :: i, idim, idim1, idim2, igauss1, igauss2, ip1, ip2, iparticle1, iparticle2, &
815 istart_g, j, l, lmax, n_rep1, n_rep2, ndim, output_unit, weight
816 INTEGER,
DIMENSION(:),
POINTER ::
list
817 LOGICAL :: fixed_center
818 REAL(kind=
dp) :: center(3), eps_in, eps_out, factor, &
819 mass, mycos, r1, r2, rs, rvec(3)
820 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pos, r0
821 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: cost, locp
823 fixed_center = .false.
825 ndim =
SIZE(particle_set)*
SIZE(radii)
826 ALLOCATE (m(ndim, ndim))
833 IF (n_rep1 /= 0)
THEN
839 IF (n_rep2 /= 0)
THEN
847 r0 = r0 + particle_set(
list(i))%r
849 r0 = r0/real(
SIZE(
list), kind=
dp)
854 r0 = r0 + particle_set(
list(i))%r*particle_set(
list(i))%atomic_kind%mass
855 mass = mass + particle_set(
list(i))%atomic_kind%mass
861 IF (fixed_center)
THEN
869 cpassert(n_rep1 /= 0 .OR. n_rep2 /= 0)
871 ALLOCATE (locp(0:lmax,
SIZE(particle_set)))
872 ALLOCATE (pos(
SIZE(particle_set)))
873 ALLOCATE (cost(
SIZE(particle_set),
SIZE(particle_set)))
875 DO i = 1,
SIZE(particle_set)
876 rvec = particle_set(i)%r - center
877 r2 = dot_product(rvec, rvec)
880 IF (output_unit > 0)
THEN
881 WRITE (output_unit,
'(A,I6,A)')
"Atom number :: ", i,
" is out of the solvation sphere"
882 WRITE (output_unit,
'(2(A,F12.6))')
"Distance from the center::", r1,
" Radius of the sphere::", rs
887 IF (r1 /= 0.0_dp)
THEN
889 locp(l, i) = (r1**l*real(l + 1, kind=
dp)*(eps_in - eps_out))/ &
890 (rs**(2*l + 1)*eps_in*(real(l, kind=
dp)*eps_in + real(l + 1, kind=
dp)*eps_out))
894 locp(0, i) = (eps_in - eps_out)/(rs*eps_in*eps_out)
900 DO i = 1,
SIZE(particle_set)
903 IF (pos(i)*pos(j) /= 0.0_dp)
THEN
904 mycos = dot_product(particle_set(i)%r - center, particle_set(j)%r - center)/(pos(i)*pos(j))
905 IF (abs(mycos) > 1.0_dp) mycos = sign(1.0_dp, mycos)
907 factor = factor + locp(l, i)*pos(j)**l*
legendre(mycos, l, 0)
918 DO iparticle2 = 1,
SIZE(particle_set)
919 ip2 = (iparticle2 - 1)*
SIZE(radii)
920 DO igauss2 = 1,
SIZE(radii)
921 idim2 = ip2 + igauss2
922 DO iparticle1 = 1, iparticle2
923 ip1 = (iparticle1 - 1)*
SIZE(radii)
925 IF (iparticle1 == iparticle2) istart_g = igauss2
926 DO igauss1 = istart_g,
SIZE(radii)
927 idim1 = ip1 + igauss1
928 m(idim1, idim2) = cost(iparticle1, iparticle2)
929 m(idim2, idim1) = m(idim1, idim2)
static GRID_HOST_DEVICE double fac(const int i)
Factorial function, e.g. fac(5) = 5! = 120.
static void dgemm(const char transa, const char transb, const int m, const int n, const int k, const double alpha, const double *a, const int lda, const double *b, const int ldb, const double beta, double *c, const int ldc)
Convenient wrapper to hide Fortran nature of dgemm_, swapping a and b.
Handles all functions related to the CELL.
contains information regarding the decoupling/recoupling method of Bloechl
subroutine, public ddapc_eval_ami(GAmI, c0, gfunc, w, particle_set, gcut, rho_tot_g, radii, iw, Vol)
Computes the inverse AmI of the Am matrix.
subroutine, public cleanup_g_dot_rvec_sin_cos(g_dot_rvec_sin, g_dot_rvec_cos)
deallocate g_dot_rvec_* arrays
subroutine, public build_der_b_vector(dbv, gfunc, w, particle_set, radii, rho_tot_g, gcut, iparticle0)
Computes the derivative of B vector for the evaluation of the Pulay forces.
subroutine, public build_b_vector(bv, gfunc, w, particle_set, radii, rho_tot_g, gcut)
Computes the B vector for the solution of the linear system.
subroutine, public build_der_a_matrix_rows(dAm, gfunc, w, particle_set, radii, rho_tot_g, gcut, iparticle0, nparticles, g_dot_rvec_sin, g_dot_rvec_cos)
Computes the derivative of the A matrix for the evaluation of the Pulay forces.
subroutine, public build_a_matrix(Am, gfunc, w, particle_set, radii, rho_tot_g, gcut, g_dot_rvec_sin, g_dot_rvec_cos)
Computes the A matrix for the solution of the linear system.
recursive subroutine, public ewald_ddapc_pot(cp_para_env, coeff, factor, cell, multipole_section, particle_set, M, radii)
Evaluates the Ewald term E2 and E3 energy term for the decoupling/coupling of periodic images.
subroutine, public prep_g_dot_rvec_sin_cos(rho_tot_g, particle_set, gcut, g_dot_rvec_sin, g_dot_rvec_cos)
precompute sin(g.r) and cos(g.r) for quicker evaluations of sin(g.(r1-r2)) and cos(g....
subroutine, public solvation_ddapc_pot(solvation_section, particle_set, M, radii)
Evaluates the electrostatic potential due to a simple solvation model Spherical cavity in a dieletric...
subroutine, public ddapc_eval_gfunc(gfunc, w, gcut, rho_tot_g, radii)
...
various routines to log and control the output. The idea is that decisions about where to log should ...
integer function, public cp_logger_get_default_io_unit(logger)
returns the unit nr for the ionode (-1 on all other processors) skips as well checks if the procs cal...
sums arrays of real/complex numbers with much reduced round-off as compared to a naive implementation...
Defines the basic variable types.
integer, parameter, public dp
An array-based list which grows on demand. When the internal array is full, a new array of twice the ...
Definition of mathematical constants and functions.
real(kind=dp), parameter, public oorootpi
real(kind=dp), parameter, public pi
real(kind=dp), parameter, public fourpi
real(kind=dp), parameter, public twopi
Collection of simple mathematical functions and subroutines.
subroutine, public diamat_all(a, eigval, dac)
Diagonalize the symmetric n by n matrix a using the LAPACK library. Only the upper triangle of matrix...
Interface to the message passing library MPI.
Define the data structure for the particle information.
different utils that are useful to manipulate splines on the regular grid of a pw
real(kind=dp) function, public eval_interp_spl3_pbc(vec, pw)
Evaluates the PBC interpolated Spline (pw) function on the generic input vector (vec)
Calculate spherical harmonics.
real(kind=dp) function, public legendre(x, l, m)
...