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
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
117 REAL(kind=
dp),
DIMENSION(:),
POINTER :: radii
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 >= 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)
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
195 REAL(kind=
dp),
DIMENSION(:),
POINTER :: radii
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 >= 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
281 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: radii
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 >= 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)
325 my_dbvw(ig) = my_dbv(2, ig)*gfunc(ig, igauss)
329 my_dbvw(ig) = my_dbv(3, ig)*gfunc(ig, igauss)
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
373 REAL(kind=
dp),
DIMENSION(:),
POINTER :: radii
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 >= 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)
469 dam((iparticle0 - 1)*nr + 1:(iparticle0 + nparticles - 1)*nr, :, :) = 0.0_dp
471 CALL timestop(handle)
480 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: g_dot_rvec_sin, g_dot_rvec_cos
482 IF (
ALLOCATED(g_dot_rvec_sin))
DEALLOCATE (g_dot_rvec_sin)
483 IF (
ALLOCATED(g_dot_rvec_cos))
DEALLOCATE (g_dot_rvec_cos)
497 REAL(kind=
dp),
INTENT(IN) :: gcut
498 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: g_dot_rvec_sin, g_dot_rvec_cos
500 INTEGER :: e_dim, ig, igmax, iparticle, s_dim
501 REAL(kind=
dp) :: g2, g_dot_rvec, gcut2, rvec(3)
504 s_dim = rho_tot_g%pw_grid%first_gne0
505 e_dim = rho_tot_g%pw_grid%ngpts_cut_local
508 g2 = rho_tot_g%pw_grid%gsq(ig)
513 IF (igmax >= s_dim)
THEN
514 ALLOCATE (g_dot_rvec_sin(1:igmax - s_dim + 1,
SIZE(particle_set)))
515 ALLOCATE (g_dot_rvec_cos(1:igmax - s_dim + 1,
SIZE(particle_set)))
517 DO iparticle = 1,
SIZE(particle_set)
518 rvec = particle_set(iparticle)%r
520 g_dot_rvec = dot_product(rho_tot_g%pw_grid%g(:, ig), rvec)
521 g_dot_rvec_sin(ig - s_dim + 1, iparticle) = sin(g_dot_rvec)
522 g_dot_rvec_cos(ig - s_dim + 1, iparticle) = cos(g_dot_rvec)
527 ALLOCATE (g_dot_rvec_sin(0,
SIZE(particle_set)))
528 ALLOCATE (g_dot_rvec_cos(0,
SIZE(particle_set)))
550 rho_tot_g, radii, iw, Vol)
551 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: gami
552 REAL(kind=
dp),
INTENT(OUT) :: c0
553 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: gfunc
554 REAL(kind=
dp),
DIMENSION(:),
POINTER :: w
556 REAL(kind=
dp),
INTENT(IN) :: gcut
558 REAL(kind=
dp),
DIMENSION(:),
POINTER :: radii
559 INTEGER,
INTENT(IN) :: iw
560 REAL(kind=
dp),
INTENT(IN) :: vol
562 CHARACTER(len=*),
PARAMETER :: routinen =
'ddapc_eval_AmI'
564 INTEGER :: handle, ndim
565 REAL(kind=
dp) :: condition_number, inv_error
566 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: ame, cv
567 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: am, ami, amw, g_dot_rvec_cos, &
572 CALL timeset(routinen, handle)
573 ndim =
SIZE(particle_set)*
SIZE(radii)
574 ALLOCATE (am(ndim, ndim))
575 ALLOCATE (ami(ndim, ndim))
576 ALLOCATE (gami(ndim, ndim))
583 CALL build_a_matrix(am, gfunc, w, particle_set, radii, rho_tot_g, gcut, g_dot_rvec_sin, g_dot_rvec_cos)
585 am(:, :) = am(:, :)/(vol*vol)
586 CALL rho_tot_g%pw_grid%para%group%sum(am)
589 ALLOCATE (amw(ndim, ndim))
593 condition_number = maxval(abs(ame))/minval(abs(ame))
594 WRITE (iw,
'(T3,A)')
" Eigenvalues of Matrix A:"
595 WRITE (iw,
'(T3,4E15.8)') ame
596 WRITE (iw,
'(T3,A,1E15.9)')
" Condition number:", condition_number
597 IF (condition_number > 1.0e12_dp)
THEN
598 WRITE (iw, fmt=
"(/,T2,A)") &
599 "WARNING: high condition number => possibly ill-conditioned matrix"
606 WRITE (iw,
'(T3,A,F15.9)')
" Error inverting the A matrix: ", inv_error
608 c0 = dot_product(cv, matmul(ami, cv))
613 CALL timestop(handle)
632 RECURSIVE SUBROUTINE ewald_ddapc_pot(cp_para_env, coeff, factor, cell, multipole_section, &
633 particle_set, M, radii)
636 REAL(kind=
dp),
INTENT(IN) :: factor
640 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: m
641 REAL(kind=
dp),
DIMENSION(:),
POINTER :: radii
643 CHARACTER(len=*),
PARAMETER :: routinen =
'ewald_ddapc_pot'
645 INTEGER :: ewmdim, handle, iaxis, idim, idim1, idim2, idimo, igauss1, igauss2, ip1, ip2, &
646 iparticle1, iparticle2, istart_g, k1, k2, k3, n_rep, ndim, r1, r2, r3
647 INTEGER,
DIMENSION(3) :: gmax, image_cell, rmax, rmin
649 REAL(kind=
dp) :: alpha, eps, ew_neut,
fac, fac3, frac_radius, fs, g_ewald, galpha, gsq, &
650 gsqi, ij_fac, my_val, r, r2tmp, r_ewald, rc1, rc12, rc2, rc22, rcut, rcut2, t1, tol, tol1
651 REAL(kind=
dp),
DIMENSION(3) :: g_index, gvec, ra, rvec, svec
652 REAL(kind=
dp),
DIMENSION(:),
POINTER :: ewm
655 CALL timeset(routinen, handle)
656 cpassert(.NOT.
ASSOCIATED(m))
657 cpassert(
ASSOCIATED(radii))
658 rcut = min(norm2(cell%hmat(:, 1)), norm2(cell%hmat(:, 2)), norm2(cell%hmat(:, 3)))/2.0_dp
664 analyt = analyt .OR. .NOT. cell%orthorhombic .OR. .NOT.
ASSOCIATED(coeff)
669 eps = min(abs(eps), 0.5_dp)
670 tol = sqrt(abs(log(eps*rcut)))
671 alpha = sqrt(abs(log(eps*rcut*tol)))/rcut
672 galpha = 1.0_dp/(4.0_dp*alpha*alpha)
673 tol1 = sqrt(-log(eps*rcut*(2.0_dp*tol*alpha)**2))
674 IF (cell%orthorhombic)
THEN
676 gmax(iaxis) = nint(0.25_dp + cell%hmat(iaxis, iaxis)*alpha*tol1/
pi)
680 gmax(iaxis) = ceiling(alpha*tol1*norm2(cell%hmat(:, iaxis))/
pi)
683 fac = 1.e0_dp/cell%deth
685 ew_neut = -
fac*
pi/alpha**2
687 ewmdim =
SIZE(particle_set)*(
SIZE(particle_set) + 1)/2
688 ndim =
SIZE(particle_set)*
SIZE(radii)
689 ALLOCATE (ewm(ewmdim))
690 ALLOCATE (m(ndim, ndim))
695 DO iparticle1 = 1,
SIZE(particle_set)
696 ip1 = (iparticle1 - 1)*
SIZE(radii)
697 DO iparticle2 = 1, iparticle1
699 IF (iparticle1 == iparticle2) ij_fac = 0.5_dp
701 ip2 = (iparticle2 - 1)*
SIZE(radii)
704 IF (mod(iparticle1, cp_para_env%num_pe) /= cp_para_env%mepos) cycle
709 rvec = particle_set(iparticle1)%r - particle_set(iparticle2)%r
711 IF (iparticle1 /= iparticle2)
THEN
713 r2tmp = dot_product(ra, ra)
714 IF (r2tmp <= rcut2)
THEN
720 svec = matmul(cell%h_inv, rvec)
722 frac_radius = rcut*norm2(cell%h_inv(iaxis, :))
723 rmin(iaxis) = floor(-svec(iaxis) - frac_radius)
724 rmax(iaxis) = ceiling(-svec(iaxis) + frac_radius)
726 DO r1 = rmin(1), rmax(1)
727 DO r2 = rmin(2), rmax(2)
728 DO r3 = rmin(3), rmax(3)
729 IF ((r1 == 0) .AND. (r2 == 0) .AND. (r3 == 0)) cycle
730 image_cell = [r1, r2, r3]
731 ra = rvec + matmul(cell%hmat, real(image_cell, kind=
dp))
732 r2tmp = dot_product(ra, ra)
733 IF (r2tmp <= rcut2)
THEN
736 r_ewald = r_ewald + t1*ij_fac
747 DO k2 = -gmax(2), gmax(2)
748 DO k3 = -gmax(3), gmax(3)
749 IF (k1 == 0 .AND. k2 == 0 .AND. k3 == 0) cycle
750 fs = 2.0_dp;
IF (k1 == 0) fs = 1.0_dp
751 g_index = [real(k1, kind=
dp), real(k2, kind=
dp), real(k3, kind=
dp)]
752 gvec =
twopi*matmul(transpose(cell%h_inv), g_index)
753 gsq = dot_product(gvec, gvec)
755 t1 =
fac*gsqi*exp(-galpha*gsq)
756 g_ewald = g_ewald + t1*cos(dot_product(gvec, rvec))
766 g_ewald = r_ewald +
fourpi*g_ewald
770 IF (iparticle1 == iparticle2)
THEN
771 g_ewald = g_ewald - 2.0_dp*alpha*
oorootpi
774 IF (iparticle1 /= iparticle2)
THEN
779 ewm(idim) = my_val - factor*g_ewald
783 CALL cp_para_env%sum(ewm)
785 DO iparticle2 = 1,
SIZE(particle_set)
786 ip2 = (iparticle2 - 1)*
SIZE(radii)
787 idimo = (iparticle2 - 1)
788 idimo = idimo*(idimo + 1)/2
789 DO igauss2 = 1,
SIZE(radii)
790 idim2 = ip2 + igauss2
793 DO iparticle1 = 1, iparticle2
794 ip1 = (iparticle1 - 1)*
SIZE(radii)
795 idim = idimo + iparticle1
797 IF (iparticle1 == iparticle2) istart_g = igauss2
798 DO igauss1 = istart_g,
SIZE(radii)
799 idim1 = ip1 + igauss1
802 m(idim1, idim2) = ewm(idim) - factor*ew_neut - factor*fac3*(rc12 + rc22)
803 m(idim2, idim1) = m(idim1, idim2)
809 CALL timestop(handle)
826 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: m
827 REAL(kind=
dp),
DIMENSION(:),
POINTER :: radii
829 INTEGER :: i, idim, idim1, idim2, igauss1, igauss2, ip1, ip2, iparticle1, iparticle2, &
830 istart_g, j, l, lmax, n_rep1, n_rep2, ndim, output_unit, weight
831 INTEGER,
DIMENSION(:),
POINTER ::
list
832 LOGICAL :: fixed_center
833 REAL(kind=
dp) :: center(3), eps_in, eps_out, factor, &
834 mass, mycos, r1, r2, rs, rvec(3)
835 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pos, r0
836 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: cost, locp
838 fixed_center = .false.
840 ndim =
SIZE(particle_set)*
SIZE(radii)
841 ALLOCATE (m(ndim, ndim))
848 IF (n_rep1 /= 0)
THEN
854 IF (n_rep2 /= 0)
THEN
862 r0 = r0 + particle_set(
list(i))%r
864 r0 = r0/real(
SIZE(
list), kind=
dp)
869 r0 = r0 + particle_set(
list(i))%r*particle_set(
list(i))%atomic_kind%mass
870 mass = mass + particle_set(
list(i))%atomic_kind%mass
876 IF (fixed_center)
THEN
884 cpassert(n_rep1 /= 0 .OR. n_rep2 /= 0)
886 ALLOCATE (locp(0:lmax,
SIZE(particle_set)))
887 ALLOCATE (pos(
SIZE(particle_set)))
888 ALLOCATE (cost(
SIZE(particle_set),
SIZE(particle_set)))
890 DO i = 1,
SIZE(particle_set)
891 rvec = particle_set(i)%r - center
892 r2 = dot_product(rvec, rvec)
895 IF (output_unit > 0)
THEN
896 WRITE (output_unit,
'(A,I6,A)')
"Atom number :: ", i,
" is out of the solvation sphere"
897 WRITE (output_unit,
'(2(A,F12.6))')
"Distance from the center::", r1,
" Radius of the sphere::", rs
899 cpabort(
"Unable to evaluate electrostatic potential in solution")
902 IF (r1 /= 0.0_dp)
THEN
904 locp(l, i) = (r1**l*real(l + 1, kind=
dp)*(eps_in - eps_out))/ &
905 (rs**(2*l + 1)*eps_in*(real(l, kind=
dp)*eps_in + real(l + 1, kind=
dp)*eps_out))
909 locp(0, i) = (eps_in - eps_out)/(rs*eps_in*eps_out)
915 DO i = 1,
SIZE(particle_set)
918 IF (pos(i)*pos(j) /= 0.0_dp)
THEN
919 mycos = dot_product(particle_set(i)%r - center, particle_set(j)%r - center)/(pos(i)*pos(j))
920 IF (abs(mycos) > 1.0_dp) mycos = sign(1.0_dp, mycos)
922 factor = factor + locp(l, i)*pos(j)**l*
legendre(mycos, l, 0)
933 DO iparticle2 = 1,
SIZE(particle_set)
934 ip2 = (iparticle2 - 1)*
SIZE(radii)
935 DO igauss2 = 1,
SIZE(radii)
936 idim2 = ip2 + igauss2
937 DO iparticle1 = 1, iparticle2
938 ip1 = (iparticle1 - 1)*
SIZE(radii)
940 IF (iparticle1 == iparticle2) istart_g = igauss2
941 DO igauss1 = istart_g,
SIZE(radii)
942 idim1 = ip1 + igauss1
943 m(idim1, idim2) = cost(iparticle1, iparticle2)
944 m(idim2, idim1) = m(idim1, idim2)
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 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_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.
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 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....
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 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 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 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
real(kind=dp), dimension(0:maxfac), parameter, public fac
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)
...
Type defining parameters related to the simulation cell.
stores all the informations relevant to an mpi environment