46#include "./base/base_uses.f90"
52 REAL(KIND=
dp),
PARAMETER :: epsr = 1.e-12_dp
54 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'qs_dispersion_nonloc'
71 CHARACTER(len=*),
PARAMETER :: routinen =
'qs_dispersion_nonloc_init'
73 CHARACTER(LEN=default_path_length) :: filename
74 INTEGER :: funit, handle, nqs, nr_points, q1_i, &
77 CALL timeset(routinen, handle)
79 SELECT CASE (dispersion_env%nl_type)
81 cpabort(
"Unknown vdW-DF functional")
89 vdw_type = dispersion_env%type
90 SELECT CASE (vdw_type)
95 filename = dispersion_env%kernel_file_name
96 IF (para_env%is_source())
THEN
98 CALL open_file(file_name=filename, unit_number=funit, file_form=
"FORMATTED")
99 READ (funit, *) nqs, nr_points
100 READ (funit, *) dispersion_env%r_max
102 CALL para_env%bcast(nqs)
103 CALL para_env%bcast(nr_points)
104 CALL para_env%bcast(dispersion_env%r_max)
105 ALLOCATE (dispersion_env%q_mesh(nqs), dispersion_env%kernel(0:nr_points, nqs, nqs), &
106 dispersion_env%d2phi_dk2(0:nr_points, nqs, nqs))
107 dispersion_env%nqs = nqs
108 dispersion_env%nr_points = nr_points
109 IF (para_env%is_source())
THEN
111 READ (funit,
"(1p, 4e23.14)") dispersion_env%q_mesh
117 READ (funit,
"(1p, 4e23.14)") dispersion_env%kernel(0:nr_points, q1_i, q2_i)
118 dispersion_env%kernel(0:nr_points, q2_i, q1_i) = dispersion_env%kernel(0:nr_points, q1_i, q2_i)
127 READ (funit,
"(1p, 4e23.14)") dispersion_env%d2phi_dk2(0:nr_points, q1_i, q2_i)
128 dispersion_env%d2phi_dk2(0:nr_points, q2_i, q1_i) = dispersion_env%d2phi_dk2(0:nr_points, q1_i, q2_i)
133 CALL para_env%bcast(dispersion_env%q_mesh)
134 CALL para_env%bcast(dispersion_env%kernel)
135 CALL para_env%bcast(dispersion_env%d2phi_dk2)
137 ALLOCATE (dispersion_env%d2y_dx2(nqs, nqs))
138 CALL initialize_spline_interpolation(dispersion_env%q_mesh, dispersion_env%d2y_dx2)
140 dispersion_env%q_cut = dispersion_env%q_mesh(nqs)
141 dispersion_env%q_min = dispersion_env%q_mesh(1)
142 dispersion_env%dk = 2.0_dp*
pi/dispersion_env%r_max
146 CALL timestop(handle)
165 dispersion_env, energy_only, pw_pool, xc_pw_pool, para_env, virial)
168 REAL(kind=
dp),
INTENT(OUT) :: edispersion
170 LOGICAL,
INTENT(IN) :: energy_only
175 CHARACTER(LEN=*),
PARAMETER :: routinen =
'calculate_dispersion_nonloc'
176 INTEGER,
DIMENSION(3, 3),
PARAMETER :: nd = reshape((/1, 0, 0, 0, 1, 0, 0, 0, 1/), (/3, 3/))
178 INTEGER :: handle, i, i_grid, idir, ispin, nl_type, &
179 np, nspin, p, q, r, s
180 INTEGER,
DIMENSION(1:3) :: hi, lo, n
181 LOGICAL :: use_virial
182 REAL(kind=
dp) :: b_value, beta, const, ec_nl, sumnp
183 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: dq0_dgradrho, dq0_drho, hpot, potential, &
185 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: drho, thetas
192 CALL timeset(routinen, handle)
194 cpassert(
ASSOCIATED(rho_r))
195 cpassert(
ASSOCIATED(rho_g))
196 cpassert(
ASSOCIATED(pw_pool))
198 IF (
PRESENT(virial))
THEN
199 use_virial = virial%pv_calculate .AND. (.NOT. virial%pv_numer)
204 cpassert(.NOT. energy_only)
206 IF (.NOT. energy_only)
THEN
207 cpassert(
ASSOCIATED(vxc_rho))
210 nl_type = dispersion_env%nl_type
212 b_value = dispersion_env%b_value
213 beta = 0.03125_dp*(3.0_dp/(b_value**2.0_dp))**0.75_dp
216 const = 1.0_dp/(3.0_dp*
rootpi*b_value**1.5_dp)/(
pi**0.75_dp)
219 CALL pw_pool%create_pw(tmp_g)
220 CALL pw_pool%create_pw(tmp_r)
223 ALLOCATE (drho_r(3, nspin))
226 CALL pw_pool%create_pw(drho_r(idir, ispin))
233 np =
SIZE(tmp_r%array)
234 ALLOCATE (rho(np), drho(np, 3))
236 lo(i) = lbound(tmp_r%array, i)
237 hi(i) = ubound(tmp_r%array, i)
238 n(i) = hi(i) - lo(i) + 1
246 rho(r*n(2)*n(1) + q*n(1) + p + 1) = 0.0_dp
258 drho(r*n(2)*n(1) + q*n(1) + p + 1, i) = 0.0_dp
274 s = r*n(2)*n(1) + q*n(1) + p + 1
275 rho(s) = rho(s) + tmp_r%array(p + lo(1), q + lo(2), r + lo(3))
288 s = r*n(2)*n(1) + q*n(1) + p + 1
289 drho(s, i) = drho(s, i) + drho_r(i, ispin)%array(p + lo(1), q + lo(2), r + lo(3))
304 IF (energy_only)
THEN
306 SELECT CASE (nl_type)
308 cpabort(
"Unknown vdW-DF functional")
310 CALL get_q0_on_grid_eo_vdw(rho, drho, q0, dispersion_env)
312 CALL get_q0_on_grid_eo_rvv10(rho, drho, q0, dispersion_env)
315 ALLOCATE (q0(np), dq0_drho(np), dq0_dgradrho(np))
316 SELECT CASE (nl_type)
318 cpabort(
"Unknown vdW-DF functional")
320 CALL get_q0_on_grid_vdw(rho, drho, q0, dq0_drho, dq0_dgradrho, dispersion_env)
322 CALL get_q0_on_grid_rvv10(rho, drho, q0, dq0_drho, dq0_dgradrho, dispersion_env)
340 ALLOCATE (thetas(np, dispersion_env%nqs))
343 CALL spline_interpolation(dispersion_env%q_mesh, dispersion_env%d2y_dx2, q0, thetas)
348 SELECT CASE (nl_type)
350 cpabort(
"Unknown vdW-DF functional")
354 DO i = 1, dispersion_env%nqs
355 thetas(:, i) = thetas(:, i)*rho(:)
364 IF (rho(i_grid) > epsr)
THEN
365 DO i = 1, dispersion_env%nqs
366 thetas(i_grid, i) = thetas(i_grid, i)*const*rho(i_grid)**(0.75_dp)
369 thetas(i_grid, :) = 0.0_dp
377 lo(i) = lbound(tmp_r%array, i)
378 hi(i) = ubound(tmp_r%array, i)
379 n(i) = hi(i) - lo(i) + 1
381 ALLOCATE (thetas_g(dispersion_env%nqs))
382 DO i = 1, dispersion_env%nqs
389 tmp_r%array(p + lo(1), q + lo(2), r + lo(3)) = thetas(r*n(2)*n(1) + q*n(1) + p + 1, i)
394 CALL pw_pool%create_pw(thetas_g(i))
397 grid => thetas_g(1)%pw_grid
404 CALL para_env%sum(sumnp)
407 CALL vdw_energy(thetas_g, dispersion_env, ec_nl, energy_only, virial)
408 SELECT CASE (nl_type)
410 ec_nl = 0.5_dp*ec_nl + beta*sum(rho(:))*grid%vol/sumnp
415 virial%pv_xc(idir, idir) = virial%pv_xc(idir, idir) + ec_nl
418 CALL vdw_energy(thetas_g, dispersion_env, ec_nl, energy_only)
419 SELECT CASE (nl_type)
421 ec_nl = 0.5_dp*ec_nl + beta*sum(rho(:))*grid%vol/sumnp
424 CALL para_env%sum(ec_nl)
425 IF (nl_type ==
vdw_nl_rvv10) ec_nl = ec_nl*dispersion_env%scale_rvv10
428 IF (energy_only)
THEN
435 lo(i) = lbound(tmp_r%array, i)
436 hi(i) = ubound(tmp_r%array, i)
437 n(i) = hi(i) - lo(i) + 1
439 DO i = 1, dispersion_env%nqs
447 thetas(r*n(2)*n(1) + q*n(1) + p + 1, i) = tmp_r%array(p + lo(1), q + lo(2), r + lo(3))
460 ALLOCATE (potential(np), hpot(np))
463 grid => tmp_g%pw_grid
464 CALL get_potential(q0, dq0_drho, dq0_dgradrho, rho, thetas, potential, hpot, &
465 dispersion_env, drho, grid%dvol, virial)
467 CALL get_potential(q0, dq0_drho, dq0_dgradrho, rho, thetas, potential, hpot, &
470 SELECT CASE (nl_type)
472 potential(:) = (0.5_dp*potential(:) + beta)*dispersion_env%scale_rvv10
473 hpot(:) = 0.5_dp*dispersion_env%scale_rvv10*hpot(:)
475 CALL pw_pool%create_pw(vxc_r)
477 lo(i) = lbound(vxc_r%array, i)
478 hi(i) = ubound(vxc_r%array, i)
479 n(i) = hi(i) - lo(i) + 1
487 vxc_r%array(p + lo(1), q + lo(2), r + lo(3)) = potential(r*n(2)*n(1) + q*n(1) + p + 1)
493 lo(i) = lbound(tmp_r%array, i)
494 hi(i) = ubound(tmp_r%array, i)
495 n(i) = hi(i) - lo(i) + 1
504 tmp_r%array(p + lo(1), q + lo(2), r + lo(3)) = 0.0_dp
516 tmp_r%array(p + lo(1), q + lo(2), r + lo(3)) = tmp_r%array(p + lo(1), q + lo(2), r + lo(3)) &
517 + hpot(r*n(2)*n(1) + q*n(1) + p + 1) &
518 *drho_r(idir, ispin)%array(p + lo(1), q + lo(2), r + lo(3))
527 CALL pw_axpy(tmp_r, vxc_r, -1._dp)
530 CALL pw_pool%give_back_pw(vxc_r)
531 CALL xc_pw_pool%create_pw(vxc_r)
532 CALL xc_pw_pool%create_pw(vxc_g)
536 CALL pw_axpy(vxc_r, vxc_rho(ispin), 1._dp)
538 CALL xc_pw_pool%give_back_pw(vxc_r)
539 CALL xc_pw_pool%give_back_pw(vxc_g)
540 DEALLOCATE (q0, dq0_drho, dq0_dgradrho)
545 DO i = 1, dispersion_env%nqs
546 CALL pw_pool%give_back_pw(thetas_g(i))
550 CALL pw_pool%give_back_pw(drho_r(idir, ispin))
553 CALL pw_pool%give_back_pw(tmp_r)
554 CALL pw_pool%give_back_pw(tmp_g)
556 DEALLOCATE (rho, drho, drho_r, thetas_g)
558 CALL timestop(handle)
575 SUBROUTINE vdw_energy(thetas_g, dispersion_env, vdW_xc_energy, energy_only, virial)
578 REAL(kind=
dp),
INTENT(OUT) :: vdw_xc_energy
579 LOGICAL,
INTENT(IN) :: energy_only
582 CHARACTER(LEN=*),
PARAMETER :: routinen =
'vdW_energy'
584 COMPLEX(KIND=dp) :: uu
585 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:) :: theta
586 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: u_vdw(:, :)
587 INTEGER :: handle, ig, iq, l, m, nl_type, nqs, &
589 LOGICAL :: use_virial
590 REAL(kind=
dp) :: g, g2, g2_last, g_multiplier, gm
591 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: dkernel_of_dk, kernel_of_k
592 REAL(kind=
dp),
DIMENSION(3, 3) :: virial_thread
595 CALL timeset(routinen, handle)
596 nqs = dispersion_env%nqs
598 use_virial =
PRESENT(virial)
599 virial_thread(:, :) = 0.0_dp
601 vdw_xc_energy = 0._dp
602 grid => thetas_g(1)%pw_grid
610 nl_type = dispersion_env%nl_type
612 IF (.NOT. energy_only)
THEN
613 ALLOCATE (u_vdw(grid%ngpts_cut_local, nqs))
629 g2_last = huge(0._dp)
631 ALLOCATE (kernel_of_k(nqs, nqs), dkernel_of_dk(nqs, nqs))
632 ALLOCATE (theta(nqs))
635 DO ig = 1, grid%ngpts_cut_local
637 IF (abs(g2 - g2_last) > 1.e-10)
THEN
640 CALL interpolate_kernel(g, kernel_of_k, dispersion_env)
641 IF (use_virial)
CALL interpolate_dkernel_dk(g, dkernel_of_dk, dispersion_env)
644 theta(iq) = thetas_g(iq)%array(ig)
649 uu = uu + kernel_of_k(q2_i, q1_i)*theta(q1_i)
651 IF (ig < grid%first_gne0)
THEN
652 vdw_xc_energy = vdw_xc_energy + real(uu*conjg(theta(q2_i)), kind=
dp)
654 vdw_xc_energy = vdw_xc_energy + g_multiplier*real(uu*conjg(theta(q2_i)), kind=
dp)
656 IF (.NOT. energy_only) u_vdw(ig, q2_i) = uu
658 IF (use_virial .AND. ig >= grid%first_gne0)
THEN
660 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)
666 virial_thread(l, m) = virial_thread(l, m) - gm*(grid%g(l, ig)*grid%g(m, ig))/g
677 DEALLOCATE (kernel_of_k, dkernel_of_dk)
679 IF (.NOT. energy_only)
THEN
681 DO ig = 1, grid%ngpts_cut_local
683 thetas_g(iq)%array(ig) = u_vdw(ig, iq)
691 IF (.NOT. energy_only)
THEN
695 vdw_xc_energy = vdw_xc_energy*grid%vol*0.5_dp
700 virial%pv_xc(l, m) = virial%pv_xc(l, m) + virial_thread(l, m)
701 virial%pv_xc(m, l) = virial%pv_xc(l, m)
704 virial%pv_xc(l, m) = virial%pv_xc(l, m) + virial_thread(l, m)
708 CALL timestop(handle)
710 END SUBROUTINE vdw_energy
735 SUBROUTINE get_potential(q0, dq0_drho, dq0_dgradrho, total_rho, u_vdW, potential, h_prefactor, &
736 dispersion_env, drho, dvol, virial)
738 REAL(
dp),
DIMENSION(:),
INTENT(in) :: q0, dq0_drho, dq0_dgradrho, total_rho
739 REAL(
dp),
DIMENSION(:, :),
INTENT(in) :: u_vdw
740 REAL(
dp),
DIMENSION(:),
INTENT(out) :: potential, h_prefactor
742 REAL(
dp),
DIMENSION(:, :),
INTENT(in),
OPTIONAL :: drho
743 REAL(
dp),
INTENT(IN),
OPTIONAL :: dvol
746 CHARACTER(len=*),
PARAMETER :: routinen =
'get_potential'
748 INTEGER :: handle, i_grid, l, m, nl_type, nqs, p_i, &
750 LOGICAL :: use_virial
751 REAL(
dp) :: a, b, b_value, c, const, d, dp_dq0, dq, &
752 dq_6, e, f, p, prefactor, tmp_1_2, &
754 REAL(
dp),
ALLOCATABLE,
DIMENSION(:) :: y
755 REAL(
dp),
DIMENSION(3, 3) :: virial_thread
756 REAL(
dp),
DIMENSION(:),
POINTER :: q_mesh
757 REAL(
dp),
DIMENSION(:, :),
POINTER :: d2y_dx2
759 CALL timeset(routinen, handle)
761 use_virial =
PRESENT(virial)
762 cpassert(.NOT. use_virial .OR.
PRESENT(drho))
763 cpassert(.NOT. use_virial .OR.
PRESENT(dvol))
765 virial_thread(:, :) = 0.0_dp
766 b_value = dispersion_env%b_value
767 const = 1.0_dp/(3.0_dp*b_value**(3.0_dp/2.0_dp)*
pi**(5.0_dp/4.0_dp))
771 d2y_dx2 => dispersion_env%d2y_dx2
772 q_mesh => dispersion_env%q_mesh
773 nqs = dispersion_env%nqs
774 nl_type = dispersion_env%nl_type
793 DO i_grid = 1,
SIZE(u_vdw, 1)
797 DO WHILE ((q_hi - q_low) > 1)
798 q = int((q_hi + q_low)/2)
799 IF (q_mesh(q) > q0(i_grid))
THEN
805 IF (q_hi == q_low) cpabort(
"get_potential: qhi == qlow")
807 dq = q_mesh(q_hi) - q_mesh(q_low)
810 a = (q_mesh(q_hi) - q0(i_grid))/dq
811 b = (q0(i_grid) - q_mesh(q_low))/dq
812 c = (a**3 - a)*dq*dq_6
813 d = (b**3 - b)*dq*dq_6
814 e = (3.0_dp*a**2 - 1.0_dp)*dq_6
815 f = (3.0_dp*b**2 - 1.0_dp)*dq_6
820 dp_dq0 = (y(q_hi) - y(q_low))/dq - e*d2y_dx2(p_i, q_low) + f*d2y_dx2(p_i, q_hi)
821 p = a*y(q_low) + b*y(q_hi) + c*d2y_dx2(p_i, q_low) + d*d2y_dx2(p_i, q_hi)
823 SELECT CASE (nl_type)
825 cpabort(
"Unknown vdW-DF functional")
827 potential(i_grid) = potential(i_grid) + u_vdw(i_grid, p_i)*(p + dp_dq0*dq0_drho(i_grid))
828 prefactor = u_vdw(i_grid, p_i)*dp_dq0*dq0_dgradrho(i_grid)
830 IF (total_rho(i_grid) > epsr)
THEN
831 tmp_1_2 = sqrt(total_rho(i_grid))
832 tmp_1_4 = sqrt(tmp_1_2)
833 tmp_3_4 = tmp_1_4*tmp_1_4*tmp_1_4
834 potential(i_grid) = potential(i_grid) &
835 + u_vdw(i_grid, p_i)*(const*0.75_dp/tmp_1_4*p &
836 + const*tmp_3_4*dp_dq0*dq0_drho(i_grid))
837 prefactor = u_vdw(i_grid, p_i)*const*tmp_3_4*dp_dq0*dq0_dgradrho(i_grid)
842 IF (q0(i_grid) .NE. q_mesh(nqs))
THEN
843 h_prefactor(i_grid) = h_prefactor(i_grid) + prefactor
846 IF (use_virial .AND. abs(prefactor) > 0.0_dp)
THEN
847 SELECT CASE (nl_type)
851 prefactor = 0.5_dp*prefactor
853 prefactor = prefactor*dvol
856 virial_thread(l, m) = virial_thread(l, m) - prefactor*drho(i_grid, l)*drho(i_grid, m)
871 virial%pv_xc(l, m) = virial%pv_xc(l, m) + virial_thread(l, m)
872 virial%pv_xc(m, l) = virial%pv_xc(l, m)
875 virial%pv_xc(l, m) = virial%pv_xc(l, m) + virial_thread(l, m)
879 CALL timestop(handle)
880 END SUBROUTINE get_potential
890 ELEMENTAL SUBROUTINE calculate_exponent(hi, alpha, exponent)
891 INTEGER,
INTENT(in) :: hi
892 REAL(
dp),
INTENT(in) :: alpha
893 REAL(
dp),
INTENT(out) :: exponent
896 REAL(
dp) :: multiplier
902 multiplier = multiplier*alpha
903 exponent = exponent + (multiplier/i)
905 END SUBROUTINE calculate_exponent
917 ELEMENTAL SUBROUTINE calculate_exponent_derivative(hi, alpha, exponent, derivative)
918 INTEGER,
INTENT(in) :: hi
919 REAL(
dp),
INTENT(in) :: alpha
920 REAL(
dp),
INTENT(out) :: exponent, derivative
923 REAL(
dp) :: multiplier
930 derivative = derivative + multiplier
931 multiplier = multiplier*alpha
932 exponent = exponent + (multiplier/i)
934 END SUBROUTINE calculate_exponent_derivative
948 SUBROUTINE get_q0_on_grid_vdw(total_rho, gradient_rho, q0, dq0_drho, dq0_dgradrho, dispersion_env)
956 REAL(
dp),
INTENT(IN) :: total_rho(:), gradient_rho(:, :)
957 REAL(
dp),
INTENT(OUT) :: q0(:), dq0_drho(:), dq0_dgradrho(:)
960 INTEGER,
PARAMETER :: m_cut = 12
961 REAL(
dp),
PARAMETER :: lda_a = 0.031091_dp, lda_a1 = 0.2137_dp, lda_b1 = 7.5957_dp, &
962 lda_b2 = 3.5876_dp, lda_b3 = 1.6382_dp, lda_b4 = 0.49294_dp
965 REAL(
dp) :: dq0_dq, exponent, gradient_correction, &
966 kf, lda_1, lda_2, q, q__q_cut, q_cut, &
967 q_min, r_s, sqrt_r_s, z_ab
969 q_cut = dispersion_env%q_cut
970 q_min = dispersion_env%q_min
971 SELECT CASE (dispersion_env%nl_type)
973 cpabort(
"Unknown vdW-DF functional")
983 dq0_dgradrho(:) = 0.0_dp
985 DO i_grid = 1,
SIZE(total_rho)
993 IF (total_rho(i_grid) < epsr) cycle
997 kf = (3.0_dp*
pi*
pi*total_rho(i_grid))**(1.0_dp/3.0_dp)
998 r_s = (3.0_dp/(4.0_dp*
pi*total_rho(i_grid)))**(1.0_dp/3.0_dp)
1001 gradient_correction = -z_ab/(36.0_dp*kf*total_rho(i_grid)**2) &
1002 *(gradient_rho(i_grid, 1)**2 + gradient_rho(i_grid, 2)**2 + gradient_rho(i_grid, 3)**2)
1004 lda_1 = 8.0_dp*
pi/3.0_dp*(lda_a*(1.0_dp + lda_a1*r_s))
1005 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)
1009 q = kf + lda_1*log(1.0_dp + 1.0_dp/lda_2) + gradient_correction
1015 CALL calculate_exponent_derivative(m_cut, q__q_cut, exponent, dq0_dq)
1016 q0(i_grid) = q_cut*(1.0_dp - exp(-exponent))
1017 dq0_dq = dq0_dq*exp(-exponent)
1022 IF (q0(i_grid) < q_min)
THEN
1037 dq0_drho(i_grid) = dq0_dq*(kf/3.0_dp - 7.0_dp/3.0_dp*gradient_correction &
1038 - 8.0_dp*
pi/9.0_dp*lda_a*lda_a1*r_s*log(1.0_dp + 1.0_dp/lda_2) &
1039 + lda_1/(lda_2*(1.0_dp + lda_2)) &
1040 *(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 &
1041 + 2.0_dp*lda_b4/3.0_dp*r_s**2)))
1043 dq0_dgradrho(i_grid) = total_rho(i_grid)*dq0_dq*2.0_dp*(-z_ab)/(36.0_dp*kf*total_rho(i_grid)**2)
1047 END SUBROUTINE get_q0_on_grid_vdw
1058 PURE SUBROUTINE get_q0_on_grid_rvv10(total_rho, gradient_rho, q0, dq0_drho, dq0_dgradrho, dispersion_env)
1066 REAL(
dp),
INTENT(IN) :: total_rho(:), gradient_rho(:, :)
1067 REAL(
dp),
INTENT(OUT) :: q0(:), dq0_drho(:), dq0_dgradrho(:)
1070 INTEGER,
PARAMETER :: m_cut = 12
1073 REAL(
dp) :: b_value, c_value, dk_dn, dq0_dq, dw0_dn, &
1074 exponent, gmod2, k, mod_grad, q, &
1075 q__q_cut, q_cut, q_min, w0, wg2, wp2
1077 q_cut = dispersion_env%q_cut
1078 q_min = dispersion_env%q_min
1079 b_value = dispersion_env%b_value
1080 c_value = dispersion_env%c_value
1084 dq0_drho(:) = 0.0_dp
1085 dq0_dgradrho(:) = 0.0_dp
1087 DO i_grid = 1,
SIZE(total_rho)
1089 gmod2 = gradient_rho(i_grid, 1)**2 + gradient_rho(i_grid, 2)**2 + gradient_rho(i_grid, 3)**2
1092 IF (total_rho(i_grid) > epsr)
THEN
1096 mod_grad = sqrt(gmod2)
1098 wp2 = 16.0_dp*
pi*total_rho(i_grid)
1099 wg2 = 4_dp*c_value*(mod_grad/total_rho(i_grid))**4
1101 k = b_value*3.0_dp*
pi*((total_rho(i_grid)/(9.0_dp*
pi))**(1.0_dp/6.0_dp))
1102 w0 = sqrt(wg2 + wp2/3.0_dp)
1109 CALL calculate_exponent_derivative(m_cut, q__q_cut, exponent, dq0_dq)
1110 q0(i_grid) = q_cut*(1.0_dp - exp(-exponent))
1111 dq0_dq = dq0_dq*exp(-exponent)
1114 IF (q0(i_grid) < q_min)
THEN
1119 dw0_dn = 1.0_dp/(2.0_dp*w0)*(16.0_dp/3.0_dp*
pi - 4.0_dp*wg2/total_rho(i_grid))
1120 dk_dn = k/(6.0_dp*total_rho(i_grid))
1122 dq0_drho(i_grid) = dq0_dq*1.0_dp/(k**2.0)*(dw0_dn*k - dk_dn*w0)
1123 dq0_dgradrho(i_grid) = dq0_dq*1.0_dp/(2.0_dp*k*w0)*4.0_dp*wg2/gmod2
1128 END SUBROUTINE get_q0_on_grid_rvv10
1137 SUBROUTINE get_q0_on_grid_eo_vdw(total_rho, gradient_rho, q0, dispersion_env)
1139 REAL(
dp),
INTENT(IN) :: total_rho(:), gradient_rho(:, :)
1140 REAL(
dp),
INTENT(OUT) :: q0(:)
1143 INTEGER,
PARAMETER :: m_cut = 12
1144 REAL(
dp),
PARAMETER :: lda_a = 0.031091_dp, lda_a1 = 0.2137_dp, lda_b1 = 7.5957_dp, &
1145 lda_b2 = 3.5876_dp, lda_b3 = 1.6382_dp, lda_b4 = 0.49294_dp
1148 REAL(
dp) :: exponent, gradient_correction, kf, &
1149 lda_1, lda_2, q, q__q_cut, q_cut, &
1150 q_min, r_s, sqrt_r_s, z_ab
1152 q_cut = dispersion_env%q_cut
1153 q_min = dispersion_env%q_min
1154 SELECT CASE (dispersion_env%nl_type)
1156 cpabort(
"Unknown vdW-DF functional")
1165 DO i_grid = 1,
SIZE(total_rho)
1172 IF (total_rho(i_grid) < epsr) cycle
1176 kf = (3.0_dp*
pi*
pi*total_rho(i_grid))**(1.0_dp/3.0_dp)
1177 r_s = (3.0_dp/(4.0_dp*
pi*total_rho(i_grid)))**(1.0_dp/3.0_dp)
1178 sqrt_r_s = sqrt(r_s)
1180 gradient_correction = -z_ab/(36.0_dp*kf*total_rho(i_grid)**2) &
1181 *(gradient_rho(i_grid, 1)**2 + gradient_rho(i_grid, 2)**2 + gradient_rho(i_grid, 3)**2)
1183 lda_1 = 8.0_dp*
pi/3.0_dp*(lda_a*(1.0_dp + lda_a1*r_s))
1184 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)
1188 q = kf + lda_1*log(1.0_dp + 1.0_dp/lda_2) + gradient_correction
1195 CALL calculate_exponent(m_cut, q__q_cut, exponent)
1196 q0(i_grid) = q_cut*(1.0_dp - exp(-exponent))
1202 IF (q0(i_grid) < q_min)
THEN
1207 END SUBROUTINE get_q0_on_grid_eo_vdw
1216 PURE SUBROUTINE get_q0_on_grid_eo_rvv10(total_rho, gradient_rho, q0, dispersion_env)
1218 REAL(
dp),
INTENT(IN) :: total_rho(:), gradient_rho(:, :)
1219 REAL(
dp),
INTENT(OUT) :: q0(:)
1222 INTEGER,
PARAMETER :: m_cut = 12
1225 REAL(
dp) :: b_value, c_value, exponent, gmod2, k, q, &
1226 q__q_cut, q_cut, q_min, w0, wg2, wp2
1228 q_cut = dispersion_env%q_cut
1229 q_min = dispersion_env%q_min
1230 b_value = dispersion_env%b_value
1231 c_value = dispersion_env%c_value
1236 DO i_grid = 1,
SIZE(total_rho)
1238 gmod2 = gradient_rho(i_grid, 1)**2 + gradient_rho(i_grid, 2)**2 + gradient_rho(i_grid, 3)**2
1241 IF (total_rho(i_grid) > epsr)
THEN
1245 wp2 = 16.0_dp*
pi*total_rho(i_grid)
1246 wg2 = 4_dp*c_value*(gmod2*gmod2)/(total_rho(i_grid)**4)
1248 k = b_value*3.0_dp*
pi*((total_rho(i_grid)/(9.0_dp*
pi))**(1.0_dp/6.0_dp))
1249 w0 = sqrt(wg2 + wp2/3.0_dp)
1256 CALL calculate_exponent(m_cut, q__q_cut, exponent)
1257 q0(i_grid) = q_cut*(1.0_dp - exp(-exponent))
1259 IF (q0(i_grid) < q_min)
THEN
1267 END SUBROUTINE get_q0_on_grid_eo_rvv10
1281 SUBROUTINE spline_interpolation(x, d2y_dx2, evaluation_points, values)
1282 REAL(
dp),
INTENT(in) :: x(:), d2y_dx2(:, :), evaluation_points(:)
1283 REAL(
dp),
INTENT(out) :: values(:, :)
1285 INTEGER :: i_grid, index, lower_bound, &
1286 ngrid_points, nx, p_i, upper_bound
1287 REAL(
dp) :: a, b, c, const, d, dx
1288 REAL(
dp),
ALLOCATABLE :: y(:)
1291 ngrid_points =
SIZE(evaluation_points)
1304 DO i_grid = 1, ngrid_points
1307 DO WHILE ((upper_bound - lower_bound) > 1)
1308 index = (upper_bound + lower_bound)/2
1309 IF (evaluation_points(i_grid) > x(index))
THEN
1316 dx = x(upper_bound) - x(lower_bound)
1317 const = dx*dx/6.0_dp
1319 a = (x(upper_bound) - evaluation_points(i_grid))/dx
1320 b = (evaluation_points(i_grid) - x(lower_bound))/dx
1321 c = (a**3 - a)*const
1322 d = (b**3 - b)*const
1327 values(i_grid, p_i) = a*y(lower_bound) + b*y(upper_bound) &
1328 + (c*d2y_dx2(p_i, lower_bound) + d*d2y_dx2(p_i, upper_bound))
1335 END SUBROUTINE spline_interpolation
1345 SUBROUTINE initialize_spline_interpolation(x, d2y_dx2)
1347 REAL(
dp),
INTENT(in) :: x(:)
1348 REAL(
dp),
INTENT(inout) :: d2y_dx2(:, :)
1350 INTEGER :: index, nx, p_i
1351 REAL(
dp) :: temp1, temp2
1352 REAL(
dp),
ALLOCATABLE :: temp_array(:), y(:)
1362 ALLOCATE (temp_array(nx), y(nx))
1374 d2y_dx2(p_i, 1) = 0.0_dp
1375 temp_array(1) = 0.0_dp
1376 DO index = 2, nx - 1
1377 temp1 = (x(index) - x(index - 1))/(x(index + 1) - x(index - 1))
1378 temp2 = temp1*d2y_dx2(p_i, index - 1) + 2.0_dp
1379 d2y_dx2(p_i, index) = (temp1 - 1.0_dp)/temp2
1380 temp_array(index) = (y(index + 1) - y(index))/(x(index + 1) - x(index)) &
1381 - (y(index) - y(index - 1))/(x(index) - x(index - 1))
1382 temp_array(index) = (6.0_dp*temp_array(index)/(x(index + 1) - x(index - 1)) &
1383 - temp1*temp_array(index - 1))/temp2
1385 d2y_dx2(p_i, nx) = 0.0_dp
1386 DO index = nx - 1, 1, -1
1387 d2y_dx2(p_i, index) = d2y_dx2(p_i, index)*d2y_dx2(p_i, index + 1) + temp_array(index)
1392 DEALLOCATE (temp_array, y)
1395 END SUBROUTINE initialize_spline_interpolation
1409 SUBROUTINE interpolate_kernel(k, kernel_of_k, dispersion_env)
1410 REAL(
dp),
INTENT(in) :: k
1411 REAL(
dp),
INTENT(out) :: kernel_of_k(:, :)
1414 INTEGER :: k_i, nr_points, q1_i, q2_i
1415 REAL(
dp) :: a, b, c, const, d, dk, r_max
1416 REAL(
dp),
DIMENSION(:, :, :),
POINTER :: d2phi_dk2, kernel
1418 nr_points = dispersion_env%nr_points
1419 r_max = dispersion_env%r_max
1420 dk = dispersion_env%dk
1421 kernel => dispersion_env%kernel
1422 d2phi_dk2 => dispersion_env%d2phi_dk2
1429 cpassert(k < nr_points*dk)
1431 kernel_of_k = 0.0_dp
1440 IF (mod(k, dk) == 0)
THEN
1441 DO q1_i = 1, dispersion_env%Nqs
1443 kernel_of_k(q1_i, q2_i) = kernel(k_i, q1_i, q2_i)
1444 kernel_of_k(q2_i, q1_i) = kernel(k_i, q2_i, q1_i)
1452 const = dk*dk/6.0_dp
1453 a = (dk*(k_i + 1.0_dp) - k)/dk
1455 c = (a**3 - a)*const
1456 d = (b**3 - b)*const
1457 DO q1_i = 1, dispersion_env%Nqs
1459 kernel_of_k(q1_i, q2_i) = a*kernel(k_i, q1_i, q2_i) + b*kernel(k_i + 1, q1_i, q2_i) &
1460 + (c*d2phi_dk2(k_i, q1_i, q2_i) + d*d2phi_dk2(k_i + 1, q1_i, q2_i))
1461 kernel_of_k(q2_i, q1_i) = kernel_of_k(q1_i, q2_i)
1465 END SUBROUTINE interpolate_kernel
1475 SUBROUTINE interpolate_dkernel_dk(k, dkernel_of_dk, dispersion_env)
1476 REAL(
dp),
INTENT(in) :: k
1477 REAL(
dp),
INTENT(out) :: dkernel_of_dk(:, :)
1480 INTEGER :: k_i, nr_points, q1_i, q2_i
1481 REAL(
dp) :: a, b, dadk, dbdk, dcdk, dddk, dk, dk_6
1482 REAL(
dp),
DIMENSION(:, :, :),
POINTER :: d2phi_dk2, kernel
1484 nr_points = dispersion_env%nr_points
1485 dk = dispersion_env%dk
1486 kernel => dispersion_env%kernel
1487 d2phi_dk2 => dispersion_env%d2phi_dk2
1490 cpassert(k < nr_points*dk)
1492 dkernel_of_dk = 0.0_dp
1495 a = (dk*(k_i + 1.0_dp) - k)/dk
1499 dcdk = -(3*a**2 - 1.0_dp)*dk_6
1500 dddk = (3*b**2 - 1.0_dp)*dk_6
1501 DO q1_i = 1, dispersion_env%Nqs
1503 dkernel_of_dk(q1_i, q2_i) = dadk*kernel(k_i, q1_i, q2_i) + dbdk*kernel(k_i + 1, q1_i, q2_i) &
1504 + dcdk*d2phi_dk2(k_i, q1_i, q2_i) + dddk*d2phi_dk2(k_i + 1, q1_i, q2_i)
1505 dkernel_of_dk(q2_i, q1_i) = dkernel_of_dk(q1_i, q2_i)
1509 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_path_length
Definition of mathematical constants and functions.
real(kind=dp), parameter, public pi
real(kind=dp), parameter, public rootpi
complex(kind=dp), parameter, public z_zero
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 ...