41 #include "../base/base_uses.f90"
45 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'dielectric_methods'
49 INTERFACE dielectric_compute
50 MODULE PROCEDURE dielectric_compute_periodic_r3d_rs, &
51 dielectric_compute_neumann_r3d_rs
52 MODULE PROCEDURE dielectric_compute_periodic_c1d_gs, &
53 dielectric_compute_neumann_c1d_gs
54 END INTERFACE dielectric_compute
68 TYPE(dielectric_type),
INTENT(INOUT),
POINTER :: dielectric
69 TYPE(pw_pool_type),
POINTER :: pw_pool
70 TYPE(dielectric_parameters),
INTENT(IN) :: dielectric_params
72 CHARACTER(LEN=*),
PARAMETER :: routinen =
'dielectric_create'
76 CALL timeset(routinen, handle)
78 IF (.NOT.
ASSOCIATED(dielectric))
THEN
80 NULLIFY (dielectric%eps)
81 NULLIFY (dielectric%deps_drho)
82 ALLOCATE (dielectric%eps, dielectric%deps_drho)
83 CALL pw_pool%create_pw(dielectric%eps)
84 CALL pw_pool%create_pw(dielectric%deps_drho)
85 CALL pw_set(dielectric%eps, 1.0_dp)
86 CALL pw_zero(dielectric%deps_drho)
88 CALL pw_pool%create_pw(dielectric%dln_eps(i))
89 CALL pw_zero(dielectric%dln_eps(i))
91 dielectric%params = dielectric_params
92 dielectric%params%times_called = 0
112 SUBROUTINE dielectric_compute_periodic_c1d_gs (dielectric, diel_rs_grid, pw_pool, rho, rho_core)
114 TYPE(dielectric_type),
INTENT(INOUT),
POINTER :: dielectric
115 TYPE(realspace_grid_type),
POINTER :: diel_rs_grid
116 TYPE(pw_pool_type),
INTENT(IN),
POINTER :: pw_pool
117 TYPE(pw_c1d_gs_type),
INTENT(IN) :: rho
118 TYPE(pw_c1d_gs_type),
INTENT(IN),
OPTIONAL :: rho_core
120 CHARACTER(LEN=*),
PARAMETER :: routinen =
'dielectric_compute_periodic'
121 REAL(
dp),
PARAMETER :: small_value = epsilon(1.0_dp)
123 INTEGER :: derivative_method, dielec_functiontype, &
124 handle, i, idir, j, k, times_called
125 INTEGER,
DIMENSION(3) :: lb, ub
126 REAL(
dp) :: eps0, rho_max, rho_min
127 TYPE(pw_r3d_rs_type) :: ln_eps, rho_elec_rs
128 TYPE(pw_r3d_rs_type) :: rho_core_rs
129 TYPE(pw_r3d_rs_type),
DIMENSION(3) :: deps, drho
131 CALL timeset(routinen, handle)
133 rho_min = dielectric%params%rho_min
134 rho_max = dielectric%params%rho_max
135 eps0 = dielectric%params%eps0
136 derivative_method = dielectric%params%derivative_method
137 times_called = dielectric%params%times_called
138 dielec_functiontype = dielectric%params%dielec_functiontype
143 CALL cp_abort(__location__, &
144 "The specified derivative method is not compatible with the type of "// &
145 "the dielectric constant function.")
148 CALL pw_pool%create_pw(rho_elec_rs)
151 CALL pw_transfer(rho, rho_elec_rs)
153 IF (
PRESENT(rho_core))
THEN
155 CALL pw_pool%create_pw(rho_core_rs)
156 CALL pw_transfer(rho_core, rho_core_rs)
157 IF (dielectric%params%dielec_core_correction)
THEN
160 CALL pw_axpy(rho_core_rs, rho_elec_rs, -2.0_dp)
162 CALL pw_axpy(rho_core_rs, rho_elec_rs, -1.0_dp)
164 CALL pw_pool%give_back_pw(rho_core_rs)
166 cpabort(
"For dielectric constant larger than 1, rho_core has to be present.")
170 SELECT CASE (dielec_functiontype)
172 CALL dielectric_constant_sccs(rho_elec_rs, dielectric%eps, dielectric%deps_drho, &
173 eps0, rho_max, rho_min)
175 IF (times_called .EQ. 0)
THEN
176 CALL dielectric_constant_spatially_dependent(dielectric%eps, pw_pool, dielectric%params)
179 CALL dielectric_constant_spatially_rho_dependent(rho_elec_rs, dielectric%eps, &
180 dielectric%deps_drho, pw_pool, dielectric%params)
187 SELECT CASE (derivative_method)
189 CALL pw_pool%create_pw(ln_eps)
190 ln_eps%array = log(dielectric%eps%array)
193 CALL pw_pool%create_pw(deps(i))
194 CALL pw_zero(deps(i))
198 CALL pw_pool%create_pw(deps(i))
199 CALL pw_pool%create_pw(drho(i))
200 CALL pw_zero(deps(i))
201 CALL pw_zero(drho(i))
205 SELECT CASE (derivative_method)
213 CALL derive_fft(ln_eps, dielectric%dln_eps, pw_pool)
216 CALL derive_fft(dielectric%eps, deps, pw_pool)
218 lb(1:3) = pw_pool%pw_grid%bounds_local(1, 1:3)
219 ub(1:3) = pw_pool%pw_grid%bounds_local(2, 1:3)
226 IF (abs(dielectric%deps_drho%array(i, j, k)) .LE. small_value)
THEN
227 deps(idir)%array(i, j, k) = 0.0_dp
232 dielectric%dln_eps(idir)%array = deps(idir)%array/dielectric%eps%array
239 deps(i)%array = drho(i)%array*dielectric%deps_drho%array
240 dielectric%dln_eps(i)%array = deps(i)%array/dielectric%eps%array
244 SELECT CASE (derivative_method)
246 CALL pw_pool%give_back_pw(ln_eps)
249 CALL pw_pool%give_back_pw(deps(i))
253 CALL pw_pool%give_back_pw(drho(i))
254 CALL pw_pool%give_back_pw(deps(i))
259 CALL pw_pool%give_back_pw(rho_elec_rs)
261 dielectric%params%times_called = dielectric%params%times_called + 1
263 CALL timestop(handle)
265 END SUBROUTINE dielectric_compute_periodic_c1d_gs
287 SUBROUTINE dielectric_compute_neumann_c1d_gs (dielectric, diel_rs_grid, pw_pool_orig, &
288 dct_pw_grid, neumann_directions, recv_msgs_bnds, &
289 dests_expand, srcs_expand, flipg_stat, bounds_shftd, rho, rho_core)
291 TYPE(dielectric_type),
INTENT(INOUT),
POINTER :: dielectric
292 TYPE(realspace_grid_type),
POINTER :: diel_rs_grid
293 TYPE(pw_pool_type),
INTENT(IN),
POINTER :: pw_pool_orig
294 TYPE(pw_grid_type),
INTENT(IN),
POINTER :: dct_pw_grid
295 INTEGER,
INTENT(IN) :: neumann_directions
296 INTEGER,
DIMENSION(:, :, :),
INTENT(IN),
POINTER :: recv_msgs_bnds
297 INTEGER,
DIMENSION(:),
INTENT(IN),
POINTER :: dests_expand, srcs_expand, flipg_stat
298 INTEGER,
DIMENSION(2, 3),
INTENT(IN) :: bounds_shftd
299 TYPE(pw_c1d_gs_type),
INTENT(IN) :: rho
300 TYPE(pw_c1d_gs_type),
INTENT(IN),
OPTIONAL :: rho_core
302 CHARACTER(LEN=*),
PARAMETER :: routinen =
'dielectric_compute_neumann'
303 REAL(
dp),
PARAMETER :: small_value = epsilon(1.0_dp)
305 INTEGER :: derivative_method, dielec_functiontype, &
306 handle, i, idir, j, k, times_called
307 INTEGER,
DIMENSION(3) :: lb, ub
308 REAL(
dp) :: eps0, rho_max, rho_min
309 TYPE(pw_pool_type),
POINTER :: pw_pool_xpndd
310 TYPE(pw_r3d_rs_type) :: ln_eps, rho_core_rs, rho_core_rs_xpndd, &
311 rho_elec_rs, rho_elec_rs_xpndd
312 TYPE(pw_r3d_rs_type),
DIMENSION(3) :: deps, drho
314 CALL timeset(routinen, handle)
316 rho_min = dielectric%params%rho_min
317 rho_max = dielectric%params%rho_max
318 eps0 = dielectric%params%eps0
319 derivative_method = dielectric%params%derivative_method
320 times_called = dielectric%params%times_called
321 dielec_functiontype = dielectric%params%dielec_functiontype
326 CALL cp_abort(__location__, &
327 "The specified derivative method is not compatible with the type of "// &
328 "the dielectric constant function.")
334 CALL pw_pool_orig%create_pw(rho_elec_rs)
335 CALL pw_transfer(rho, rho_elec_rs)
337 CALL pw_pool_xpndd%create_pw(rho_elec_rs_xpndd)
338 CALL pw_expand(neumann_directions, recv_msgs_bnds, dests_expand, srcs_expand, flipg_stat, bounds_shftd, &
339 rho_elec_rs, rho_elec_rs_xpndd)
341 IF (
PRESENT(rho_core))
THEN
343 CALL pw_pool_orig%create_pw(rho_core_rs)
344 CALL pw_transfer(rho_core, rho_core_rs)
346 CALL pw_pool_xpndd%create_pw(rho_core_rs_xpndd)
347 CALL pw_expand(neumann_directions, recv_msgs_bnds, dests_expand, srcs_expand, flipg_stat, bounds_shftd, &
348 rho_core_rs, rho_core_rs_xpndd)
350 IF (dielectric%params%dielec_core_correction)
THEN
352 CALL pw_axpy(rho_core_rs_xpndd, rho_elec_rs_xpndd, -2.0_dp)
354 CALL pw_axpy(rho_core_rs_xpndd, rho_elec_rs_xpndd, -1.0_dp)
356 CALL pw_pool_orig%give_back_pw(rho_core_rs)
357 CALL pw_pool_xpndd%give_back_pw(rho_core_rs_xpndd)
359 cpabort(
"For dielectric constant larger than 1, rho_core has to be present.")
363 SELECT CASE (dielec_functiontype)
365 CALL dielectric_constant_sccs(rho_elec_rs_xpndd, dielectric%eps, dielectric%deps_drho, &
366 eps0, rho_max, rho_min)
368 IF (times_called .EQ. 0)
THEN
369 CALL dielectric_constant_spatially_dependent(dielectric%eps, pw_pool_xpndd, dielectric%params)
372 CALL dielectric_constant_spatially_rho_dependent(rho_elec_rs_xpndd, dielectric%eps, &
373 dielectric%deps_drho, pw_pool_xpndd, dielectric%params)
380 SELECT CASE (derivative_method)
382 CALL pw_pool_xpndd%create_pw(ln_eps)
383 ln_eps%array = log(dielectric%eps%array)
386 CALL pw_pool_xpndd%create_pw(deps(i))
387 CALL pw_zero(deps(i))
391 CALL pw_pool_xpndd%create_pw(deps(i))
392 CALL pw_pool_xpndd%create_pw(drho(i))
393 CALL pw_zero(deps(i))
394 CALL pw_zero(drho(i))
398 SELECT CASE (derivative_method)
406 CALL derive_fft(ln_eps, dielectric%dln_eps, pw_pool_xpndd)
409 CALL derive_fft(dielectric%eps, deps, pw_pool_xpndd)
411 lb(1:3) = pw_pool_xpndd%pw_grid%bounds_local(1, 1:3)
412 ub(1:3) = pw_pool_xpndd%pw_grid%bounds_local(2, 1:3)
419 IF (abs(dielectric%deps_drho%array(i, j, k)) .LE. small_value)
THEN
420 deps(idir)%array(i, j, k) = 0.0_dp
425 dielectric%dln_eps(idir)%array = deps(idir)%array/dielectric%eps%array
430 CALL derive_fft(rho_elec_rs_xpndd, drho, pw_pool_xpndd)
432 deps(i)%array = drho(i)%array*dielectric%deps_drho%array
433 dielectric%dln_eps(i)%array = deps(i)%array/dielectric%eps%array
437 SELECT CASE (derivative_method)
439 CALL pw_pool_xpndd%give_back_pw(ln_eps)
442 CALL pw_pool_xpndd%give_back_pw(deps(i))
446 CALL pw_pool_xpndd%give_back_pw(drho(i))
447 CALL pw_pool_xpndd%give_back_pw(deps(i))
452 CALL pw_pool_orig%give_back_pw(rho_elec_rs)
453 CALL pw_pool_xpndd%give_back_pw(rho_elec_rs_xpndd)
456 dielectric%params%times_called = dielectric%params%times_called + 1
458 CALL timestop(handle)
460 END SUBROUTINE dielectric_compute_neumann_c1d_gs
474 SUBROUTINE dielectric_compute_periodic_r3d_rs (dielectric, diel_rs_grid, pw_pool, rho, rho_core)
476 TYPE(dielectric_type),
INTENT(INOUT),
POINTER :: dielectric
477 TYPE(realspace_grid_type),
POINTER :: diel_rs_grid
478 TYPE(pw_pool_type),
INTENT(IN),
POINTER :: pw_pool
479 TYPE(pw_r3d_rs_type),
INTENT(IN) :: rho
480 TYPE(pw_c1d_gs_type),
INTENT(IN),
OPTIONAL :: rho_core
482 CHARACTER(LEN=*),
PARAMETER :: routinen =
'dielectric_compute_periodic'
483 REAL(
dp),
PARAMETER :: small_value = epsilon(1.0_dp)
485 INTEGER :: derivative_method, dielec_functiontype, &
486 handle, i, idir, j, k, times_called
487 INTEGER,
DIMENSION(3) :: lb, ub
488 REAL(
dp) :: eps0, rho_max, rho_min
489 TYPE(pw_r3d_rs_type) :: ln_eps, rho_elec_rs
490 TYPE(pw_r3d_rs_type) :: rho_core_rs
491 TYPE(pw_r3d_rs_type),
DIMENSION(3) :: deps, drho
493 CALL timeset(routinen, handle)
495 rho_min = dielectric%params%rho_min
496 rho_max = dielectric%params%rho_max
497 eps0 = dielectric%params%eps0
498 derivative_method = dielectric%params%derivative_method
499 times_called = dielectric%params%times_called
500 dielec_functiontype = dielectric%params%dielec_functiontype
505 CALL cp_abort(__location__, &
506 "The specified derivative method is not compatible with the type of "// &
507 "the dielectric constant function.")
510 CALL pw_pool%create_pw(rho_elec_rs)
513 CALL pw_transfer(rho, rho_elec_rs)
515 IF (
PRESENT(rho_core))
THEN
517 CALL pw_pool%create_pw(rho_core_rs)
518 CALL pw_transfer(rho_core, rho_core_rs)
519 IF (dielectric%params%dielec_core_correction)
THEN
522 CALL pw_axpy(rho_core_rs, rho_elec_rs, -2.0_dp)
524 CALL pw_axpy(rho_core_rs, rho_elec_rs, -1.0_dp)
526 CALL pw_pool%give_back_pw(rho_core_rs)
528 cpabort(
"For dielectric constant larger than 1, rho_core has to be present.")
532 SELECT CASE (dielec_functiontype)
534 CALL dielectric_constant_sccs(rho_elec_rs, dielectric%eps, dielectric%deps_drho, &
535 eps0, rho_max, rho_min)
537 IF (times_called .EQ. 0)
THEN
538 CALL dielectric_constant_spatially_dependent(dielectric%eps, pw_pool, dielectric%params)
541 CALL dielectric_constant_spatially_rho_dependent(rho_elec_rs, dielectric%eps, &
542 dielectric%deps_drho, pw_pool, dielectric%params)
549 SELECT CASE (derivative_method)
551 CALL pw_pool%create_pw(ln_eps)
552 ln_eps%array = log(dielectric%eps%array)
555 CALL pw_pool%create_pw(deps(i))
556 CALL pw_zero(deps(i))
560 CALL pw_pool%create_pw(deps(i))
561 CALL pw_pool%create_pw(drho(i))
562 CALL pw_zero(deps(i))
563 CALL pw_zero(drho(i))
567 SELECT CASE (derivative_method)
575 CALL derive_fft(ln_eps, dielectric%dln_eps, pw_pool)
578 CALL derive_fft(dielectric%eps, deps, pw_pool)
580 lb(1:3) = pw_pool%pw_grid%bounds_local(1, 1:3)
581 ub(1:3) = pw_pool%pw_grid%bounds_local(2, 1:3)
588 IF (abs(dielectric%deps_drho%array(i, j, k)) .LE. small_value)
THEN
589 deps(idir)%array(i, j, k) = 0.0_dp
594 dielectric%dln_eps(idir)%array = deps(idir)%array/dielectric%eps%array
601 deps(i)%array = drho(i)%array*dielectric%deps_drho%array
602 dielectric%dln_eps(i)%array = deps(i)%array/dielectric%eps%array
606 SELECT CASE (derivative_method)
608 CALL pw_pool%give_back_pw(ln_eps)
611 CALL pw_pool%give_back_pw(deps(i))
615 CALL pw_pool%give_back_pw(drho(i))
616 CALL pw_pool%give_back_pw(deps(i))
621 CALL pw_pool%give_back_pw(rho_elec_rs)
623 dielectric%params%times_called = dielectric%params%times_called + 1
625 CALL timestop(handle)
627 END SUBROUTINE dielectric_compute_periodic_r3d_rs
649 SUBROUTINE dielectric_compute_neumann_r3d_rs (dielectric, diel_rs_grid, pw_pool_orig, &
650 dct_pw_grid, neumann_directions, recv_msgs_bnds, &
651 dests_expand, srcs_expand, flipg_stat, bounds_shftd, rho, rho_core)
653 TYPE(dielectric_type),
INTENT(INOUT),
POINTER :: dielectric
654 TYPE(realspace_grid_type),
POINTER :: diel_rs_grid
655 TYPE(pw_pool_type),
INTENT(IN),
POINTER :: pw_pool_orig
656 TYPE(pw_grid_type),
INTENT(IN),
POINTER :: dct_pw_grid
657 INTEGER,
INTENT(IN) :: neumann_directions
658 INTEGER,
DIMENSION(:, :, :),
INTENT(IN),
POINTER :: recv_msgs_bnds
659 INTEGER,
DIMENSION(:),
INTENT(IN),
POINTER :: dests_expand, srcs_expand, flipg_stat
660 INTEGER,
DIMENSION(2, 3),
INTENT(IN) :: bounds_shftd
661 TYPE(pw_r3d_rs_type),
INTENT(IN) :: rho
662 TYPE(pw_c1d_gs_type),
INTENT(IN),
OPTIONAL :: rho_core
664 CHARACTER(LEN=*),
PARAMETER :: routinen =
'dielectric_compute_neumann'
665 REAL(
dp),
PARAMETER :: small_value = epsilon(1.0_dp)
667 INTEGER :: derivative_method, dielec_functiontype, &
668 handle, i, idir, j, k, times_called
669 INTEGER,
DIMENSION(3) :: lb, ub
670 REAL(
dp) :: eps0, rho_max, rho_min
671 TYPE(pw_pool_type),
POINTER :: pw_pool_xpndd
672 TYPE(pw_r3d_rs_type) :: ln_eps, rho_core_rs, rho_core_rs_xpndd, &
673 rho_elec_rs, rho_elec_rs_xpndd
674 TYPE(pw_r3d_rs_type),
DIMENSION(3) :: deps, drho
676 CALL timeset(routinen, handle)
678 rho_min = dielectric%params%rho_min
679 rho_max = dielectric%params%rho_max
680 eps0 = dielectric%params%eps0
681 derivative_method = dielectric%params%derivative_method
682 times_called = dielectric%params%times_called
683 dielec_functiontype = dielectric%params%dielec_functiontype
688 CALL cp_abort(__location__, &
689 "The specified derivative method is not compatible with the type of "// &
690 "the dielectric constant function.")
696 CALL pw_pool_orig%create_pw(rho_elec_rs)
697 CALL pw_transfer(rho, rho_elec_rs)
699 CALL pw_pool_xpndd%create_pw(rho_elec_rs_xpndd)
700 CALL pw_expand(neumann_directions, recv_msgs_bnds, dests_expand, srcs_expand, flipg_stat, bounds_shftd, &
701 rho_elec_rs, rho_elec_rs_xpndd)
703 IF (
PRESENT(rho_core))
THEN
705 CALL pw_pool_orig%create_pw(rho_core_rs)
706 CALL pw_transfer(rho_core, rho_core_rs)
708 CALL pw_pool_xpndd%create_pw(rho_core_rs_xpndd)
709 CALL pw_expand(neumann_directions, recv_msgs_bnds, dests_expand, srcs_expand, flipg_stat, bounds_shftd, &
710 rho_core_rs, rho_core_rs_xpndd)
712 IF (dielectric%params%dielec_core_correction)
THEN
714 CALL pw_axpy(rho_core_rs_xpndd, rho_elec_rs_xpndd, -2.0_dp)
716 CALL pw_axpy(rho_core_rs_xpndd, rho_elec_rs_xpndd, -1.0_dp)
718 CALL pw_pool_orig%give_back_pw(rho_core_rs)
719 CALL pw_pool_xpndd%give_back_pw(rho_core_rs_xpndd)
721 cpabort(
"For dielectric constant larger than 1, rho_core has to be present.")
725 SELECT CASE (dielec_functiontype)
727 CALL dielectric_constant_sccs(rho_elec_rs_xpndd, dielectric%eps, dielectric%deps_drho, &
728 eps0, rho_max, rho_min)
730 IF (times_called .EQ. 0)
THEN
731 CALL dielectric_constant_spatially_dependent(dielectric%eps, pw_pool_xpndd, dielectric%params)
734 CALL dielectric_constant_spatially_rho_dependent(rho_elec_rs_xpndd, dielectric%eps, &
735 dielectric%deps_drho, pw_pool_xpndd, dielectric%params)
742 SELECT CASE (derivative_method)
744 CALL pw_pool_xpndd%create_pw(ln_eps)
745 ln_eps%array = log(dielectric%eps%array)
748 CALL pw_pool_xpndd%create_pw(deps(i))
749 CALL pw_zero(deps(i))
753 CALL pw_pool_xpndd%create_pw(deps(i))
754 CALL pw_pool_xpndd%create_pw(drho(i))
755 CALL pw_zero(deps(i))
756 CALL pw_zero(drho(i))
760 SELECT CASE (derivative_method)
768 CALL derive_fft(ln_eps, dielectric%dln_eps, pw_pool_xpndd)
771 CALL derive_fft(dielectric%eps, deps, pw_pool_xpndd)
773 lb(1:3) = pw_pool_xpndd%pw_grid%bounds_local(1, 1:3)
774 ub(1:3) = pw_pool_xpndd%pw_grid%bounds_local(2, 1:3)
781 IF (abs(dielectric%deps_drho%array(i, j, k)) .LE. small_value)
THEN
782 deps(idir)%array(i, j, k) = 0.0_dp
787 dielectric%dln_eps(idir)%array = deps(idir)%array/dielectric%eps%array
792 CALL derive_fft(rho_elec_rs_xpndd, drho, pw_pool_xpndd)
794 deps(i)%array = drho(i)%array*dielectric%deps_drho%array
795 dielectric%dln_eps(i)%array = deps(i)%array/dielectric%eps%array
799 SELECT CASE (derivative_method)
801 CALL pw_pool_xpndd%give_back_pw(ln_eps)
804 CALL pw_pool_xpndd%give_back_pw(deps(i))
808 CALL pw_pool_xpndd%give_back_pw(drho(i))
809 CALL pw_pool_xpndd%give_back_pw(deps(i))
814 CALL pw_pool_orig%give_back_pw(rho_elec_rs)
815 CALL pw_pool_xpndd%give_back_pw(rho_elec_rs_xpndd)
818 dielectric%params%times_called = dielectric%params%times_called + 1
820 CALL timestop(handle)
822 END SUBROUTINE dielectric_compute_neumann_r3d_rs
837 SUBROUTINE dielectric_constant_sccs(rho, eps, deps_drho, eps0, rho_max, rho_min)
839 TYPE(pw_r3d_rs_type),
INTENT(IN) :: rho, eps, deps_drho
840 REAL(kind=
dp),
INTENT(IN) :: eps0, rho_max, rho_min
842 CHARACTER(LEN=*),
PARAMETER :: routinen =
'dielectric_constant_sccs'
844 INTEGER :: handle, i, j, k, lb1, lb2, lb3, ub1, &
846 INTEGER,
DIMENSION(2, 3) :: bounds_local
847 REAL(kind=
dp) :: denom, t
849 CALL timeset(routinen, handle)
851 IF (eps0 .LT. 1.0_dp)
THEN
852 cpabort(
"The dielectric constant has to be greater than or equal to 1.")
855 bounds_local = rho%pw_grid%bounds_local
856 lb1 = bounds_local(1, 1); ub1 = bounds_local(2, 1)
857 lb2 = bounds_local(1, 2); ub2 = bounds_local(2, 2)
858 lb3 = bounds_local(1, 3); ub3 = bounds_local(2, 3)
860 denom = log(rho_max) - log(rho_min)
864 IF (rho%array(i, j, k) .LT. rho_min)
THEN
865 eps%array(i, j, k) = eps0
866 deps_drho%array(i, j, k) = 0.0_dp
867 ELSE IF (rho%array(i, j, k) .GT. rho_max)
THEN
868 eps%array(i, j, k) = 1.0_dp
869 deps_drho%array(i, j, k) = 0.0_dp
871 t =
twopi*(log(rho_max) - log(rho%array(i, j, k)))/denom
872 eps%array(i, j, k) = exp(log(eps0)*(t - sin(t))/
twopi)
873 deps_drho%array(i, j, k) = -eps%array(i, j, k)*log(eps0)*(1.0_dp - cos(t))/(denom*rho%array(i, j, k))
879 CALL timestop(handle)
881 END SUBROUTINE dielectric_constant_sccs
902 SUBROUTINE dielectric_constant_aa_cuboidal(eps, dielec_const, pw_pool, zeta, &
903 x_xtnt, y_xtnt, z_xtnt, &
904 x_glbl, y_glbl, z_glbl, &
905 x_locl, y_locl, z_locl)
907 TYPE(pw_r3d_rs_type),
INTENT(INOUT) :: eps
908 REAL(kind=
dp),
INTENT(IN) :: dielec_const
909 TYPE(pw_pool_type),
POINTER :: pw_pool
910 REAL(kind=
dp),
INTENT(IN) :: zeta
911 REAL(
dp),
DIMENSION(2),
INTENT(IN) :: x_xtnt, y_xtnt, z_xtnt
912 REAL(
dp),
ALLOCATABLE,
DIMENSION(:),
INTENT(IN) :: x_glbl, y_glbl, z_glbl, x_locl, y_locl, &
915 CHARACTER(LEN=*),
PARAMETER :: routinen =
'dielectric_constant_aa_cuboidal'
916 LOGICAL,
DIMENSION(6),
PARAMETER :: test_forb_xtnts = .true.
918 INTEGER :: handle, i, j, k, lb1, lb2, lb3, &
919 n_forb_xtnts, ub1, ub2, ub3
920 INTEGER,
DIMENSION(2, 3) :: bounds_local
921 LOGICAL :: forb_xtnt1, forb_xtnt2, forb_xtnt3, &
922 forb_xtnt4, forb_xtnt5, forb_xtnt6
923 REAL(kind=
dp) :: dx, dy, dz
924 TYPE(pw_grid_type),
POINTER :: pw_grid
925 TYPE(pw_r3d_rs_type) :: eps_tmp
927 CALL timeset(routinen, handle)
929 IF (dielec_const .LT. 1.0_dp)
THEN
930 cpabort(
"The dielectric constant has to be greater than or equal to 1.")
933 pw_grid => eps%pw_grid
935 dx = pw_grid%dr(1); dy = pw_grid%dr(2); dz = pw_grid%dr(3)
937 forb_xtnt1 = x_xtnt(1) .LT. x_glbl(lbound(x_glbl, 1))
938 forb_xtnt2 = x_xtnt(2) .GT. x_glbl(ubound(x_glbl, 1)) + dx
939 forb_xtnt3 = y_xtnt(1) .LT. y_glbl(lbound(y_glbl, 1))
940 forb_xtnt4 = y_xtnt(2) .GT. y_glbl(ubound(y_glbl, 1)) + dy
941 forb_xtnt5 = z_xtnt(1) .LT. z_glbl(lbound(z_glbl, 1))
942 forb_xtnt6 = z_xtnt(2) .GT. z_glbl(ubound(z_glbl, 1)) + dz
943 n_forb_xtnts = count((/forb_xtnt1, forb_xtnt2, forb_xtnt3, &
944 forb_xtnt4, forb_xtnt5, forb_xtnt6/) .EQV. test_forb_xtnts)
945 IF (n_forb_xtnts .GT. 0)
THEN
946 CALL cp_abort(__location__, &
947 "The given extents for the dielectric region are outside the range of "// &
948 "the simulation cell.")
951 CALL pw_pool%create_pw(eps_tmp)
952 CALL pw_copy(eps, eps_tmp)
954 bounds_local = pw_grid%bounds_local
955 lb1 = bounds_local(1, 1); ub1 = bounds_local(2, 1)
956 lb2 = bounds_local(1, 2); ub2 = bounds_local(2, 2)
957 lb3 = bounds_local(1, 3); ub3 = bounds_local(2, 3)
962 IF ((x_locl(i) .GE. x_xtnt(1)) .AND. (x_locl(i) .LE. x_xtnt(2)) .AND. &
963 (y_locl(j) .GE. y_xtnt(1)) .AND. (y_locl(j) .LE. y_xtnt(2)) .AND. &
964 (z_locl(k) .GE. z_xtnt(1)) .AND. (z_locl(k) .LE. z_xtnt(2)))
THEN
965 eps_tmp%array(i, j, k) = dielec_const
971 CALL pw_mollifier(pw_pool, zeta, x_glbl, y_glbl, z_glbl, eps_tmp, eps)
972 CALL pw_pool%give_back_pw(eps_tmp)
974 CALL timestop(handle)
976 END SUBROUTINE dielectric_constant_aa_cuboidal
997 SUBROUTINE dielectric_constant_xaa_annular(eps, dielec_const, pw_pool, zeta, &
998 x_xtnt, base_center, base_radii, &
999 x_glbl, y_glbl, z_glbl, &
1000 x_locl, y_locl, z_locl)
1002 TYPE(pw_r3d_rs_type),
INTENT(INOUT) :: eps
1003 REAL(kind=
dp),
INTENT(IN) :: dielec_const
1004 TYPE(pw_pool_type),
POINTER :: pw_pool
1005 REAL(
dp),
INTENT(IN) :: zeta
1006 REAL(
dp),
DIMENSION(2),
INTENT(IN) :: x_xtnt, base_center, base_radii
1007 REAL(
dp),
ALLOCATABLE,
DIMENSION(:),
INTENT(IN) :: x_glbl, y_glbl, z_glbl, x_locl, y_locl, &
1010 CHARACTER(LEN=*),
PARAMETER :: routinen =
'dielectric_constant_xaa_annular'
1011 LOGICAL,
DIMENSION(6),
PARAMETER :: test_forb_xtnts = .true.
1013 INTEGER :: handle, i, j, k, lb1, lb2, lb3, &
1014 n_forb_xtnts, ub1, ub2, ub3
1015 INTEGER,
DIMENSION(2, 3) :: bounds_local
1016 LOGICAL :: forb_xtnt1, forb_xtnt2, forb_xtnt3, &
1017 forb_xtnt4, forb_xtnt5, forb_xtnt6
1018 REAL(kind=
dp) :: bctry, bctrz, distsq, dx, dy, dz
1019 TYPE(pw_grid_type),
POINTER :: pw_grid
1020 TYPE(pw_r3d_rs_type) :: eps_tmp
1022 CALL timeset(routinen, handle)
1024 IF (dielec_const .LT. 1.0_dp)
THEN
1025 cpabort(
"The dielectric constant has to be greater than or equal to 1.")
1028 pw_grid => eps%pw_grid
1030 bctry = base_center(1); bctrz = base_center(2)
1031 dx = pw_grid%dr(1); dy = pw_grid%dr(2); dz = pw_grid%dr(3)
1033 forb_xtnt1 = x_xtnt(1) .LT. x_glbl(lbound(x_glbl, 1))
1034 forb_xtnt2 = x_xtnt(2) .GT. x_glbl(ubound(x_glbl, 1)) + dx
1035 forb_xtnt3 = bctry - maxval(base_radii) .LT. y_glbl(lbound(y_glbl, 1))
1036 forb_xtnt4 = bctry + maxval(base_radii) .GT. y_glbl(ubound(y_glbl, 1)) + dy
1037 forb_xtnt5 = bctrz - maxval(base_radii) .LT. z_glbl(lbound(z_glbl, 1))
1038 forb_xtnt6 = bctrz + maxval(base_radii) .GT. z_glbl(ubound(z_glbl, 1)) + dz
1039 n_forb_xtnts = count((/forb_xtnt1, forb_xtnt2, forb_xtnt3, &
1040 forb_xtnt4, forb_xtnt5, forb_xtnt6/) .EQV. test_forb_xtnts)
1041 IF (n_forb_xtnts .GT. 0)
THEN
1042 CALL cp_abort(__location__, &
1043 "The given extents for the dielectric region are outside the range of "// &
1044 "the simulation cell.")
1047 CALL pw_pool%create_pw(eps_tmp)
1048 CALL pw_copy(eps, eps_tmp)
1050 bounds_local = pw_grid%bounds_local
1051 lb1 = bounds_local(1, 1); ub1 = bounds_local(2, 1)
1052 lb2 = bounds_local(1, 2); ub2 = bounds_local(2, 2)
1053 lb3 = bounds_local(1, 3); ub3 = bounds_local(2, 3)
1058 distsq = (y_locl(j) - bctry)**2 + (z_locl(k) - bctrz)**2
1059 IF ((x_locl(i) .GE. x_xtnt(1)) .AND. (x_locl(i) .LE. x_xtnt(2)) .AND. &
1060 (distsq .GE. minval(base_radii)**2) .AND. (distsq .LE. maxval(base_radii)**2))
THEN
1061 eps_tmp%array(i, j, k) = dielec_const
1067 CALL pw_mollifier(pw_pool, zeta, x_glbl, y_glbl, z_glbl, eps_tmp, eps)
1068 CALL pw_pool%give_back_pw(eps_tmp)
1070 CALL timestop(handle)
1072 END SUBROUTINE dielectric_constant_xaa_annular
1083 SUBROUTINE dielectric_constant_spatially_dependent(eps, pw_pool, dielectric_params)
1085 TYPE(pw_r3d_rs_type),
INTENT(INOUT) :: eps
1086 TYPE(pw_pool_type),
INTENT(IN),
POINTER :: pw_pool
1087 TYPE(dielectric_parameters),
INTENT(IN) :: dielectric_params
1089 CHARACTER(LEN=*),
PARAMETER :: routinen =
'dielectric_constant_spatially_dependent'
1091 INTEGER :: handle, j, n_aa_cuboidal, &
1092 n_dielectric_region, n_xaa_annular
1093 REAL(
dp) :: dielec_const, zeta
1094 REAL(
dp),
ALLOCATABLE,
DIMENSION(:) :: x_glbl, x_locl, y_glbl, y_locl, z_glbl, &
1096 REAL(
dp),
DIMENSION(2) :: base_center, base_radii
1097 TYPE(pw_grid_type),
POINTER :: pw_grid
1099 CALL timeset(routinen, handle)
1101 eps%array = dielectric_params%eps0
1103 n_aa_cuboidal = dielectric_params%n_aa_cuboidal
1104 n_xaa_annular = dielectric_params%n_xaa_annular
1105 pw_grid => pw_pool%pw_grid
1106 CALL setup_grid_axes(pw_grid, x_glbl, y_glbl, z_glbl, x_locl, y_locl, z_locl)
1107 n_dielectric_region = n_aa_cuboidal + n_xaa_annular
1109 IF (n_dielectric_region .EQ. 0)
THEN
1110 cpabort(
"No density independent dielectric region is defined.")
1113 DO j = 1, n_aa_cuboidal
1114 dielec_const = dielectric_params%aa_cuboidal_eps(j)
1115 zeta = dielectric_params%aa_cuboidal_zeta(j)
1117 CALL dielectric_constant_aa_cuboidal(eps, dielec_const, pw_pool, zeta, &
1118 dielectric_params%aa_cuboidal_xxtnt(:, j), &
1119 dielectric_params%aa_cuboidal_yxtnt(:, j), &
1120 dielectric_params%aa_cuboidal_zxtnt(:, j), &
1121 x_glbl, y_glbl, z_glbl, &
1122 x_locl, y_locl, z_locl)
1125 DO j = 1, n_xaa_annular
1126 base_center = dielectric_params%xaa_annular_bctr(:, j)
1127 base_radii = dielectric_params%xaa_annular_brad(:, j)
1128 dielec_const = dielectric_params%xaa_annular_eps(j)
1129 zeta = dielectric_params%xaa_annular_zeta(j)
1131 CALL dielectric_constant_xaa_annular(eps, dielec_const, pw_pool, zeta, &
1132 dielectric_params%xaa_annular_xxtnt(:, j), &
1133 base_center, base_radii, &
1134 x_glbl, y_glbl, z_glbl, &
1135 x_locl, y_locl, z_locl)
1138 CALL timestop(handle)
1140 END SUBROUTINE dielectric_constant_spatially_dependent
1155 SUBROUTINE dielectric_constant_spatially_rho_dependent(rho, eps, deps_drho, &
1156 pw_pool, dielectric_params)
1158 TYPE(pw_r3d_rs_type),
INTENT(IN) :: rho, eps, deps_drho
1159 TYPE(pw_pool_type),
INTENT(IN),
POINTER :: pw_pool
1160 TYPE(dielectric_parameters),
INTENT(IN) :: dielectric_params
1162 CHARACTER(LEN=*),
PARAMETER :: routinen =
'dielectric_constant_spatially_rho_dependent'
1165 TYPE(pw_r3d_rs_type) :: dswch_func_drho, eps_sptldep, swch_func
1167 CALL timeset(routinen, handle)
1169 IF (dielectric_params%eps0 .LT. 1.0_dp)
THEN
1170 cpabort(
"The dielectric constant has to be greater than or equal to 1.")
1173 CALL pw_pool%create_pw(eps_sptldep)
1174 CALL pw_pool%create_pw(swch_func)
1175 CALL pw_pool%create_pw(dswch_func_drho)
1176 CALL pw_zero(eps_sptldep)
1177 CALL pw_zero(swch_func)
1178 CALL pw_zero(dswch_func_drho)
1180 CALL dielectric_constant_spatially_dependent(eps_sptldep, pw_pool, dielectric_params)
1181 CALL dielectric_constant_sccs(rho, swch_func, dswch_func_drho, 2.0_dp, &
1182 dielectric_params%rho_max, dielectric_params%rho_min)
1184 eps%array = ((swch_func%array - 1.0_dp)*(eps_sptldep%array - 1.0_dp)) + 1.0_dp
1185 deps_drho%array = dswch_func_drho%array*(eps_sptldep%array - 1.0_dp)
1187 CALL pw_pool%give_back_pw(dswch_func_drho)
1188 CALL pw_pool%give_back_pw(swch_func)
1189 CALL pw_pool%give_back_pw(eps_sptldep)
1191 CALL timestop(handle)
1193 END SUBROUTINE dielectric_constant_spatially_rho_dependent
1203 TYPE(pw_r3d_rs_type),
INTENT(IN) :: f
1204 TYPE(pw_r3d_rs_type),
DIMENSION(3),
INTENT(INOUT) :: df
1205 TYPE(pw_pool_type),
POINTER :: pw_pool
1207 CHARACTER(LEN=*),
PARAMETER :: routinen =
'derive_fft_r3d'
1209 INTEGER :: handle, i
1210 INTEGER,
DIMENSION(3) :: nd
1211 TYPE(pw_c1d_gs_type),
DIMENSION(2) :: work_gs
1213 CALL timeset(routinen, handle)
1216 CALL pw_pool%create_pw(work_gs(i))
1219 CALL pw_transfer(f, work_gs(1))
1223 CALL pw_copy(work_gs(1), work_gs(2))
1225 CALL pw_transfer(work_gs(2), df(i))
1229 CALL pw_pool%give_back_pw(work_gs(i))
1232 CALL timestop(handle)
the type I Discrete Cosine Transform (DCT-I)
subroutine, public pw_expand(neumann_directions, recv_msgs_bnds, dests_expand, srcs_expand, flipg_stat, bounds_shftd, pw_in, pw_expanded)
expands a pw_r3d_rs_type data to an evenly symmetric pw_r3d_rs_type data that is 8 times larger than ...
methods for evaluating the dielectric constant
subroutine, public dielectric_create(dielectric, pw_pool, dielectric_params)
allocates memory for a dielectric data type
subroutine, public derive_fft(f, df, pw_pool)
computes the derivative of a function using FFT
dielectric constant data type
integer, parameter, public derivative_fft_use_drho
integer, parameter, public derivative_fft_use_deps
integer, parameter, public derivative_fft
integer, parameter, public derivative_cd5
integer, parameter, public spatially_rho_dependent
integer, parameter, public derivative_cd3
integer, parameter, public spatially_dependent
integer, parameter, public rho_dependent
integer, parameter, public derivative_cd7
Defines the basic variable types.
integer, parameter, public dp
Definition of mathematical constants and functions.
real(kind=dp), parameter, public twopi
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 ...
subroutine, public pw_pool_release(pool)
releases the given pool (see cp2k/doc/ReferenceCounting.html)
subroutine, public pw_pool_create(pool, pw_grid, max_cache)
creates a pool for pw
numerical operations on real-space grid
subroutine, public setup_grid_axes(pw_grid, x_glbl, y_glbl, z_glbl, x_locl, y_locl, z_locl)
returns the global axes and the portion of the axes that are local to the current mpi rank
subroutine, public derive_fdm_cd7(f, df, rs_grid)
6th order finite difference derivative of a function on realspace grid
subroutine, public pw_mollifier(pw_pool, zeta, x_glbl, y_glbl, z_glbl, pw_in, pw_out)
convolutes a function with a smoothing kernel K_\zeta v * K_\zeta K_\zeta is the standard mollifier d...
subroutine, public derive_fdm_cd5(f, df, rs_grid)
4th order finite difference derivative of a function on realspace grid
subroutine, public derive_fdm_cd3(f, df, rs_grid)
2nd order finite difference derivative of a function on realspace grid