45#include "./base/base_uses.f90"
51 REAL(KIND=
dp),
PARAMETER :: epsr = 1.e-12_dp
53 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'qs_dispersion_nonloc'
70 CHARACTER(len=*),
PARAMETER :: routinen =
'qs_dispersion_nonloc_init'
72 CHARACTER(LEN=default_string_length) :: filename
73 INTEGER :: funit, handle, nqs, nr_points, q1_i, &
76 CALL timeset(routinen, handle)
78 SELECT CASE (dispersion_env%nl_type)
80 cpabort(
"Unknown vdW-DF functional")
88 vdw_type = dispersion_env%type
89 SELECT CASE (vdw_type)
94 filename = dispersion_env%kernel_file_name
95 IF (para_env%is_source())
THEN
97 CALL open_file(file_name=filename, unit_number=funit, file_form=
"FORMATTED")
98 READ (funit, *) nqs, nr_points
99 READ (funit, *) dispersion_env%r_max
101 CALL para_env%bcast(nqs)
102 CALL para_env%bcast(nr_points)
103 CALL para_env%bcast(dispersion_env%r_max)
104 ALLOCATE (dispersion_env%q_mesh(nqs), dispersion_env%kernel(0:nr_points, nqs, nqs), &
105 dispersion_env%d2phi_dk2(0:nr_points, nqs, nqs))
106 dispersion_env%nqs = nqs
107 dispersion_env%nr_points = nr_points
108 IF (para_env%is_source())
THEN
110 READ (funit,
"(1p, 4e23.14)") dispersion_env%q_mesh
116 READ (funit,
"(1p, 4e23.14)") dispersion_env%kernel(0:nr_points, q1_i, q2_i)
117 dispersion_env%kernel(0:nr_points, q2_i, q1_i) = dispersion_env%kernel(0:nr_points, q1_i, q2_i)
126 READ (funit,
"(1p, 4e23.14)") dispersion_env%d2phi_dk2(0:nr_points, q1_i, q2_i)
127 dispersion_env%d2phi_dk2(0:nr_points, q2_i, q1_i) = dispersion_env%d2phi_dk2(0:nr_points, q1_i, q2_i)
132 CALL para_env%bcast(dispersion_env%q_mesh)
133 CALL para_env%bcast(dispersion_env%kernel)
134 CALL para_env%bcast(dispersion_env%d2phi_dk2)
136 ALLOCATE (dispersion_env%d2y_dx2(nqs, nqs))
137 CALL initialize_spline_interpolation(dispersion_env%q_mesh, dispersion_env%d2y_dx2)
139 dispersion_env%q_cut = dispersion_env%q_mesh(nqs)
140 dispersion_env%q_min = dispersion_env%q_mesh(1)
141 dispersion_env%dk = 2.0_dp*
pi/dispersion_env%r_max
145 CALL timestop(handle)
164 dispersion_env, energy_only, pw_pool, xc_pw_pool, para_env, virial)
167 REAL(kind=
dp),
INTENT(OUT) :: edispersion
169 LOGICAL,
INTENT(IN) :: energy_only
174 CHARACTER(LEN=*),
PARAMETER :: routinen =
'calculate_dispersion_nonloc'
175 INTEGER,
DIMENSION(3, 3),
PARAMETER :: nd = reshape((/1, 0, 0, 0, 1, 0, 0, 0, 1/), (/3, 3/))
177 INTEGER :: handle, i, i_grid, idir, ispin, nl_type, &
178 np, nspin, p, q, r, s
179 INTEGER,
DIMENSION(1:3) :: hi, lo, n
180 LOGICAL :: use_virial
181 REAL(kind=
dp) :: b_value, beta, const, ec_nl, sumnp
182 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: dq0_dgradrho, dq0_drho, hpot, potential, &
184 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: drho, thetas
191 CALL timeset(routinen, handle)
193 cpassert(
ASSOCIATED(rho_r))
194 cpassert(
ASSOCIATED(rho_g))
195 cpassert(
ASSOCIATED(pw_pool))
197 IF (
PRESENT(virial))
THEN
198 use_virial = virial%pv_calculate .AND. (.NOT. virial%pv_numer)
203 cpassert(.NOT. energy_only)
205 IF (.NOT. energy_only)
THEN
206 cpassert(
ASSOCIATED(vxc_rho))
209 nl_type = dispersion_env%nl_type
211 b_value = dispersion_env%b_value
212 beta = 0.03125_dp*(3.0_dp/(b_value**2.0_dp))**0.75_dp
215 const = 1.0_dp/(3.0_dp*
rootpi*b_value**1.5_dp)/(
pi**0.75_dp)
218 CALL pw_pool%create_pw(tmp_g)
219 CALL pw_pool%create_pw(tmp_r)
222 ALLOCATE (drho_r(3, nspin))
225 CALL pw_pool%create_pw(drho_r(idir, ispin))
232 np =
SIZE(tmp_r%array)
233 ALLOCATE (rho(np), drho(np, 3))
235 lo(i) = lbound(tmp_r%array, i)
236 hi(i) = ubound(tmp_r%array, i)
237 n(i) = hi(i) - lo(i) + 1
245 rho(r*n(2)*n(1) + q*n(1) + p + 1) = 0.0_dp
257 drho(r*n(2)*n(1) + q*n(1) + p + 1, i) = 0.0_dp
273 s = r*n(2)*n(1) + q*n(1) + p + 1
274 rho(s) = rho(s) + tmp_r%array(p + lo(1), q + lo(2), r + lo(3))
287 s = r*n(2)*n(1) + q*n(1) + p + 1
288 drho(s, i) = drho(s, i) + drho_r(i, ispin)%array(p + lo(1), q + lo(2), r + lo(3))
303 IF (energy_only)
THEN
305 SELECT CASE (nl_type)
307 cpabort(
"Unknown vdW-DF functional")
309 CALL get_q0_on_grid_eo_vdw(rho, drho, q0, dispersion_env)
311 CALL get_q0_on_grid_eo_rvv10(rho, drho, q0, dispersion_env)
314 ALLOCATE (q0(np), dq0_drho(np), dq0_dgradrho(np))
315 SELECT CASE (nl_type)
317 cpabort(
"Unknown vdW-DF functional")
319 CALL get_q0_on_grid_vdw(rho, drho, q0, dq0_drho, dq0_dgradrho, dispersion_env)
321 CALL get_q0_on_grid_rvv10(rho, drho, q0, dq0_drho, dq0_dgradrho, dispersion_env)
339 ALLOCATE (thetas(np, dispersion_env%nqs))
342 CALL spline_interpolation(dispersion_env%q_mesh, dispersion_env%d2y_dx2, q0, thetas)
347 SELECT CASE (nl_type)
349 cpabort(
"Unknown vdW-DF functional")
353 DO i = 1, dispersion_env%nqs
354 thetas(:, i) = thetas(:, i)*rho(:)
363 IF (rho(i_grid) > epsr)
THEN
364 DO i = 1, dispersion_env%nqs
365 thetas(i_grid, i) = thetas(i_grid, i)*const*rho(i_grid)**(0.75_dp)
368 thetas(i_grid, :) = 0.0_dp
376 lo(i) = lbound(tmp_r%array, i)
377 hi(i) = ubound(tmp_r%array, i)
378 n(i) = hi(i) - lo(i) + 1
380 ALLOCATE (thetas_g(dispersion_env%nqs))
381 DO i = 1, dispersion_env%nqs
388 tmp_r%array(p + lo(1), q + lo(2), r + lo(3)) = thetas(r*n(2)*n(1) + q*n(1) + p + 1, i)
393 CALL pw_pool%create_pw(thetas_g(i))
396 grid => thetas_g(1)%pw_grid
403 CALL para_env%sum(sumnp)
406 CALL vdw_energy(thetas_g, dispersion_env, ec_nl, energy_only, virial)
407 SELECT CASE (nl_type)
409 ec_nl = 0.5_dp*ec_nl + beta*sum(rho(:))*grid%vol/sumnp
414 virial%pv_xc(idir, idir) = virial%pv_xc(idir, idir) + ec_nl
417 CALL vdw_energy(thetas_g, dispersion_env, ec_nl, energy_only)
418 SELECT CASE (nl_type)
420 ec_nl = 0.5_dp*ec_nl + beta*sum(rho(:))*grid%vol/sumnp
423 CALL para_env%sum(ec_nl)
424 IF (nl_type ==
vdw_nl_rvv10) ec_nl = ec_nl*dispersion_env%scale_rvv10
427 IF (energy_only)
THEN
434 lo(i) = lbound(tmp_r%array, i)
435 hi(i) = ubound(tmp_r%array, i)
436 n(i) = hi(i) - lo(i) + 1
438 DO i = 1, dispersion_env%nqs
446 thetas(r*n(2)*n(1) + q*n(1) + p + 1, i) = tmp_r%array(p + lo(1), q + lo(2), r + lo(3))
459 ALLOCATE (potential(np), hpot(np))
462 grid => tmp_g%pw_grid
463 CALL get_potential(q0, dq0_drho, dq0_dgradrho, rho, thetas, potential, hpot, &
464 dispersion_env, drho, grid%dvol, virial)
466 CALL get_potential(q0, dq0_drho, dq0_dgradrho, rho, thetas, potential, hpot, &
469 SELECT CASE (nl_type)
471 potential(:) = (0.5_dp*potential(:) + beta)*dispersion_env%scale_rvv10
472 hpot(:) = 0.5_dp*dispersion_env%scale_rvv10*hpot(:)
474 CALL pw_pool%create_pw(vxc_r)
476 lo(i) = lbound(vxc_r%array, i)
477 hi(i) = ubound(vxc_r%array, i)
478 n(i) = hi(i) - lo(i) + 1
486 vxc_r%array(p + lo(1), q + lo(2), r + lo(3)) = potential(r*n(2)*n(1) + q*n(1) + p + 1)
492 lo(i) = lbound(tmp_r%array, i)
493 hi(i) = ubound(tmp_r%array, i)
494 n(i) = hi(i) - lo(i) + 1
503 tmp_r%array(p + lo(1), q + lo(2), r + lo(3)) = 0.0_dp
515 tmp_r%array(p + lo(1), q + lo(2), r + lo(3)) = tmp_r%array(p + lo(1), q + lo(2), r + lo(3)) &
516 + hpot(r*n(2)*n(1) + q*n(1) + p + 1) &
517 *drho_r(idir, ispin)%array(p + lo(1), q + lo(2), r + lo(3))
526 CALL pw_axpy(tmp_r, vxc_r, -1._dp)
529 CALL pw_pool%give_back_pw(vxc_r)
530 CALL xc_pw_pool%create_pw(vxc_r)
531 CALL xc_pw_pool%create_pw(vxc_g)
535 CALL pw_axpy(vxc_r, vxc_rho(ispin), 1._dp)
537 CALL xc_pw_pool%give_back_pw(vxc_r)
538 CALL xc_pw_pool%give_back_pw(vxc_g)
539 DEALLOCATE (q0, dq0_drho, dq0_dgradrho)
544 DO i = 1, dispersion_env%nqs
545 CALL pw_pool%give_back_pw(thetas_g(i))
549 CALL pw_pool%give_back_pw(drho_r(idir, ispin))
552 CALL pw_pool%give_back_pw(tmp_r)
553 CALL pw_pool%give_back_pw(tmp_g)
555 DEALLOCATE (rho, drho, drho_r, thetas_g)
557 CALL timestop(handle)
574 SUBROUTINE vdw_energy(thetas_g, dispersion_env, vdW_xc_energy, energy_only, virial)
577 REAL(kind=
dp),
INTENT(OUT) :: vdw_xc_energy
578 LOGICAL,
INTENT(IN) :: energy_only
581 CHARACTER(LEN=*),
PARAMETER :: routinen =
'vdW_energy'
583 COMPLEX(KIND=dp) :: uu
584 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:) :: theta
585 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: u_vdw(:, :)
586 INTEGER :: handle, ig, iq, l, m, nl_type, nqs, &
588 LOGICAL :: use_virial
589 REAL(kind=
dp) :: g, g2, g2_last, g_multiplier, gm
590 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: dkernel_of_dk, kernel_of_k
591 REAL(kind=
dp),
DIMENSION(3, 3) :: virial_thread
594 CALL timeset(routinen, handle)
595 nqs = dispersion_env%nqs
597 use_virial =
PRESENT(virial)
598 virial_thread(:, :) = 0.0_dp
600 vdw_xc_energy = 0._dp
601 grid => thetas_g(1)%pw_grid
609 nl_type = dispersion_env%nl_type
611 IF (.NOT. energy_only)
THEN
612 ALLOCATE (u_vdw(grid%ngpts_cut_local, nqs))
613 u_vdw(:, :) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
628 g2_last = huge(0._dp)
630 ALLOCATE (kernel_of_k(nqs, nqs), dkernel_of_dk(nqs, nqs))
631 ALLOCATE (theta(nqs))
634 DO ig = 1, grid%ngpts_cut_local
636 IF (abs(g2 - g2_last) > 1.e-10)
THEN
639 CALL interpolate_kernel(g, kernel_of_k, dispersion_env)
640 IF (use_virial)
CALL interpolate_dkernel_dk(g, dkernel_of_dk, dispersion_env)
643 theta(iq) = thetas_g(iq)%array(ig)
646 uu = cmplx(0.0_dp, 0.0_dp, kind=
dp)
648 uu = uu + kernel_of_k(q2_i, q1_i)*theta(q1_i)
650 IF (ig < grid%first_gne0)
THEN
651 vdw_xc_energy = vdw_xc_energy + real(uu*conjg(theta(q2_i)), kind=
dp)
653 vdw_xc_energy = vdw_xc_energy + g_multiplier*real(uu*conjg(theta(q2_i)), kind=
dp)
655 IF (.NOT. energy_only) u_vdw(ig, q2_i) = uu
657 IF (use_virial .AND. ig >= grid%first_gne0)
THEN
659 gm = 0.5_dp*g_multiplier*grid%vol*dkernel_of_dk(q1_i, q2_i)*real(theta(q1_i)*conjg(theta(q2_i)), kind=
dp)
665 virial_thread(l, m) = virial_thread(l, m) - gm*(grid%g(l, ig)*grid%g(m, ig))/g
676 DEALLOCATE (kernel_of_k, dkernel_of_dk)
678 IF (.NOT. energy_only)
THEN
680 DO ig = 1, grid%ngpts_cut_local
682 thetas_g(iq)%array(ig) = u_vdw(ig, iq)
690 IF (.NOT. energy_only)
THEN
694 vdw_xc_energy = vdw_xc_energy*grid%vol*0.5_dp
699 virial%pv_xc(l, m) = virial%pv_xc(l, m) + virial_thread(l, m)
700 virial%pv_xc(m, l) = virial%pv_xc(l, m)
703 virial%pv_xc(l, m) = virial%pv_xc(l, m) + virial_thread(l, m)
707 CALL timestop(handle)
709 END SUBROUTINE vdw_energy
734 SUBROUTINE get_potential(q0, dq0_drho, dq0_dgradrho, total_rho, u_vdW, potential, h_prefactor, &
735 dispersion_env, drho, dvol, virial)
737 REAL(
dp),
DIMENSION(:),
INTENT(in) :: q0, dq0_drho, dq0_dgradrho, total_rho
738 REAL(
dp),
DIMENSION(:, :),
INTENT(in) :: u_vdw
739 REAL(
dp),
DIMENSION(:),
INTENT(out) :: potential, h_prefactor
741 REAL(
dp),
DIMENSION(:, :),
INTENT(in),
OPTIONAL :: drho
742 REAL(
dp),
INTENT(IN),
OPTIONAL :: dvol
745 CHARACTER(len=*),
PARAMETER :: routinen =
'get_potential'
747 INTEGER :: handle, i_grid, l, m, nl_type, nqs, p_i, &
749 LOGICAL :: use_virial
750 REAL(
dp) :: a, b, b_value, c, const, d, dp_dq0, dq, &
751 dq_6, e, f, p, prefactor, tmp_1_2, &
753 REAL(
dp),
ALLOCATABLE,
DIMENSION(:) :: y
754 REAL(
dp),
DIMENSION(3, 3) :: virial_thread
755 REAL(
dp),
DIMENSION(:),
POINTER :: q_mesh
756 REAL(
dp),
DIMENSION(:, :),
POINTER :: d2y_dx2
758 CALL timeset(routinen, handle)
760 use_virial =
PRESENT(virial)
761 cpassert(.NOT. use_virial .OR.
PRESENT(drho))
762 cpassert(.NOT. use_virial .OR.
PRESENT(dvol))
764 virial_thread(:, :) = 0.0_dp
765 b_value = dispersion_env%b_value
766 const = 1.0_dp/(3.0_dp*b_value**(3.0_dp/2.0_dp)*
pi**(5.0_dp/4.0_dp))
770 d2y_dx2 => dispersion_env%d2y_dx2
771 q_mesh => dispersion_env%q_mesh
772 nqs = dispersion_env%nqs
773 nl_type = dispersion_env%nl_type
792 DO i_grid = 1,
SIZE(u_vdw, 1)
796 DO WHILE ((q_hi - q_low) > 1)
797 q = int((q_hi + q_low)/2)
798 IF (q_mesh(q) > q0(i_grid))
THEN
804 IF (q_hi == q_low) cpabort(
"get_potential: qhi == qlow")
806 dq = q_mesh(q_hi) - q_mesh(q_low)
809 a = (q_mesh(q_hi) - q0(i_grid))/dq
810 b = (q0(i_grid) - q_mesh(q_low))/dq
811 c = (a**3 - a)*dq*dq_6
812 d = (b**3 - b)*dq*dq_6
813 e = (3.0_dp*a**2 - 1.0_dp)*dq_6
814 f = (3.0_dp*b**2 - 1.0_dp)*dq_6
819 dp_dq0 = (y(q_hi) - y(q_low))/dq - e*d2y_dx2(p_i, q_low) + f*d2y_dx2(p_i, q_hi)
820 p = a*y(q_low) + b*y(q_hi) + c*d2y_dx2(p_i, q_low) + d*d2y_dx2(p_i, q_hi)
822 SELECT CASE (nl_type)
824 cpabort(
"Unknown vdW-DF functional")
826 potential(i_grid) = potential(i_grid) + u_vdw(i_grid, p_i)*(p + dp_dq0*dq0_drho(i_grid))
827 prefactor = u_vdw(i_grid, p_i)*dp_dq0*dq0_dgradrho(i_grid)
829 IF (total_rho(i_grid) > epsr)
THEN
830 tmp_1_2 = sqrt(total_rho(i_grid))
831 tmp_1_4 = sqrt(tmp_1_2)
832 tmp_3_4 = tmp_1_4*tmp_1_4*tmp_1_4
833 potential(i_grid) = potential(i_grid) &
834 + u_vdw(i_grid, p_i)*(const*0.75_dp/tmp_1_4*p &
835 + const*tmp_3_4*dp_dq0*dq0_drho(i_grid))
836 prefactor = u_vdw(i_grid, p_i)*const*tmp_3_4*dp_dq0*dq0_dgradrho(i_grid)
841 IF (q0(i_grid) .NE. q_mesh(nqs))
THEN
842 h_prefactor(i_grid) = h_prefactor(i_grid) + prefactor
845 IF (use_virial .AND. abs(prefactor) > 0.0_dp)
THEN
846 SELECT CASE (nl_type)
850 prefactor = 0.5_dp*prefactor
852 prefactor = prefactor*dvol
855 virial_thread(l, m) = virial_thread(l, m) - prefactor*drho(i_grid, l)*drho(i_grid, m)
870 virial%pv_xc(l, m) = virial%pv_xc(l, m) + virial_thread(l, m)
871 virial%pv_xc(m, l) = virial%pv_xc(l, m)
874 virial%pv_xc(l, m) = virial%pv_xc(l, m) + virial_thread(l, m)
878 CALL timestop(handle)
879 END SUBROUTINE get_potential
889 ELEMENTAL SUBROUTINE calculate_exponent(hi, alpha, exponent)
890 INTEGER,
INTENT(in) :: hi
891 REAL(
dp),
INTENT(in) :: alpha
892 REAL(
dp),
INTENT(out) :: exponent
895 REAL(
dp) :: multiplier
901 multiplier = multiplier*alpha
902 exponent = exponent + (multiplier/i)
904 END SUBROUTINE calculate_exponent
916 ELEMENTAL SUBROUTINE calculate_exponent_derivative(hi, alpha, exponent, derivative)
917 INTEGER,
INTENT(in) :: hi
918 REAL(
dp),
INTENT(in) :: alpha
919 REAL(
dp),
INTENT(out) :: exponent, derivative
922 REAL(
dp) :: multiplier
929 derivative = derivative + multiplier
930 multiplier = multiplier*alpha
931 exponent = exponent + (multiplier/i)
933 END SUBROUTINE calculate_exponent_derivative
947 SUBROUTINE get_q0_on_grid_vdw(total_rho, gradient_rho, q0, dq0_drho, dq0_dgradrho, dispersion_env)
955 REAL(
dp),
INTENT(IN) :: total_rho(:), gradient_rho(:, :)
956 REAL(
dp),
INTENT(OUT) :: q0(:), dq0_drho(:), dq0_dgradrho(:)
959 INTEGER,
PARAMETER :: m_cut = 12
960 REAL(
dp),
PARAMETER :: lda_a = 0.031091_dp, lda_a1 = 0.2137_dp, lda_b1 = 7.5957_dp, &
961 lda_b2 = 3.5876_dp, lda_b3 = 1.6382_dp, lda_b4 = 0.49294_dp
964 REAL(
dp) :: dq0_dq, exponent, gradient_correction, &
965 kf, lda_1, lda_2, q, q__q_cut, q_cut, &
966 q_min, r_s, sqrt_r_s, z_ab
968 q_cut = dispersion_env%q_cut
969 q_min = dispersion_env%q_min
970 SELECT CASE (dispersion_env%nl_type)
972 cpabort(
"Unknown vdW-DF functional")
982 dq0_dgradrho(:) = 0.0_dp
984 DO i_grid = 1,
SIZE(total_rho)
992 IF (total_rho(i_grid) < epsr) cycle
996 kf = (3.0_dp*
pi*
pi*total_rho(i_grid))**(1.0_dp/3.0_dp)
997 r_s = (3.0_dp/(4.0_dp*
pi*total_rho(i_grid)))**(1.0_dp/3.0_dp)
1000 gradient_correction = -z_ab/(36.0_dp*kf*total_rho(i_grid)**2) &
1001 *(gradient_rho(i_grid, 1)**2 + gradient_rho(i_grid, 2)**2 + gradient_rho(i_grid, 3)**2)
1003 lda_1 = 8.0_dp*
pi/3.0_dp*(lda_a*(1.0_dp + lda_a1*r_s))
1004 lda_2 = 2.0_dp*lda_a*(lda_b1*sqrt_r_s + lda_b2*r_s + lda_b3*r_s*sqrt_r_s + lda_b4*r_s*r_s)
1008 q = kf + lda_1*log(1.0_dp + 1.0_dp/lda_2) + gradient_correction
1014 CALL calculate_exponent_derivative(m_cut, q__q_cut, exponent, dq0_dq)
1015 q0(i_grid) = q_cut*(1.0_dp - exp(-exponent))
1016 dq0_dq = dq0_dq*exp(-exponent)
1021 IF (q0(i_grid) < q_min)
THEN
1036 dq0_drho(i_grid) = dq0_dq*(kf/3.0_dp - 7.0_dp/3.0_dp*gradient_correction &
1037 - 8.0_dp*
pi/9.0_dp*lda_a*lda_a1*r_s*log(1.0_dp + 1.0_dp/lda_2) &
1038 + lda_1/(lda_2*(1.0_dp + lda_2)) &
1039 *(2.0_dp*lda_a*(lda_b1/6.0_dp*sqrt_r_s + lda_b2/3.0_dp*r_s + lda_b3/2.0_dp*r_s*sqrt_r_s &
1040 + 2.0_dp*lda_b4/3.0_dp*r_s**2)))
1042 dq0_dgradrho(i_grid) = total_rho(i_grid)*dq0_dq*2.0_dp*(-z_ab)/(36.0_dp*kf*total_rho(i_grid)**2)
1046 END SUBROUTINE get_q0_on_grid_vdw
1057 PURE SUBROUTINE get_q0_on_grid_rvv10(total_rho, gradient_rho, q0, dq0_drho, dq0_dgradrho, dispersion_env)
1065 REAL(
dp),
INTENT(IN) :: total_rho(:), gradient_rho(:, :)
1066 REAL(
dp),
INTENT(OUT) :: q0(:), dq0_drho(:), dq0_dgradrho(:)
1069 INTEGER,
PARAMETER :: m_cut = 12
1072 REAL(
dp) :: b_value, c_value, dk_dn, dq0_dq, dw0_dn, &
1073 exponent, gmod2, k, mod_grad, q, &
1074 q__q_cut, q_cut, q_min, w0, wg2, wp2
1076 q_cut = dispersion_env%q_cut
1077 q_min = dispersion_env%q_min
1078 b_value = dispersion_env%b_value
1079 c_value = dispersion_env%c_value
1083 dq0_drho(:) = 0.0_dp
1084 dq0_dgradrho(:) = 0.0_dp
1086 DO i_grid = 1,
SIZE(total_rho)
1088 gmod2 = gradient_rho(i_grid, 1)**2 + gradient_rho(i_grid, 2)**2 + gradient_rho(i_grid, 3)**2
1091 IF (total_rho(i_grid) > epsr)
THEN
1095 mod_grad = sqrt(gmod2)
1097 wp2 = 16.0_dp*
pi*total_rho(i_grid)
1098 wg2 = 4_dp*c_value*(mod_grad/total_rho(i_grid))**4
1100 k = b_value*3.0_dp*
pi*((total_rho(i_grid)/(9.0_dp*
pi))**(1.0_dp/6.0_dp))
1101 w0 = sqrt(wg2 + wp2/3.0_dp)
1108 CALL calculate_exponent_derivative(m_cut, q__q_cut, exponent, dq0_dq)
1109 q0(i_grid) = q_cut*(1.0_dp - exp(-exponent))
1110 dq0_dq = dq0_dq*exp(-exponent)
1113 IF (q0(i_grid) < q_min)
THEN
1118 dw0_dn = 1.0_dp/(2.0_dp*w0)*(16.0_dp/3.0_dp*
pi - 4.0_dp*wg2/total_rho(i_grid))
1119 dk_dn = k/(6.0_dp*total_rho(i_grid))
1121 dq0_drho(i_grid) = dq0_dq*1.0_dp/(k**2.0)*(dw0_dn*k - dk_dn*w0)
1122 dq0_dgradrho(i_grid) = dq0_dq*1.0_dp/(2.0_dp*k*w0)*4.0_dp*wg2/gmod2
1127 END SUBROUTINE get_q0_on_grid_rvv10
1136 SUBROUTINE get_q0_on_grid_eo_vdw(total_rho, gradient_rho, q0, dispersion_env)
1138 REAL(
dp),
INTENT(IN) :: total_rho(:), gradient_rho(:, :)
1139 REAL(
dp),
INTENT(OUT) :: q0(:)
1142 INTEGER,
PARAMETER :: m_cut = 12
1143 REAL(
dp),
PARAMETER :: lda_a = 0.031091_dp, lda_a1 = 0.2137_dp, lda_b1 = 7.5957_dp, &
1144 lda_b2 = 3.5876_dp, lda_b3 = 1.6382_dp, lda_b4 = 0.49294_dp
1147 REAL(
dp) :: exponent, gradient_correction, kf, &
1148 lda_1, lda_2, q, q__q_cut, q_cut, &
1149 q_min, r_s, sqrt_r_s, z_ab
1151 q_cut = dispersion_env%q_cut
1152 q_min = dispersion_env%q_min
1153 SELECT CASE (dispersion_env%nl_type)
1155 cpabort(
"Unknown vdW-DF functional")
1164 DO i_grid = 1,
SIZE(total_rho)
1171 IF (total_rho(i_grid) < epsr) cycle
1175 kf = (3.0_dp*
pi*
pi*total_rho(i_grid))**(1.0_dp/3.0_dp)
1176 r_s = (3.0_dp/(4.0_dp*
pi*total_rho(i_grid)))**(1.0_dp/3.0_dp)
1177 sqrt_r_s = sqrt(r_s)
1179 gradient_correction = -z_ab/(36.0_dp*kf*total_rho(i_grid)**2) &
1180 *(gradient_rho(i_grid, 1)**2 + gradient_rho(i_grid, 2)**2 + gradient_rho(i_grid, 3)**2)
1182 lda_1 = 8.0_dp*
pi/3.0_dp*(lda_a*(1.0_dp + lda_a1*r_s))
1183 lda_2 = 2.0_dp*lda_a*(lda_b1*sqrt_r_s + lda_b2*r_s + lda_b3*r_s*sqrt_r_s + lda_b4*r_s*r_s)
1187 q = kf + lda_1*log(1.0_dp + 1.0_dp/lda_2) + gradient_correction
1194 CALL calculate_exponent(m_cut, q__q_cut, exponent)
1195 q0(i_grid) = q_cut*(1.0_dp - exp(-exponent))
1201 IF (q0(i_grid) < q_min)
THEN
1206 END SUBROUTINE get_q0_on_grid_eo_vdw
1215 PURE SUBROUTINE get_q0_on_grid_eo_rvv10(total_rho, gradient_rho, q0, dispersion_env)
1217 REAL(
dp),
INTENT(IN) :: total_rho(:), gradient_rho(:, :)
1218 REAL(
dp),
INTENT(OUT) :: q0(:)
1221 INTEGER,
PARAMETER :: m_cut = 12
1224 REAL(
dp) :: b_value, c_value, exponent, gmod2, k, q, &
1225 q__q_cut, q_cut, q_min, w0, wg2, wp2
1227 q_cut = dispersion_env%q_cut
1228 q_min = dispersion_env%q_min
1229 b_value = dispersion_env%b_value
1230 c_value = dispersion_env%c_value
1235 DO i_grid = 1,
SIZE(total_rho)
1237 gmod2 = gradient_rho(i_grid, 1)**2 + gradient_rho(i_grid, 2)**2 + gradient_rho(i_grid, 3)**2
1240 IF (total_rho(i_grid) > epsr)
THEN
1244 wp2 = 16.0_dp*
pi*total_rho(i_grid)
1245 wg2 = 4_dp*c_value*(gmod2*gmod2)/(total_rho(i_grid)**4)
1247 k = b_value*3.0_dp*
pi*((total_rho(i_grid)/(9.0_dp*
pi))**(1.0_dp/6.0_dp))
1248 w0 = sqrt(wg2 + wp2/3.0_dp)
1255 CALL calculate_exponent(m_cut, q__q_cut, exponent)
1256 q0(i_grid) = q_cut*(1.0_dp - exp(-exponent))
1258 IF (q0(i_grid) < q_min)
THEN
1266 END SUBROUTINE get_q0_on_grid_eo_rvv10
1280 SUBROUTINE spline_interpolation(x, d2y_dx2, evaluation_points, values)
1281 REAL(
dp),
INTENT(in) :: x(:), d2y_dx2(:, :), evaluation_points(:)
1282 REAL(
dp),
INTENT(out) :: values(:, :)
1284 INTEGER :: i_grid, index, lower_bound, &
1285 ngrid_points, nx, p_i, upper_bound
1286 REAL(
dp) :: a, b, c, const, d, dx
1287 REAL(
dp),
ALLOCATABLE :: y(:)
1290 ngrid_points =
SIZE(evaluation_points)
1303 DO i_grid = 1, ngrid_points
1306 DO WHILE ((upper_bound - lower_bound) > 1)
1307 index = (upper_bound + lower_bound)/2
1308 IF (evaluation_points(i_grid) > x(index))
THEN
1315 dx = x(upper_bound) - x(lower_bound)
1316 const = dx*dx/6.0_dp
1318 a = (x(upper_bound) - evaluation_points(i_grid))/dx
1319 b = (evaluation_points(i_grid) - x(lower_bound))/dx
1320 c = (a**3 - a)*const
1321 d = (b**3 - b)*const
1326 values(i_grid, p_i) = a*y(lower_bound) + b*y(upper_bound) &
1327 + (c*d2y_dx2(p_i, lower_bound) + d*d2y_dx2(p_i, upper_bound))
1334 END SUBROUTINE spline_interpolation
1344 SUBROUTINE initialize_spline_interpolation(x, d2y_dx2)
1346 REAL(
dp),
INTENT(in) :: x(:)
1347 REAL(
dp),
INTENT(inout) :: d2y_dx2(:, :)
1349 INTEGER :: index, nx, p_i
1350 REAL(
dp) :: temp1, temp2
1351 REAL(
dp),
ALLOCATABLE :: temp_array(:), y(:)
1361 ALLOCATE (temp_array(nx), y(nx))
1373 d2y_dx2(p_i, 1) = 0.0_dp
1374 temp_array(1) = 0.0_dp
1375 DO index = 2, nx - 1
1376 temp1 = (x(index) - x(index - 1))/(x(index + 1) - x(index - 1))
1377 temp2 = temp1*d2y_dx2(p_i, index - 1) + 2.0_dp
1378 d2y_dx2(p_i, index) = (temp1 - 1.0_dp)/temp2
1379 temp_array(index) = (y(index + 1) - y(index))/(x(index + 1) - x(index)) &
1380 - (y(index) - y(index - 1))/(x(index) - x(index - 1))
1381 temp_array(index) = (6.0_dp*temp_array(index)/(x(index + 1) - x(index - 1)) &
1382 - temp1*temp_array(index - 1))/temp2
1384 d2y_dx2(p_i, nx) = 0.0_dp
1385 DO index = nx - 1, 1, -1
1386 d2y_dx2(p_i, index) = d2y_dx2(p_i, index)*d2y_dx2(p_i, index + 1) + temp_array(index)
1391 DEALLOCATE (temp_array, y)
1394 END SUBROUTINE initialize_spline_interpolation
1408 SUBROUTINE interpolate_kernel(k, kernel_of_k, dispersion_env)
1409 REAL(
dp),
INTENT(in) :: k
1410 REAL(
dp),
INTENT(out) :: kernel_of_k(:, :)
1413 INTEGER :: k_i, nr_points, q1_i, q2_i
1414 REAL(
dp) :: a, b, c, const, d, dk, r_max
1415 REAL(
dp),
DIMENSION(:, :, :),
POINTER :: d2phi_dk2, kernel
1417 nr_points = dispersion_env%nr_points
1418 r_max = dispersion_env%r_max
1419 dk = dispersion_env%dk
1420 kernel => dispersion_env%kernel
1421 d2phi_dk2 => dispersion_env%d2phi_dk2
1428 cpassert(k < nr_points*dk)
1430 kernel_of_k = 0.0_dp
1439 IF (mod(k, dk) == 0)
THEN
1440 DO q1_i = 1, dispersion_env%Nqs
1442 kernel_of_k(q1_i, q2_i) = kernel(k_i, q1_i, q2_i)
1443 kernel_of_k(q2_i, q1_i) = kernel(k_i, q2_i, q1_i)
1451 const = dk*dk/6.0_dp
1452 a = (dk*(k_i + 1.0_dp) - k)/dk
1454 c = (a**3 - a)*const
1455 d = (b**3 - b)*const
1456 DO q1_i = 1, dispersion_env%Nqs
1458 kernel_of_k(q1_i, q2_i) = a*kernel(k_i, q1_i, q2_i) + b*kernel(k_i + 1, q1_i, q2_i) &
1459 + (c*d2phi_dk2(k_i, q1_i, q2_i) + d*d2phi_dk2(k_i + 1, q1_i, q2_i))
1460 kernel_of_k(q2_i, q1_i) = kernel_of_k(q1_i, q2_i)
1464 END SUBROUTINE interpolate_kernel
1474 SUBROUTINE interpolate_dkernel_dk(k, dkernel_of_dk, dispersion_env)
1475 REAL(
dp),
INTENT(in) :: k
1476 REAL(
dp),
INTENT(out) :: dkernel_of_dk(:, :)
1479 INTEGER :: k_i, nr_points, q1_i, q2_i
1480 REAL(
dp) :: a, b, dadk, dbdk, dcdk, dddk, dk, dk_6
1481 REAL(
dp),
DIMENSION(:, :, :),
POINTER :: d2phi_dk2, kernel
1483 nr_points = dispersion_env%nr_points
1484 dk = dispersion_env%dk
1485 kernel => dispersion_env%kernel
1486 d2phi_dk2 => dispersion_env%d2phi_dk2
1489 cpassert(k < nr_points*dk)
1491 dkernel_of_dk = 0.0_dp
1494 a = (dk*(k_i + 1.0_dp) - k)/dk
1498 dcdk = -(3*a**2 - 1.0_dp)*dk_6
1499 dddk = (3*b**2 - 1.0_dp)*dk_6
1500 DO q1_i = 1, dispersion_env%Nqs
1502 dkernel_of_dk(q1_i, q2_i) = dadk*kernel(k_i, q1_i, q2_i) + dbdk*kernel(k_i + 1, q1_i, q2_i) &
1503 + dcdk*d2phi_dk2(k_i, q1_i, q2_i) + dddk*d2phi_dk2(k_i + 1, q1_i, q2_i)
1504 dkernel_of_dk(q2_i, q1_i) = dkernel_of_dk(q1_i, q2_i)
1508 END SUBROUTINE interpolate_dkernel_dk
collects all references to literature in CP2K as new algorithms / method are included from literature...
integer, save, public dion2004
integer, save, public romanperez2009
integer, save, public sabatini2013
Utility routines to open and close files. Tracking of preconnections.
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public default_string_length
Definition of mathematical constants and functions.
real(kind=dp), parameter, public pi
real(kind=dp), parameter, public rootpi
Interface to the message passing library MPI.
integer, parameter, public halfspace
subroutine, public pw_derive(pw, n)
Calculate the derivative of a plane wave vector.
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...
Calculation of non local dispersion functionals Some routines adapted from: Copyright (C) 2001-2009 Q...
subroutine, public qs_dispersion_nonloc_init(dispersion_env, para_env)
...
subroutine, public calculate_dispersion_nonloc(vxc_rho, rho_r, rho_g, edispersion, dispersion_env, energy_only, pw_pool, xc_pw_pool, para_env, virial)
Calculates the non-local vdW functional using the method of Soler For spin polarized cases we use E(a...
Definition of disperson types for DFT calculations.
stores all the informations relevant to an mpi environment
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...