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'
67 TYPE(qs_dispersion_type),
POINTER :: dispersion_env
68 TYPE(mp_para_env_type),
POINTER :: para_env
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)
165 TYPE(pw_r3d_rs_type),
DIMENSION(:),
POINTER :: vxc_rho, rho_r
166 TYPE(pw_c1d_gs_type),
DIMENSION(:),
POINTER :: rho_g
167 REAL(kind=
dp),
INTENT(OUT) :: edispersion
168 TYPE(qs_dispersion_type),
POINTER :: dispersion_env
169 LOGICAL,
INTENT(IN) :: energy_only
170 TYPE(pw_pool_type),
POINTER :: pw_pool, xc_pw_pool
171 TYPE(mp_para_env_type),
POINTER :: para_env
172 TYPE(virial_type),
OPTIONAL,
POINTER :: virial
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
185 TYPE(pw_c1d_gs_type) :: tmp_g, vxc_g
186 TYPE(pw_c1d_gs_type),
ALLOCATABLE,
DIMENSION(:) :: thetas_g
187 TYPE(pw_grid_type),
POINTER :: grid
188 TYPE(pw_r3d_rs_type) :: tmp_r, vxc_r
189 TYPE(pw_r3d_rs_type),
ALLOCATABLE,
DIMENSION(:, :) :: drho_r
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))
226 CALL pw_transfer(rho_g(ispin), tmp_g)
228 CALL pw_transfer(tmp_g, 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
264 CALL pw_transfer(rho_g(ispin), tmp_g)
265 CALL pw_transfer(tmp_g, tmp_r)
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))
394 CALL pw_transfer(tmp_r, 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
439 CALL pw_transfer(thetas_g(i), tmp_r)
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))
523 CALL pw_transfer(tmp_r, tmp_g)
525 CALL pw_transfer(tmp_g, tmp_r)
526 CALL pw_axpy(tmp_r, vxc_r, -1._dp)
528 CALL pw_transfer(vxc_r, tmp_g)
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)
532 CALL pw_transfer(tmp_g, vxc_g)
533 CALL pw_transfer(vxc_g, vxc_r)
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)
575 TYPE(pw_c1d_gs_type),
DIMENSION(:),
INTENT(IN) :: thetas_g
576 TYPE(qs_dispersion_type),
POINTER :: dispersion_env
577 REAL(kind=
dp),
INTENT(OUT) :: vdw_xc_energy
578 LOGICAL,
INTENT(IN) :: energy_only
579 TYPE(virial_type),
OPTIONAL,
POINTER :: virial
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
592 TYPE(pw_grid_type),
POINTER :: grid
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
740 TYPE(qs_dispersion_type),
POINTER :: dispersion_env
741 REAL(
dp),
DIMENSION(:, :),
INTENT(in),
OPTIONAL :: drho
742 REAL(
dp),
INTENT(IN),
OPTIONAL :: dvol
743 TYPE(virial_type),
OPTIONAL,
POINTER :: virial
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(:)
957 TYPE(qs_dispersion_type),
POINTER :: dispersion_env
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(:)
1067 TYPE(qs_dispersion_type),
POINTER :: dispersion_env
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(:)
1140 TYPE(qs_dispersion_type),
POINTER :: dispersion_env
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(:)
1219 TYPE(qs_dispersion_type),
POINTER :: dispersion_env
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(:, :)
1411 TYPE(qs_dispersion_type),
POINTER :: dispersion_env
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(:, :)
1477 TYPE(qs_dispersion_type),
POINTER :: dispersion_env
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.