56#include "./base/base_uses.f90"
62 REAL(KIND=
dp),
PARAMETER :: epsr = 1.e-12_dp
63 INTEGER,
DIMENSION(3, 3),
PARAMETER :: nd = reshape([1, 0, 0, 0, 1, 0, 0, 0, 1], [3, 3])
65 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'qs_dispersion_nonloc'
84 CHARACTER(len=*),
PARAMETER :: routinen =
'qs_dispersion_nonloc_init'
86 CHARACTER(LEN=default_path_length) :: filename
87 INTEGER :: funit, handle, ipair, itable, nqs, &
90 CALL timeset(routinen, handle)
92 SELECT CASE (dispersion_env%nl_type)
94 cpabort(
"Unknown vdW-DF functional")
102 vdw_type = dispersion_env%type
103 SELECT CASE (vdw_type)
108 filename = dispersion_env%kernel_file_name
109 IF (para_env%is_source())
THEN
111 CALL open_file(file_name=filename, unit_number=funit, file_form=
"FORMATTED")
112 READ (funit, *) nqs, nr_points
113 READ (funit, *) dispersion_env%r_max
115 CALL para_env%bcast(nqs)
116 CALL para_env%bcast(nr_points)
117 CALL para_env%bcast(dispersion_env%r_max)
118 ALLOCATE (dispersion_env%q_mesh(nqs), dispersion_env%kernel_table(nqs*(nqs + 1)/2, 0:nr_points, 2))
119 dispersion_env%nqs = nqs
120 dispersion_env%nr_points = nr_points
121 IF (para_env%is_source())
THEN
123 READ (funit,
"(1p, 4e23.14)") dispersion_env%q_mesh
127 DO ipair = 1, nqs*(nqs + 1)/2
128 READ (funit,
"(1p, 4e23.14)") dispersion_env%kernel_table(ipair, 0:nr_points, itable)
133 CALL para_env%bcast(dispersion_env%q_mesh)
134 CALL para_env%bcast(dispersion_env%kernel_table)
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)
163 dispersion_env, energy_only, pw_pool, para_env, virial)
165 REAL(kind=
dp),
DIMENSION(:) :: rho
166 REAL(kind=
dp),
DIMENSION(:, :) :: drho
167 REAL(kind=
dp),
INTENT(OUT) :: edispersion
169 LOGICAL,
INTENT(IN) :: energy_only
174 CHARACTER(LEN=*),
PARAMETER :: routinen =
'calculate_vxc_nlvdw'
176 INTEGER :: handle, handle_fft, i, i_grid, idir, &
178 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: q_low
179 LOGICAL :: use_virial
180 REAL(kind=
dp) :: b_value, beta, ec_nl, sumnp
181 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: dq0_dgradrho, dq0_drho, hpot, q0, &
183 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: spline_coeff, u_contract
184 REAL(kind=
dp),
CONTIGUOUS,
POINTER :: tmp_1d(:), vxc_1d(:)
190 CALL timeset(routinen, handle)
192 IF (
PRESENT(virial))
THEN
193 use_virial = virial%pv_calculate .AND. (.NOT. virial%pv_numer)
198 cpassert(.NOT. energy_only)
201 nl_type = dispersion_env%nl_type
203 b_value = dispersion_env%b_value
204 beta = 0.03125_dp*(3.0_dp/(b_value**2.0_dp))**0.75_dp
206 CALL pw_pool%create_pw(tmp_g)
207 CALL pw_pool%create_pw(tmp_r)
208 np = pw_pool%pw_grid%ngpts_local
209 tmp_1d(1:np) => tmp_r%array
219 IF (energy_only)
THEN
221 SELECT CASE (nl_type)
223 cpabort(
"Unknown vdW-DF functional")
225 CALL get_q0_on_grid_eo_vdw(rho, drho, q0, dispersion_env)
227 CALL get_q0_on_grid_eo_rvv10(rho, drho, q0, dispersion_env)
230 ALLOCATE (q0(np), dq0_drho(np), dq0_dgradrho(np))
231 SELECT CASE (nl_type)
233 cpabort(
"Unknown vdW-DF functional")
235 CALL get_q0_on_grid_vdw(rho, drho, q0, dq0_drho, dq0_dgradrho, dispersion_env)
237 CALL get_q0_on_grid_rvv10(rho, drho, q0, dq0_drho, dq0_dgradrho, dispersion_env)
243 ALLOCATE (q_low(np), spline_coeff(np, 4), theta_scale(np))
244 CALL prepare_splines(q0, rho, dispersion_env, q_low, spline_coeff, theta_scale)
245 ALLOCATE (thetas_g(dispersion_env%nqs))
246 CALL timeset(
"vdW_theta_forward", handle_fft)
247 DO i = 1, dispersion_env%nqs
248 CALL build_theta(i, q_low, spline_coeff, theta_scale, dispersion_env, tmp_1d)
249 CALL pw_pool%create_pw(thetas_g(i))
252 CALL timestop(handle_fft)
253 DEALLOCATE (spline_coeff, theta_scale)
254 grid => thetas_g(1)%pw_grid
261 CALL para_env%sum(sumnp)
264 CALL vdw_energy(thetas_g, dispersion_env, ec_nl, energy_only, virial)
265 SELECT CASE (nl_type)
267 ec_nl = 0.5_dp*ec_nl + beta*sum(rho(:))*grid%vol/sumnp
272 virial%pv_xc(idir, idir) = virial%pv_xc(idir, idir) + ec_nl
275 CALL vdw_energy(thetas_g, dispersion_env, ec_nl, energy_only)
276 SELECT CASE (nl_type)
278 ec_nl = 0.5_dp*ec_nl + beta*sum(rho(:))*grid%vol/sumnp
281 CALL para_env%sum(ec_nl)
282 IF (nl_type ==
vdw_nl_rvv10) ec_nl = ec_nl*dispersion_env%scale_rvv10
285 IF (energy_only)
THEN
286 DEALLOCATE (q0, q_low)
290 ALLOCATE (u_contract(np, 4), hpot(np))
294 IF (s > 0 .AND. s < dispersion_env%nqs - 1)
THEN
295 IF (q0(i_grid) == dispersion_env%q_mesh(s + 1)) q_low(i_grid) = s + 1
297 u_contract(i_grid, :) = 0.0_dp
300 CALL timeset(
"vdW_theta_inverse", handle_fft)
301 DO i = 1, dispersion_env%nqs
303 CALL accumulate_potential(i, q_low, dispersion_env, tmp_1d, u_contract)
305 CALL timestop(handle_fft)
308 vxc_1d(1:np) => vxc_r%array
310 grid => tmp_g%pw_grid
311 CALL get_potential(q0, dq0_drho, dq0_dgradrho, rho, q_low, u_contract, vxc_1d, hpot, &
312 dispersion_env, drho, grid%dvol, virial)
314 CALL get_potential(q0, dq0_drho, dq0_dgradrho, rho, q_low, u_contract, vxc_1d, hpot, &
317 DEALLOCATE (u_contract, q_low, q0, dq0_drho, dq0_dgradrho)
318 SELECT CASE (nl_type)
322 vxc_1d(i_grid) = (0.5_dp*vxc_1d(i_grid) + beta)*dispersion_env%scale_rvv10
323 hpot(i_grid) = 0.5_dp*dispersion_env%scale_rvv10*hpot(i_grid)
329 CALL combine_nlvdw_potential(vxc_r, drho, hpot, tmp_r, tmp_g, pw_pool)
335 DO i = 1, dispersion_env%nqs
336 CALL pw_pool%give_back_pw(thetas_g(i))
338 CALL pw_pool%give_back_pw(tmp_r)
339 CALL pw_pool%give_back_pw(tmp_g)
341 DEALLOCATE (thetas_g)
343 CALL timestop(handle)
361 TYPE(
pw_r3d_rs_type),
DIMENSION(:),
POINTER :: rho0_r, rho1_r, fxc_rho
363 CHARACTER(len=*),
PARAMETER :: routinen =
'qs_fxc_nlvdw_apply'
365 INTEGER :: handle, ispin, nspins, nsteps, order, vdw
367 REAL(kind=
dp) :: eps_delta
372 CALL timeset(routinen, handle)
382 nspins =
SIZE(rho0_r)
384 CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
385 ALLOCATE (fxc_vdw(nspins))
387 CALL auxbas_pw_pool%create_pw(fxc_vdw(ispin))
390 order, eps_delta, fxc_vdw)
392 CALL pw_axpy(fxc_vdw(ispin), fxc_rho(ispin), 1.0_dp)
393 CALL auxbas_pw_pool%give_back_pw(fxc_vdw(ispin))
399 CALL timestop(handle)
434 INTEGER,
INTENT(IN) :: accuracy
435 REAL(kind=
dp),
INTENT(IN) :: epsrho
438 CHARACTER(len=*),
PARAMETER :: routinen =
'qs_fxc_nlvdw_fdiff'
440 INTEGER :: handle, ispin, istep, np, nspins, nstep
441 REAL(kind=
dp) :: beta, edisp, oeps1
442 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: rho, rho1, rhonl
443 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: drho, drho1, drhonl
444 REAL(kind=
dp),
DIMENSION(-4:4) :: ak
452 CALL timeset(routinen, handle)
455 SELECT CASE (accuracy)
458 ak(-2:2) = [1.0_dp, -8.0_dp, 0.0_dp, 8.0_dp, -1.0_dp]/12.0_dp
461 ak(-3:3) = [-1.0_dp, 9.0_dp, -45.0_dp, 0.0_dp, 45.0_dp, -9.0_dp, 1.0_dp]/60.0_dp
464 ak(-4:4) = [1.0_dp, -32.0_dp/3.0_dp, 56.0_dp, -224.0_dp, 0.0_dp, &
465 224.0_dp, -56.0_dp, 32.0_dp/3.0_dp, -1.0_dp]/280.0_dp
468 CALL get_qs_env(qs_env, dft_control=dft_control, &
469 pw_env=pw_env, para_env=para_env)
470 CALL pw_env_get(pw_env, auxbas_pw_pool=pw_pool)
471 CALL pw_env_get(pw_env, vdw_pw_pool=vdw_pw_pool)
473 nspins = dft_control%nspins
475 ALLOCATE (vxc00(nspins))
477 CALL pw_pool%create_pw(vxc00(ispin))
481 np = vdw_pw_pool%pw_grid%ngpts_local
482 ALLOCATE (rho(np), drho(np, 3))
484 ALLOCATE (rho1(np), drho1(np, 3))
486 ALLOCATE (rhonl(np), drhonl(np, 3))
488 DO istep = -nstep, nstep
490 IF (ak(istep) /= 0.0_dp)
THEN
491 beta = real(istep, kind=
dp)*epsrho
492 rhonl(:) = rho(:) + beta*rho1(:)
493 drhonl(:, :) = drho(:, :) + beta*drho1(:, :)
494 CALL vdw_pw_pool%create_pw(vxcnl)
496 .false., vdw_pw_pool, para_env)
501 CALL vdw_pw_pool%give_back_pw(vxcnl)
503 CALL pw_axpy(vxc00(ispin), fxc_rho(ispin), ak(istep))
509 DEALLOCATE (rho, drho)
510 DEALLOCATE (rho1, drho1)
511 DEALLOCATE (rhonl, drhonl)
513 CALL pw_pool%give_back_pw(vxc00(ispin))
517 oeps1 = 1.0_dp/epsrho
519 CALL pw_scale(fxc_rho(ispin), oeps1)
522 CALL timestop(handle)
536 REAL(kind=
dp),
DIMENSION(:) :: rho
537 REAL(kind=
dp),
DIMENSION(:, :) :: drho
540 CHARACTER(LEN=*),
PARAMETER :: routinen =
'prepare_nlvdw_density'
542 INTEGER :: handle, i, idir, ispin, np, nspins, p, &
544 INTEGER,
DIMENSION(3) :: hi, lo, n
548 CALL timeset(routinen, handle)
552 CALL pw_pool%create_pw(tmp_g)
553 CALL pw_pool%create_pw(tmp_r)
557 CALL xc_pw_pool%create_pw(rho_g)
558 CALL pw_pool%create_pw(rho_tot_g)
563 CALL pw_axpy(tmp_g, rho_tot_g, 1._dp)
566 CALL xc_pw_pool%give_back_pw(rho_g)
568 np =
SIZE(tmp_r%array)
569 cpassert(np ==
SIZE(rho))
570 cpassert(np ==
SIZE(drho, 1))
572 lo(i) = lbound(tmp_r%array, i)
573 hi(i) = ubound(tmp_r%array, i)
574 n(i) = hi(i) - lo(i) + 1
581 s = r*n(2)*n(1) + q*n(1) + p + 1
582 rho(s) = tmp_r%array(p + lo(1), q + lo(2), r + lo(3))
596 s = r*n(2)*n(1) + q*n(1) + p + 1
597 drho(s, idir) = tmp_r%array(p + lo(1), q + lo(2), r + lo(3))
603 CALL pw_pool%give_back_pw(rho_tot_g)
604 CALL pw_pool%give_back_pw(tmp_r)
605 CALL pw_pool%give_back_pw(tmp_g)
607 CALL timestop(handle)
620 SUBROUTINE combine_nlvdw_potential(vxc_r, drho, hpot, tmp_r, tmp_g, pw_pool)
622 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: drho
623 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: hpot
628 CHARACTER(LEN=*),
PARAMETER :: routinen =
'combine_nlvdw_potential'
630 INTEGER :: handle, i, idir, np, p, q, r, s
631 INTEGER,
DIMENSION(1:3) :: hi, lo, n
632 REAL(kind=
dp),
CONTIGUOUS,
POINTER :: tmp_1d(:)
635 CALL timeset(routinen, handle)
637 np =
SIZE(tmp_r%array)
638 tmp_1d(1:np) => tmp_r%array
640 lo(i) = lbound(tmp_r%array, i)
641 hi(i) = ubound(tmp_r%array, i)
642 n(i) = hi(i) - lo(i) + 1
647 CALL pw_pool%create_pw(div_g)
655 s = r*n(2)*n(1) + q*n(1) + p + 1
656 tmp_r%array(p + lo(1), q + lo(2), r + lo(3)) = hpot(s)*drho(s, idir)
663 CALL pw_axpy(tmp_g, div_g, 1._dp)
667 CALL pw_axpy(tmp_r, vxc_r, -1._dp)
669 CALL pw_pool%give_back_pw(div_g)
671 CALL timestop(handle)
673 END SUBROUTINE combine_nlvdw_potential
687 CHARACTER(LEN=*),
PARAMETER :: routinen =
'return_nlvdw_potential'
689 INTEGER :: handle, ispin, nspins
693 CALL timeset(routinen, handle)
695 nspins =
SIZE(vxc_rho)
697 CALL pw_pool%create_pw(tmp_g)
699 CALL xc_pw_pool%create_pw(vxc_g)
701 CALL xc_pw_pool%create_pw(tmp_r)
704 CALL pw_axpy(tmp_r, vxc_rho(ispin), 1._dp)
706 CALL pw_pool%give_back_pw(tmp_g)
707 CALL xc_pw_pool%give_back_pw(vxc_g)
708 CALL xc_pw_pool%give_back_pw(tmp_r)
710 CALL timestop(handle)
727 SUBROUTINE vdw_energy(thetas_g, dispersion_env, vdW_xc_energy, energy_only, virial)
730 REAL(kind=
dp),
INTENT(OUT) :: vdw_xc_energy
731 LOGICAL,
INTENT(IN) :: energy_only
734 CHARACTER(LEN=*),
PARAMETER :: routinen =
'vdW_energy'
735 REAL(kind=
dp),
PARAMETER :: eps_g2 = 1.0e-10_dp
737 INTEGER :: handle, ig, iq, l, m, nl_type, nqs, &
739 LOGICAL :: use_virial
740 REAL(kind=
dp) :: g, g2, g2_last, g_multiplier, gm
741 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: theta_im, theta_re, u_im, u_re
742 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: dkernel_of_dk, kernel_of_k
743 REAL(kind=
dp),
DIMENSION(3, 3) :: virial_thread
746 CALL timeset(routinen, handle)
747 nqs = dispersion_env%nqs
749 use_virial =
PRESENT(virial)
750 virial_thread(:, :) = 0.0_dp
752 vdw_xc_energy = 0._dp
753 grid => thetas_g(1)%pw_grid
761 nl_type = dispersion_env%nl_type
770 g2_last = huge(0._dp)
772 ALLOCATE (kernel_of_k(nqs, nqs))
773 IF (use_virial)
ALLOCATE (dkernel_of_dk(nqs, nqs))
774 ALLOCATE (theta_re(nqs), theta_im(nqs), u_re(nqs), u_im(nqs))
777 DO ig = 1, grid%ngpts_cut_local
779 IF (abs(g2 - g2_last) > eps_g2)
THEN
783 CALL interpolate_kernel(g, kernel_of_k, dispersion_env, dispersion_env%kernel_table, dkernel_of_dk)
785 CALL interpolate_kernel(g, kernel_of_k, dispersion_env, dispersion_env%kernel_table)
791 theta_re(iq) = real(thetas_g(iq)%array(ig), kind=
dp)
792 theta_im(iq) = aimag(thetas_g(iq)%array(ig))
799 u_re(q2_i) = u_re(q2_i) + kernel_of_k(q2_i, q1_i)*theta_re(q1_i)
800 u_im(q2_i) = u_im(q2_i) + kernel_of_k(q2_i, q1_i)*theta_im(q1_i)
805 IF (ig < grid%first_gne0)
THEN
806 vdw_xc_energy = vdw_xc_energy + (u_re(q2_i)*theta_re(q2_i) + u_im(q2_i)*theta_im(q2_i))
808 vdw_xc_energy = vdw_xc_energy &
809 + g_multiplier*(u_re(q2_i)*theta_re(q2_i) + u_im(q2_i)*theta_im(q2_i))
811 IF (.NOT. energy_only) thetas_g(q2_i)%array(ig) = cmplx(u_re(q2_i), u_im(q2_i), kind=
dp)
814 IF (use_virial .AND. ig >= grid%first_gne0)
THEN
820 gm = gm + dkernel_of_dk(q1_i, q2_i) &
821 *(theta_re(q1_i)*theta_re(q2_i) + theta_im(q1_i)*theta_im(q2_i))
825 gm = 0.5_dp*g_multiplier*grid%vol*gm
829 virial_thread(l, m) = virial_thread(l, m) - gm*(grid%g(l, ig)*grid%g(m, ig))/g
836 DEALLOCATE (theta_re, theta_im, u_re, u_im, kernel_of_k)
837 IF (use_virial)
DEALLOCATE (dkernel_of_dk)
841 vdw_xc_energy = vdw_xc_energy*grid%vol*0.5_dp
846 virial%pv_xc(l, m) = virial%pv_xc(l, m) + virial_thread(l, m)
847 virial%pv_xc(m, l) = virial%pv_xc(l, m)
850 virial%pv_xc(l, m) = virial%pv_xc(l, m) + virial_thread(l, m)
854 CALL timestop(handle)
856 END SUBROUTINE vdw_energy
882 SUBROUTINE get_potential(q0, dq0_drho, dq0_dgradrho, total_rho, q_low_grid, u_contract, potential, h_prefactor, &
883 dispersion_env, drho, dvol, virial)
885 REAL(
dp),
DIMENSION(:),
INTENT(in) :: q0, dq0_drho, dq0_dgradrho, total_rho
886 INTEGER,
DIMENSION(:),
INTENT(IN) :: q_low_grid
887 REAL(
dp),
DIMENSION(:, :),
INTENT(in) :: u_contract
888 REAL(
dp),
DIMENSION(:),
INTENT(out) :: potential, h_prefactor
890 REAL(
dp),
DIMENSION(:, :),
INTENT(in),
OPTIONAL :: drho
891 REAL(
dp),
INTENT(IN),
OPTIONAL :: dvol
894 CHARACTER(len=*),
PARAMETER :: routinen =
'get_potential'
896 INTEGER :: handle, i_grid, l, m, nl_type, nqs, &
898 LOGICAL :: use_virial
899 REAL(
dp) :: a, b, b_value, c, const, d, dq, dq_6, e, &
900 f, prefactor, tmp_1_2, tmp_1_4, &
901 tmp_3_4, u_dp_dq0, u_p
902 REAL(
dp),
DIMENSION(3, 3) :: virial_thread
903 REAL(
dp),
DIMENSION(:),
POINTER :: q_mesh
905 CALL timeset(routinen, handle)
907 use_virial =
PRESENT(virial)
908 cpassert(.NOT. use_virial .OR.
PRESENT(drho))
909 cpassert(.NOT. use_virial .OR.
PRESENT(dvol))
911 virial_thread(:, :) = 0.0_dp
912 b_value = dispersion_env%b_value
913 const = 1.0_dp/(3.0_dp*b_value**(3.0_dp/2.0_dp)*
pi**(5.0_dp/4.0_dp))
915 q_mesh => dispersion_env%q_mesh
916 nqs = dispersion_env%nqs
917 nl_type = dispersion_env%nl_type
927 DO i_grid = 1,
SIZE(q0)
928 potential(i_grid) = 0.0_dp
929 h_prefactor(i_grid) = 0.0_dp
930 IF (nl_type ==
vdw_nl_rvv10 .AND. total_rho(i_grid) <= epsr) cycle
931 q_low = q_low_grid(i_grid)
934 dq = q_mesh(q_hi) - q_mesh(q_low)
937 a = (q_mesh(q_hi) - q0(i_grid))/dq
938 b = (q0(i_grid) - q_mesh(q_low))/dq
939 c = (a**3 - a)*dq*dq_6
940 d = (b**3 - b)*dq*dq_6
941 e = (3.0_dp*a**2 - 1.0_dp)*dq_6
942 f = (3.0_dp*b**2 - 1.0_dp)*dq_6
944 u_p = a*u_contract(i_grid, 3) + b*u_contract(i_grid, 4) &
945 + c*u_contract(i_grid, 1) + d*u_contract(i_grid, 2)
946 u_dp_dq0 = (u_contract(i_grid, 4) - u_contract(i_grid, 3))/dq &
947 - e*u_contract(i_grid, 1) + f*u_contract(i_grid, 2)
950 SELECT CASE (nl_type)
952 cpabort(
"Unknown vdW-DF functional")
954 potential(i_grid) = u_p + u_dp_dq0*dq0_drho(i_grid)
955 prefactor = u_dp_dq0*dq0_dgradrho(i_grid)
957 tmp_1_2 = sqrt(total_rho(i_grid))
958 tmp_1_4 = sqrt(tmp_1_2)
959 tmp_3_4 = tmp_1_4*tmp_1_4*tmp_1_4
960 potential(i_grid) = const*0.75_dp/tmp_1_4*u_p + const*tmp_3_4*u_dp_dq0*dq0_drho(i_grid)
961 prefactor = const*tmp_3_4*u_dp_dq0*dq0_dgradrho(i_grid)
963 IF (q0(i_grid) /= q_mesh(nqs))
THEN
964 h_prefactor(i_grid) = prefactor
968 IF (use_virial .AND. abs(prefactor) > 0.0_dp)
THEN
969 IF (nl_type ==
vdw_nl_rvv10) prefactor = 0.5_dp*prefactor
970 prefactor = prefactor*dvol
973 virial_thread(l, m) = virial_thread(l, m) - prefactor*drho(i_grid, l)*drho(i_grid, m)
985 virial%pv_xc(l, m) = virial%pv_xc(l, m) + virial_thread(l, m)
986 virial%pv_xc(m, l) = virial%pv_xc(l, m)
989 virial%pv_xc(l, m) = virial%pv_xc(l, m) + virial_thread(l, m)
993 CALL timestop(handle)
994 END SUBROUTINE get_potential
1004 ELEMENTAL SUBROUTINE calculate_exponent(hi, alpha, exponent)
1005 INTEGER,
INTENT(in) :: hi
1006 REAL(
dp),
INTENT(in) :: alpha
1007 REAL(
dp),
INTENT(out) :: exponent
1010 REAL(
dp) :: multiplier
1016 multiplier = multiplier*alpha
1017 exponent = exponent + (multiplier/i)
1019 END SUBROUTINE calculate_exponent
1031 ELEMENTAL SUBROUTINE calculate_exponent_derivative(hi, alpha, exponent, derivative)
1032 INTEGER,
INTENT(in) :: hi
1033 REAL(
dp),
INTENT(in) :: alpha
1034 REAL(
dp),
INTENT(out) :: exponent, derivative
1037 REAL(
dp) :: multiplier
1044 derivative = derivative + multiplier
1045 multiplier = multiplier*alpha
1046 exponent = exponent + (multiplier/i)
1048 END SUBROUTINE calculate_exponent_derivative
1062 SUBROUTINE get_q0_on_grid_vdw(total_rho, gradient_rho, q0, dq0_drho, dq0_dgradrho, dispersion_env)
1070 REAL(
dp),
INTENT(IN) :: total_rho(:), gradient_rho(:, :)
1071 REAL(
dp),
INTENT(OUT) :: q0(:), dq0_drho(:), dq0_dgradrho(:)
1074 INTEGER,
PARAMETER :: m_cut = 12
1075 REAL(
dp),
PARAMETER :: lda_a = 0.031091_dp, lda_a1 = 0.2137_dp, lda_b1 = 7.5957_dp, &
1076 lda_b2 = 3.5876_dp, lda_b3 = 1.6382_dp, lda_b4 = 0.49294_dp
1079 REAL(
dp) :: dq0_dq, exponent, gradient_correction, &
1080 kf, lda_1, lda_2, q, q__q_cut, q_cut, &
1081 q_min, r_s, sqrt_r_s, z_ab
1083 q_cut = dispersion_env%q_cut
1084 q_min = dispersion_env%q_min
1085 SELECT CASE (dispersion_env%nl_type)
1087 cpabort(
"Unknown vdW-DF functional")
1098 DO i_grid = 1,
SIZE(total_rho)
1100 dq0_drho(i_grid) = 0.0_dp
1101 dq0_dgradrho(i_grid) = 0.0_dp
1109 IF (total_rho(i_grid) < epsr) cycle
1113 kf = (3.0_dp*
pi*
pi*total_rho(i_grid))**(1.0_dp/3.0_dp)
1114 r_s = (3.0_dp/(4.0_dp*
pi*total_rho(i_grid)))**(1.0_dp/3.0_dp)
1115 sqrt_r_s = sqrt(r_s)
1117 gradient_correction = -z_ab/(36.0_dp*kf*total_rho(i_grid)**2) &
1118 *(gradient_rho(i_grid, 1)**2 + gradient_rho(i_grid, 2)**2 + gradient_rho(i_grid, 3)**2)
1120 lda_1 = 8.0_dp*
pi/3.0_dp*(lda_a*(1.0_dp + lda_a1*r_s))
1121 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)
1125 q = kf + lda_1*log(1.0_dp + 1.0_dp/lda_2) + gradient_correction
1131 CALL calculate_exponent_derivative(m_cut, q__q_cut, exponent, dq0_dq)
1132 q0(i_grid) = q_cut*(1.0_dp - exp(-exponent))
1133 dq0_dq = dq0_dq*exp(-exponent)
1138 IF (q0(i_grid) < q_min)
THEN
1153 dq0_drho(i_grid) = dq0_dq*(kf/3.0_dp - 7.0_dp/3.0_dp*gradient_correction &
1154 - 8.0_dp*
pi/9.0_dp*lda_a*lda_a1*r_s*log(1.0_dp + 1.0_dp/lda_2) &
1155 + lda_1/(lda_2*(1.0_dp + lda_2)) &
1156 *(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 &
1157 + 2.0_dp*lda_b4/3.0_dp*r_s**2)))
1159 dq0_dgradrho(i_grid) = total_rho(i_grid)*dq0_dq*2.0_dp*(-z_ab)/(36.0_dp*kf*total_rho(i_grid)**2)
1164 END SUBROUTINE get_q0_on_grid_vdw
1175 SUBROUTINE get_q0_on_grid_rvv10(total_rho, gradient_rho, q0, dq0_drho, dq0_dgradrho, dispersion_env)
1183 REAL(
dp),
INTENT(IN) :: total_rho(:), gradient_rho(:, :)
1184 REAL(
dp),
INTENT(OUT) :: q0(:), dq0_drho(:), dq0_dgradrho(:)
1187 INTEGER,
PARAMETER :: m_cut = 12
1190 REAL(
dp) :: b_value, c_value, dk_dn, dq0_dq, dw0_dn, &
1191 exponent, gmod2, k, mod_grad, q, &
1192 q__q_cut, q_cut, q_min, w0, wg2, wp2
1194 q_cut = dispersion_env%q_cut
1195 q_min = dispersion_env%q_min
1196 b_value = dispersion_env%b_value
1197 c_value = dispersion_env%c_value
1203 DO i_grid = 1,
SIZE(total_rho)
1205 dq0_drho(i_grid) = 0.0_dp
1206 dq0_dgradrho(i_grid) = 0.0_dp
1208 gmod2 = gradient_rho(i_grid, 1)**2 + gradient_rho(i_grid, 2)**2 + gradient_rho(i_grid, 3)**2
1211 IF (total_rho(i_grid) > epsr)
THEN
1215 mod_grad = sqrt(gmod2)
1217 wp2 = 16.0_dp*
pi*total_rho(i_grid)
1218 wg2 = 4_dp*c_value*(mod_grad/total_rho(i_grid))**4
1220 k = b_value*3.0_dp*
pi*((total_rho(i_grid)/(9.0_dp*
pi))**(1.0_dp/6.0_dp))
1221 w0 = sqrt(wg2 + wp2/3.0_dp)
1228 CALL calculate_exponent_derivative(m_cut, q__q_cut, exponent, dq0_dq)
1229 q0(i_grid) = q_cut*(1.0_dp - exp(-exponent))
1230 dq0_dq = dq0_dq*exp(-exponent)
1233 IF (q0(i_grid) < q_min)
THEN
1238 dw0_dn = 1.0_dp/(2.0_dp*w0)*(16.0_dp/3.0_dp*
pi - 4.0_dp*wg2/total_rho(i_grid))
1239 dk_dn = k/(6.0_dp*total_rho(i_grid))
1241 dq0_drho(i_grid) = dq0_dq*1.0_dp/(k**2)*(dw0_dn*k - dk_dn*w0)
1243 IF (gmod2 > 0.0_dp)
THEN
1244 dq0_dgradrho(i_grid) = dq0_dq*1.0_dp/(2.0_dp*k*w0)*4.0_dp*wg2/gmod2
1251 END SUBROUTINE get_q0_on_grid_rvv10
1260 SUBROUTINE get_q0_on_grid_eo_vdw(total_rho, gradient_rho, q0, dispersion_env)
1262 REAL(
dp),
INTENT(IN) :: total_rho(:), gradient_rho(:, :)
1263 REAL(
dp),
INTENT(OUT) :: q0(:)
1266 INTEGER,
PARAMETER :: m_cut = 12
1267 REAL(
dp),
PARAMETER :: lda_a = 0.031091_dp, lda_a1 = 0.2137_dp, lda_b1 = 7.5957_dp, &
1268 lda_b2 = 3.5876_dp, lda_b3 = 1.6382_dp, lda_b4 = 0.49294_dp
1271 REAL(
dp) :: exponent, gradient_correction, kf, &
1272 lda_1, lda_2, q, q__q_cut, q_cut, &
1273 q_min, r_s, sqrt_r_s, z_ab
1275 q_cut = dispersion_env%q_cut
1276 q_min = dispersion_env%q_min
1277 SELECT CASE (dispersion_env%nl_type)
1279 cpabort(
"Unknown vdW-DF functional")
1290 DO i_grid = 1,
SIZE(total_rho)
1298 IF (total_rho(i_grid) < epsr) cycle
1302 kf = (3.0_dp*
pi*
pi*total_rho(i_grid))**(1.0_dp/3.0_dp)
1303 r_s = (3.0_dp/(4.0_dp*
pi*total_rho(i_grid)))**(1.0_dp/3.0_dp)
1304 sqrt_r_s = sqrt(r_s)
1306 gradient_correction = -z_ab/(36.0_dp*kf*total_rho(i_grid)**2) &
1307 *(gradient_rho(i_grid, 1)**2 + gradient_rho(i_grid, 2)**2 + gradient_rho(i_grid, 3)**2)
1309 lda_1 = 8.0_dp*
pi/3.0_dp*(lda_a*(1.0_dp + lda_a1*r_s))
1310 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)
1314 q = kf + lda_1*log(1.0_dp + 1.0_dp/lda_2) + gradient_correction
1321 CALL calculate_exponent(m_cut, q__q_cut, exponent)
1322 q0(i_grid) = q_cut*(1.0_dp - exp(-exponent))
1328 IF (q0(i_grid) < q_min)
THEN
1334 END SUBROUTINE get_q0_on_grid_eo_vdw
1343 SUBROUTINE get_q0_on_grid_eo_rvv10(total_rho, gradient_rho, q0, dispersion_env)
1345 REAL(
dp),
INTENT(IN) :: total_rho(:), gradient_rho(:, :)
1346 REAL(
dp),
INTENT(OUT) :: q0(:)
1349 INTEGER,
PARAMETER :: m_cut = 12
1352 REAL(
dp) :: b_value, c_value, exponent, gmod2, k, q, &
1353 q__q_cut, q_cut, q_min, w0, wg2, wp2
1355 q_cut = dispersion_env%q_cut
1356 q_min = dispersion_env%q_min
1357 b_value = dispersion_env%b_value
1358 c_value = dispersion_env%c_value
1364 DO i_grid = 1,
SIZE(total_rho)
1367 gmod2 = gradient_rho(i_grid, 1)**2 + gradient_rho(i_grid, 2)**2 + gradient_rho(i_grid, 3)**2
1370 IF (total_rho(i_grid) > epsr)
THEN
1374 wp2 = 16.0_dp*
pi*total_rho(i_grid)
1375 wg2 = 4_dp*c_value*(gmod2*gmod2)/(total_rho(i_grid)**4)
1377 k = b_value*3.0_dp*
pi*((total_rho(i_grid)/(9.0_dp*
pi))**(1.0_dp/6.0_dp))
1378 w0 = sqrt(wg2 + wp2/3.0_dp)
1385 CALL calculate_exponent(m_cut, q__q_cut, exponent)
1386 q0(i_grid) = q_cut*(1.0_dp - exp(-exponent))
1388 IF (q0(i_grid) < q_min)
THEN
1397 END SUBROUTINE get_q0_on_grid_eo_rvv10
1408 SUBROUTINE prepare_splines(q0, rho, dispersion_env, q_low, coeff, theta_scale)
1409 REAL(
dp),
INTENT(IN) :: q0(:), rho(:)
1411 INTEGER,
INTENT(OUT) :: q_low(:)
1412 REAL(
dp),
INTENT(OUT) :: coeff(:, :), theta_scale(:)
1414 INTEGER :: i, j, lower, nqs, upper
1416 REAL(
dp) :: a, b, const, dx, dx2_6
1417 REAL(
dp),
POINTER :: q_mesh(:)
1419 q_mesh => dispersion_env%q_mesh
1420 nqs = dispersion_env%nqs
1423 const = 1.0_dp/(3.0_dp*
rootpi*dispersion_env%b_value**1.5_dp)/(
pi**0.75_dp)
1428 IF (rvv10 .AND. rho(i) <= epsr)
THEN
1430 coeff(i, :) = 0.0_dp
1431 theta_scale(i) = 0.0_dp
1436 DO WHILE (upper - lower > 1)
1437 j = (upper + lower)/2
1438 IF (q0(i) > q_mesh(j))
THEN
1445 dx = q_mesh(upper) - q_mesh(lower)
1446 dx2_6 = dx*dx/6.0_dp
1447 a = (q_mesh(upper) - q0(i))/dx
1448 b = (q0(i) - q_mesh(lower))/dx
1451 coeff(i, 3) = (a**3 - a)*dx2_6
1452 coeff(i, 4) = (b**3 - b)*dx2_6
1454 theta_scale(i) = const*rho(i)**0.75_dp
1456 theta_scale(i) = rho(i)
1460 END SUBROUTINE prepare_splines
1471 SUBROUTINE build_theta(iq, q_low, coeff, theta_scale, dispersion_env, theta)
1472 INTEGER,
INTENT(IN) :: iq, q_low(:)
1473 REAL(
dp),
INTENT(IN) :: coeff(:, :), theta_scale(:)
1475 REAL(
dp),
INTENT(OUT) :: theta(:)
1479 REAL(
dp),
POINTER :: d2y(:, :)
1481 d2y => dispersion_env%d2y_dx2
1484 DO i = 1,
SIZE(theta)
1487 IF (lower == 0) cycle
1488 p = coeff(i, 1)*merge(1.0_dp, 0.0_dp, iq == lower) &
1489 + coeff(i, 2)*merge(1.0_dp, 0.0_dp, iq == lower + 1) &
1490 + (coeff(i, 3)*d2y(iq, lower) + coeff(i, 4)*d2y(iq, lower + 1))
1491 theta(i) = p*theta_scale(i)
1494 END SUBROUTINE build_theta
1504 SUBROUTINE accumulate_potential(iq, q_low, dispersion_env, u, u_contract)
1505 INTEGER,
INTENT(IN) :: iq, q_low(:)
1507 REAL(
dp),
INTENT(IN) :: u(:)
1508 REAL(
dp),
INTENT(INOUT) :: u_contract(:, :)
1511 REAL(
dp),
POINTER :: d2y(:, :)
1513 d2y => dispersion_env%d2y_dx2
1518 IF (lower == 0) cycle
1519 u_contract(i, 1) = u_contract(i, 1) + u(i)*d2y(iq, lower)
1520 u_contract(i, 2) = u_contract(i, 2) + u(i)*d2y(iq, lower + 1)
1521 IF (iq == lower) u_contract(i, 3) = u(i)
1522 IF (iq == lower + 1) u_contract(i, 4) = u(i)
1525 END SUBROUTINE accumulate_potential
1535 SUBROUTINE initialize_spline_interpolation(x, d2y_dx2)
1537 REAL(
dp),
INTENT(in) :: x(:)
1538 REAL(
dp),
INTENT(inout) :: d2y_dx2(:, :)
1540 INTEGER :: index, nx, p_i
1541 REAL(
dp) :: temp1, temp2
1542 REAL(
dp),
ALLOCATABLE :: temp_array(:), y(:)
1552 ALLOCATE (temp_array(nx), y(nx))
1564 d2y_dx2(p_i, 1) = 0.0_dp
1565 temp_array(1) = 0.0_dp
1566 DO index = 2, nx - 1
1567 temp1 = (x(index) - x(index - 1))/(x(index + 1) - x(index - 1))
1568 temp2 = temp1*d2y_dx2(p_i, index - 1) + 2.0_dp
1569 d2y_dx2(p_i, index) = (temp1 - 1.0_dp)/temp2
1570 temp_array(index) = (y(index + 1) - y(index))/(x(index + 1) - x(index)) &
1571 - (y(index) - y(index - 1))/(x(index) - x(index - 1))
1572 temp_array(index) = (6.0_dp*temp_array(index)/(x(index + 1) - x(index - 1)) &
1573 - temp1*temp_array(index - 1))/temp2
1575 d2y_dx2(p_i, nx) = 0.0_dp
1576 DO index = nx - 1, 1, -1
1577 d2y_dx2(p_i, index) = d2y_dx2(p_i, index)*d2y_dx2(p_i, index + 1) + temp_array(index)
1582 DEALLOCATE (temp_array, y)
1585 END SUBROUTINE initialize_spline_interpolation
1595 SUBROUTINE interpolate_kernel(k, kernel_of_k, dispersion_env, kernel_table, dkernel_of_dk)
1596 REAL(
dp),
INTENT(IN) :: k
1597 REAL(
dp),
INTENT(OUT) :: kernel_of_k(:, :)
1599 REAL(
dp),
INTENT(IN) :: kernel_table(:, 0:, :)
1600 REAL(
dp),
INTENT(OUT),
OPTIONAL :: dkernel_of_dk(:, :)
1602 INTEGER :: ipair, k_i, q1_i, q2_i
1604 REAL(
dp) :: a, b, c, d, da, db, dc, dd, dk, dk_6, &
1607 dk = dispersion_env%dk
1608 cpassert(k < dispersion_env%nr_points*dk)
1610 on_mesh = mod(k, dk) == 0.0_dp
1611 a = (dk*(k_i + 1.0_dp) - k)/dk
1613 c = (a**3 - a)*(dk*dk/6.0_dp)
1614 d = (b**3 - b)*(dk*dk/6.0_dp)
1615 DO q1_i = 1, dispersion_env%nqs
1618 ipair = q1_i*(q1_i - 1)/2 + q2_i
1620 value = kernel_table(ipair, k_i, 1)
1622 value = a*kernel_table(ipair, k_i, 1) + b*kernel_table(ipair, k_i + 1, 1) &
1623 + (c*kernel_table(ipair, k_i, 2) + d*kernel_table(ipair, k_i + 1, 2))
1625 kernel_of_k(q2_i, q1_i) =
value
1626 kernel_of_k(q1_i, q2_i) =
value
1630 IF (
PRESENT(dkernel_of_dk))
THEN
1634 dc = -(3*a**2 - 1.0_dp)*dk_6
1635 dd = (3*b**2 - 1.0_dp)*dk_6
1636 DO q1_i = 1, dispersion_env%nqs
1639 ipair = q1_i*(q1_i - 1)/2 + q2_i
1640 value = da*kernel_table(ipair, k_i, 1) + db*kernel_table(ipair, k_i + 1, 1) &
1641 + dc*kernel_table(ipair, k_i, 2) + dd*kernel_table(ipair, k_i + 1, 2)
1642 dkernel_of_dk(q2_i, q1_i) =
value
1643 dkernel_of_dk(q1_i, q2_i) =
value
1648 END SUBROUTINE interpolate_kernel
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
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
Utility routines to open and close files.
subroutine, public open_file(file_name, unit_number, file_status, file_form, file_action, file_position, file_pad, file_access, debug)
Opens a file and returns its logical unit number.
subroutine, public close_file(unit_number, file_status)
Closes an open file given by its logical unit number.
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
Interface to the message passing library MPI.
container for various plainwaves related things
subroutine, public pw_env_get(pw_env, pw_pools, cube_info, gridlevel_info, auxbas_pw_pool, auxbas_grid, auxbas_rs_desc, auxbas_rs_grid, rs_descs, rs_grids, xc_pw_pool, vdw_pw_pool, poisson_env, interp_section)
returns the various attributes of the pw env
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 prepare_nlvdw_density(rho_r, rho, drho, pw_pool, xc_pw_pool)
Transform the input density to a 1d grid used by the nl-vdW routines.
subroutine, public qs_fxc_nlvdw_apply(qs_env, xc_section, dispersion_env, rho0_r, rho1_r, fxc_rho)
Second derivative of nl-vdW potential.
subroutine, public qs_fxc_nlvdw_fdiff(qs_env, dispersion_env, rho0_r, rho1_r, accuracy, epsrho, fxc_rho)
Second derivative of nl-vdW potential using finite differences.
subroutine, public calculate_vxc_nlvdw(vxc_r, rho, drho, edispersion, dispersion_env, energy_only, pw_pool, para_env, virial)
Calculates the non-local vdW functional using the method of Soler For spin polarized cases we use E(a...
subroutine, public return_nlvdw_potential(vxc_rho, vxc_r, pw_pool, xc_pw_pool)
Take the nl-vdW potential and return it on the XC grid and for all spin channels.
Definition of disperson types for DFT calculations.
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, mimic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, sab_cneo, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, matrix_vhxc, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, xcint_weights, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, rhoz_cneo_set, ecoul_1c, rho0_s_rs, rho0_s_gs, rhoz_cneo_s_rs, rhoz_cneo_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs, do_rixs, tb_tblite)
Get the QUICKSTEP environment.
stores all the informations relevant to an mpi environment
contained for different pw related things
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...