22module xc_functional_oct_m
37#include "functionals_list.F90"
44 xc_functional_write_info, &
45 xc_functional_is_not_size_consistent, &
46 xc_functional_is_energy_functional, &
47 xc_get_default_functional
52 integer,
public,
parameter :: &
53 XC_OEP_X = 901, & !< Exact exchange
54 xc_oep_x_slater = 902, &
56 xc_ks_inversion = 904, &
57 xc_rdmft_xc_m = 905, &
58 xc_oep_x_fbe_sl = 906, &
60 xc_lda_c_fbe_sl = 908, &
61 xc_half_hartree = 917, &
62 xc_vdw_c_vdwdf = 918, &
63 xc_vdw_c_vdwdf2 = 919, &
64 xc_vdw_c_vdwdfcx = 920, &
65 xc_hyb_gga_xc_mvorb_hse06 = 921, &
66 xc_hyb_gga_xc_mvorb_pbeh = 922, &
67 xc_mgga_x_nc_br = 923, &
68 xc_mgga_x_nc_br_1 = 924, &
69 xc_mgga_c_nc_cs = 925, &
70 xc_mgga_x_nc_br_explicit = 926
74 integer,
public,
parameter :: &
75 XC_FAMILY_KS_INVERSION = 1024, &
76 xc_family_rdmft = 2048, &
77 xc_family_libvdwxc = 4096, &
78 xc_family_nc_lda = 8192, &
79 xc_family_nc_mgga = 16384
83 integer :: family = xc_family_unknown
87 integer :: spin_channels = 0
90 logical,
private :: from_libxc = .false.
92 type(xc_f03_func_t) :: conf
93 type(xc_f03_func_info_t),
private :: info
94 type(libvdwxc_t) :: libvdwxc
95 end type xc_functional_t
97 integer,
public,
parameter :: LIBXC_C_INDEX = 1000
102 subroutine xc_functional_init(functl, namespace, id, ndim, nel, spin_channels)
103 type(xc_functional_t),
intent(inout) :: functl
104 type(namespace_t),
intent(in) :: namespace
105 integer,
intent(in) :: id
106 integer,
intent(in) :: ndim
107 real(real64),
intent(in) :: nel
108 integer,
intent(in) :: spin_channels
110 integer :: interact_1d
111 real(real64) :: alpha, parameters(2)
113 push_sub(xc_functional_init)
117 functl%spin_channels = spin_channels
119 if (functl%id == 0)
then
120 functl%family = xc_family_none
123 functl%family = xc_f03_family_from_id(functl%id)
126 if (functl%family == xc_family_unknown)
then
128 select case (functl%id)
129 case (xc_oep_x, xc_oep_x_slater, xc_oep_x_fbe, xc_oep_x_fbe_sl, xc_lda_c_fbe_sl)
130 functl%family = xc_family_oep
132 case (xc_ks_inversion)
133 functl%family = xc_family_ks_inversion
135 case (xc_half_hartree)
137 functl%family = xc_family_lda
139 case (xc_vdw_c_vdwdf, xc_vdw_c_vdwdf2, xc_vdw_c_vdwdfcx)
140 functl%family = xc_family_libvdwxc
144 functl%family = xc_family_rdmft
146 case (xc_hyb_gga_xc_mvorb_hse06, xc_hyb_gga_xc_mvorb_pbeh)
147 functl%family = xc_family_hyb_gga
149 case (xc_mgga_x_nc_br, xc_mgga_x_nc_br_1, xc_mgga_x_nc_br_explicit, xc_mgga_c_nc_cs)
150 functl%family = xc_family_nc_mgga
159 if (functl%family == xc_family_oep)
then
160 functl%type = xc_exchange
161 functl%flags = xc_flags_1d + xc_flags_2d + xc_flags_3d
163 else if (functl%family == xc_family_ks_inversion .or. functl%family == xc_family_rdmft)
then
164 functl%type = xc_exchange_correlation
165 functl%flags = xc_flags_1d + xc_flags_2d + xc_flags_3d
167 else if (functl%family == xc_family_libvdwxc)
then
168 call xc_f03_func_init(functl%conf, xc_lda_c_pw, spin_channels)
169 functl%info = xc_f03_func_get_info(functl%conf)
170 functl%type = xc_f03_func_info_get_kind(functl%info)
171 functl%flags = xc_f03_func_info_get_flags(functl%info)
173 call libvdwxc_init(functl%libvdwxc, namespace, functl%id - xc_vdw_c_vdwdf + 1)
175 else if (functl%id == xc_half_hartree)
then
176 functl%type = xc_exchange_correlation
177 functl%flags = xc_flags_1d + xc_flags_2d + xc_flags_3d
179 else if(functl%id == xc_lda_c_fbe)
then
180 functl%family = xc_family_lda
181 functl%type = xc_correlation
182 functl%flags = xc_flags_have_exc + xc_flags_have_vxc + xc_flags_3d
184 else if (functl%id == xc_mgga_x_nc_br .or. functl%id == xc_mgga_x_nc_br_1 .or. functl%id == xc_mgga_x_nc_br_explicit)
then
185 functl%type = xc_exchange
186 functl%flags = xc_flags_have_vxc + xc_flags_have_exc + xc_flags_3d
188 else if(functl%id == xc_mgga_c_nc_cs)
then
189 functl%type = xc_correlation
190 functl%flags = xc_flags_have_vxc + xc_flags_have_exc + xc_flags_3d
192 else if (functl%family == xc_family_none)
then
194 functl%flags = xc_flags_1d + xc_flags_2d + xc_flags_3d
198 functl%from_libxc = .
true.
201 select case (functl%id)
202 case (xc_hyb_gga_xc_mvorb_hse06)
203 call xc_f03_func_init(functl%conf, xc_hyb_gga_xc_hse06, spin_channels)
205 case (xc_hyb_gga_xc_mvorb_pbeh)
206 call xc_f03_func_init(functl%conf, xc_hyb_gga_xc_pbeh, spin_channels)
209 call xc_f03_func_init(functl%conf, functl%id, spin_channels)
211 functl%info = xc_f03_func_get_info(functl%conf)
212 functl%type = xc_f03_func_info_get_kind(functl%info)
213 functl%flags = xc_f03_func_info_get_flags(functl%info)
216 if (
bitand(functl%flags, xc_flags_have_exc) == 0)
then
217 message(1) =
'Specified functional does not have total energy available.'
218 message(2) =
'Corresponding component of energy will just be left as zero.'
222 if (
bitand(functl%flags, xc_flags_have_vxc) == 0)
then
223 message(1) =
'Specified functional does not have XC potential available.'
224 message(2) =
'Cannot run calculations. Choose another XCFunctional.'
230 if (functl%family /= xc_family_none)
then
231 call xc_check_dimension(functl, ndim, namespace)
235 if (
bitand(functl%flags, xc_flags_hyb_camy) /= 0)
then
241 select case (functl%id)
243 case (xc_lda_c_xalpha)
255 call xc_f03_func_set_ext_params(functl%conf, parameters(1))
258 case (xc_lda_x_1d_soft, xc_lda_c_1d_csc)
273 call parse_variable(namespace,
'Interaction1D', option__interaction1d__interaction_soft_coulomb, interact_1d)
285 parameters(1) = real(interact_1d, real64)
286 parameters(2) = alpha
287 call xc_f03_func_set_ext_params(functl%conf, parameters(1))
302 if (xc_functional_is_not_size_consistent(functl, namespace))
then
303 assert(xc_f03_func_info_get_n_ext_params(functl%info) == 1)
305 call xc_f03_func_set_ext_params(functl%conf, parameters(1))
306 write(
message(1),
'(a,i1)')
"Info: Setting the number of electrons for the functional for spin ", spin_channels
310 pop_sub(xc_functional_init)
311 end subroutine xc_functional_init
315 subroutine xc_functional_end(functl)
316 type(xc_functional_t),
intent(inout) :: functl
318 push_sub(xc_functional_end)
320 if (functl%family /= xc_family_none .and. functl%family /= xc_family_oep .and. &
321 functl%family /= xc_family_ks_inversion .and. functl%id /= xc_half_hartree &
322 .and. functl%id /= xc_lda_c_fbe &
323 .and. functl%family /= xc_family_nc_lda .and. functl%family /= xc_family_nc_mgga)
then
324 call xc_f03_func_end(functl%conf)
327 if (functl%family == xc_family_libvdwxc)
then
331 pop_sub(xc_functional_end)
332 end subroutine xc_functional_end
337 subroutine xc_functional_write_info(functl, iunit, namespace)
338 type(xc_functional_t),
intent(in) :: functl
339 integer,
optional,
intent(in) :: iunit
340 type(namespace_t),
optional,
intent(in) :: namespace
342 character(len=120) :: family
345 push_sub(xc_functional_write_info)
347 if (functl%family == xc_family_oep)
then
350 select case (functl%id)
352 write(
message(1),
'(2x,a)')
'Exchange'
353 write(
message(2),
'(4x,a)')
'Exact exchange'
356 case(xc_oep_x_slater)
357 write(
message(1),
'(2x,a)')
'Exchange'
358 write(
message(2),
'(4x,a)')
'Slater exchange'
362 write(
message(1),
'(2x,a)')
'Exchange'
363 write(
message(2),
'(4x,a)')
'Force-based local exchange'
364 write(
message(3),
'(4x,a)')
'[1] Tancogne-Dejean et al., J. Chem. Phys. 160, 024103 (2024)'
367 case (xc_oep_x_fbe_sl)
368 write(
message(1),
'(2x,a)')
'Exchange'
369 write(
message(2),
'(4x,a)')
'Force-based local exchange - Sturm-Liouville'
372 case (xc_lda_c_fbe_sl)
373 write(
message(1),
'(2x,a)')
'Correlation'
374 write(
message(2),
'(4x,a)')
'Force-based local-density correlation - Sturm-Liouville'
381 else if (functl%family == xc_family_ks_inversion)
then
383 select case (functl%id)
384 case (xc_ks_inversion)
385 write(
message(1),
'(2x,a)')
'Exchange-Correlation:'
386 write(
message(2),
'(4x,a)')
' KS Inversion'
390 else if (functl%family == xc_family_libvdwxc)
then
393 else if (functl%id == xc_mgga_x_nc_br)
then
394 write(
message(1),
'(2x,a)')
'Exchange'
395 write(
message(2),
'(4x,a)')
'Noncollinear Becke-Roussel (MGGA)'
396 write(
message(3),
'(4x,a)')
'[1] N. Tancogne-Dejean, A. Rubio, and C. A. Ullrich, Phys. Rev. B 107, 165111 (2023)'
399 else if (functl%id == xc_mgga_x_nc_br_1)
then
400 write(
message(1),
'(2x,a)')
'Exchange'
401 write(
message(2),
'(4x,a)')
'Noncollinear Becke-Roussel, gamma = 1.0 (MGGA)'
402 write(
message(3),
'(4x,a)')
'[1] N. Tancogne-Dejean, A. Rubio, and C. A. Ullrich, Phys. Rev. B 107, 165111 (2023)'
405 else if (functl%id == xc_mgga_x_nc_br_explicit)
then
406 write(
message(1),
'(2x,a)')
'Exchange'
407 write(
message(2),
'(4x,a)')
'Noncollinear Becke-Roussel (MGGA) with explicit inversion of x(y)'
408 write(
message(3),
'(4x,a)')
'[1] N. Tancogne-Dejean, A. Rubio, and C. A. Ullrich, Phys. Rev. B 107, 165111 (2023)'
409 write(
message(4),
'(4x,a)')
'[2] E. Proynov et al., Chemical Physics Letters 455, 103 (2008)'
412 else if (functl%id == xc_mgga_c_nc_cs)
then
413 write(
message(1),
'(2x,a)')
'Correlation'
414 write(
message(2),
'(4x,a)')
'Noncollinear Colle-Salvetti (MGGA)'
415 write(
message(3),
'(4x,a)')
'[1] N. Tancogne-Dejean, A. Rubio, and C. A. Ullrich, Phys. Rev. B 107, 165111 (2023)'
419 else if (functl%id == xc_half_hartree)
then
420 write(
message(1),
'(2x,a)')
'Exchange-Correlation:'
421 write(
message(2),
'(4x,a)')
'Half-Hartree two-electron exchange'
424 else if(functl%id == xc_lda_c_fbe)
then
425 write(
message(1),
'(2x,a)')
'Correlation'
426 write(
message(2),
'(4x,a)')
'Force-based LDA correlation'
429 else if (functl%family /= xc_family_none)
then
430 select case (functl%type)
432 write(
message(1),
'(2x,a)')
'Exchange'
433 case (xc_correlation)
434 write(
message(1),
'(2x,a)')
'Correlation'
435 case (xc_exchange_correlation)
436 write(
message(1),
'(2x,a)')
'Exchange-correlation'
440 write(
message(1),
'(a,i6,a,i6)')
"Unknown functional type ", functl%type,
' for functional ', functl%id
444 select case (functl%family)
446 write(family,
'(a)')
"LDA"
448 write(family,
'(a)')
"GGA"
449 case (xc_family_mgga)
450 write(family,
'(a)')
"MGGA"
453 case (xc_family_hyb_lda)
454 write(family,
'(a)')
"Hybrid LDA"
455 case (xc_family_hyb_gga)
456 write(family,
'(a)')
"Hybrid GGA"
457 case (xc_family_hyb_mgga)
458 write(family,
'(a)')
"Hybrid MGGA"
460 write(
message(2),
'(4x,4a)') trim(xc_f03_func_info_get_name(functl%info)),
' (', trim(family),
')'
465 write(
message(1),
'(4x,a,i1,2a)')
'[', ii + 1,
'] ', &
466 trim(xc_f03_func_reference_get_ref(xc_f03_func_info_get_references(functl%info, ii)))
471 pop_sub(xc_functional_write_info)
472 end subroutine xc_functional_write_info
476 integer function xc_get_default_functional(dim, pseudo_x_functional, pseudo_c_functional)
result(default)
477 integer,
intent(in) :: dim
478 integer,
intent(in) :: pseudo_x_functional, pseudo_c_functional
480 push_sub(xc_get_default_functional)
485 default = pseudo_x_functional
491 default = xc_lda_x_2d
493 default = xc_lda_x_1d_soft
500 default = default + libxc_c_index*pseudo_c_functional
504 default = default + libxc_c_index * xc_lda_c_pz_mod
506 default = default + libxc_c_index * xc_lda_c_2d_amgb
508 default = default + libxc_c_index * xc_lda_c_1d_csc
514 pop_sub(xc_get_default_functional)
515 end function xc_get_default_functional
518 subroutine xc_check_dimension(functl, ndim, namespace)
519 type(xc_functional_t),
intent(in) :: functl
520 integer,
intent(in) :: ndim
521 type(namespace_t),
intent(in) :: namespace
525 push_sub(xc_check_dimension)
528 ok =
bitand(functl%flags, xc_flags_1d) /= 0
529 if (ndim == 1 .and. (.not. ok))
then
530 message(1) =
'Cannot use the specified functionals in 1D.'
534 ok =
bitand(functl%flags, xc_flags_2d) /= 0
535 if (ndim == 2 .and. (.not. ok))
then
536 message(1) =
'Cannot use the specified functionals in 2D.'
540 ok =
bitand(functl%flags, xc_flags_3d) /= 0
541 if (ndim == 3 .and. (.not. ok))
then
542 message(1) =
'Cannot use the specified functionals in 3D.'
546 pop_sub(xc_check_dimension)
547 end subroutine xc_check_dimension
550 logical function xc_functional_is_not_size_consistent(functl, namespace)
551 type(xc_functional_t),
intent(in) :: functl
552 type(namespace_t),
intent(in) :: namespace
554 integer :: n_ext_params, ip
555 character(len=128) :: ext_params_name
557 xc_functional_is_not_size_consistent = .false.
558 if (.not. functl%from_libxc)
return
560 push_sub(xc_functional_is_not_size_consistent)
563 n_ext_params = xc_f03_func_info_get_n_ext_params(functl%info)
564 do ip = 0, n_ext_params-1
565 ext_params_name = xc_f03_func_info_get_ext_params_name(functl%info, ip)
567 if (ext_params_name(1:1) ==
'_') cycle
568 if (trim(xc_f03_func_info_get_ext_params_description(functl%info, ip)) ==
'Number of electrons')
then
569 xc_functional_is_not_size_consistent = .
true.
574 if (xc_functional_is_not_size_consistent .and. n_ext_params > 1)
then
575 message(1) =
'The selected functional is currently not supported.'
579 pop_sub(xc_functional_is_not_size_consistent)
580 end function xc_functional_is_not_size_consistent
582 logical pure function xc_functional_is_energy_functional(functl)
583 type(xc_functional_t),
intent(in) :: functl
585 xc_functional_is_energy_functional =
bitand(functl%flags, xc_flags_have_exc) /= 0
586 end function xc_functional_is_energy_functional
588end module xc_functional_oct_m
real(real64), parameter, public m_one
subroutine, public libvdwxc_end(this)
subroutine, public libvdwxc_init(libvdwxc, namespace, functional)
subroutine, public libvdwxc_write_info(this, iunit, namespace)
subroutine, public messages_not_implemented(feature, namespace)
subroutine, public messages_warning(no_lines, all_nodes, namespace)
subroutine, public messages_obsolete_variable(namespace, name, rep)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
subroutine, public messages_input_error(namespace, var, details, row, column)
subroutine, public messages_experimental(name, namespace)
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
logical function, public parse_is_defined(namespace, name)
integer, parameter, public pseudo_correlation_any
integer, parameter, public pseudo_exchange_any