32#ifdef HAVE_LIBXC_FUNCS
41#include "functionals_list.F90"
57 integer,
public,
parameter :: &
58 XC_OEP_X = 901, & !< Exact exchange
79 integer,
public,
parameter :: &
80 XC_FAMILY_KS_INVERSION = 1024, &
88 integer :: family = xc_family_unknown
92 integer :: spin_channels = 0
95 logical,
private :: from_libxc = .false.
97 type(xc_f03_func_t) :: conf
98 type(xc_f03_func_info_t),
private :: info
99 type(libvdwxc_t) :: libvdwxc
102 integer,
public,
parameter :: LIBXC_C_INDEX = 1000
108 type(xc_f03_func_t),
intent(inout) :: conf
109 integer,
intent(in) :: func_id
110 integer,
intent(in) :: nspin
111 logical,
intent(in) :: on_cpu
113#ifdef HAVE_LIBXC_DEVICE
114 integer(c_int) :: xc_flag_host_device
117 xc_flag_host_device = xc_flags_on_host
119 xc_flag_host_device = xc_flags_on_device
122 call xc_f03_func_init_flags(conf, func_id, nspin, xc_flag_host_device)
124 if (.not. on_cpu)
then
125 message(1) =
"LibXC does not support device offloading,"
126 message(2) =
"but a functional was requested to be initialized on the device."
129 call xc_f03_func_init(conf, func_id, nspin)
134 subroutine xc_functional_init(functl, namespace, id, ndim, nel, spin_channels, functionals_on_cpu)
135 type(xc_functional_t),
intent(inout) :: functl
136 type(namespace_t),
intent(in) :: namespace
137 integer,
intent(in) :: id
138 integer,
intent(in) :: ndim
139 real(real64),
intent(in) :: nel
140 integer,
intent(in) :: spin_channels
141 logical,
intent(in) :: functionals_on_cpu
143 integer :: interact_1d
144 real(real64) :: alpha, parameters(2)
146 integer(c_int) :: xc_flag_host_device
152 functl%spin_channels = spin_channels
154 if (functl%id == 0)
then
155 functl%family = xc_family_none
158 functl%family = xc_f03_family_from_id(functl%id)
161 if (functl%family == xc_family_unknown)
then
163 select case (functl%id)
165 functl%family = xc_family_oep
168 functl%family = xc_family_lda
171 functl%family = xc_family_ks_inversion
181 functl%family = xc_family_hyb_gga
193#ifdef HAVE_LIBXC_DEVICE
194 if (functionals_on_cpu)
then
195 xc_flag_host_device = xc_flags_on_host
197 xc_flag_host_device = xc_flags_on_device
200 xc_flag_host_device = 0_c_int
203 if (functl%family == xc_family_oep)
then
204 functl%type = xc_exchange
205 functl%flags = xc_flags_1d + xc_flags_2d + xc_flags_3d + xc_flag_host_device
207 else if (functl%family == xc_family_ks_inversion .or. functl%family ==
xc_family_rdmft)
then
208 functl%type = xc_exchange_correlation
209 functl%flags = xc_flags_1d + xc_flags_2d + xc_flags_3d + xc_flag_host_device
213 functl%info = xc_f03_func_get_info(functl%conf)
214 functl%type = xc_f03_func_info_get_kind(functl%info)
215 functl%flags = xc_f03_func_info_get_flags(functl%info)
220 functl%type = xc_correlation
221 functl%flags = xc_flags_have_exc + xc_flags_have_vxc + xc_flags_3d
224 functl%type = xc_correlation
225 functl%flags = xc_flags_have_exc + xc_flags_have_vxc + xc_flags_3d + xc_flag_host_device
228 functl%type = xc_exchange
229 functl%flags = xc_flags_have_vxc + xc_flags_have_exc + xc_flags_3d + xc_flag_host_device
232 functl%type = xc_correlation
233 functl%flags = xc_flags_have_vxc + xc_flags_have_exc + xc_flags_3d + xc_flag_host_device
235 else if (functl%family == xc_family_none)
then
237 functl%flags = xc_flags_1d + xc_flags_2d + xc_flags_3d + xc_flag_host_device
241 functl%from_libxc = .
true.
244 select case (functl%id)
254 functl%info = xc_f03_func_get_info(functl%conf)
255 functl%type = xc_f03_func_info_get_kind(functl%info)
256 functl%flags = xc_f03_func_info_get_flags(functl%info)
259 if (
bitand(functl%flags, xc_flags_have_exc) == 0)
then
260 message(1) =
'Specified functional does not have total energy available.'
261 message(2) =
'Corresponding component of energy will just be left as zero.'
265 if (
bitand(functl%flags, xc_flags_have_vxc) == 0)
then
266 message(1) =
'Specified functional does not have XC potential available.'
267 message(2) =
'Cannot run calculations. Choose another XCFunctional.'
273 if (functl%family /= xc_family_none)
then
278 if (
bitand(functl%flags, xc_flags_hyb_camy) /= 0)
then
283 if (
bitand(functl%flags, xc_flags_vv10) /= 0)
then
289 select case (functl%id)
291 case (xc_lda_c_xalpha)
305 call xc_f03_func_set_ext_params(functl%conf,
parameters(1))
308 case (xc_lda_x_1d_soft, xc_lda_c_1d_csc)
323 call parse_variable(namespace,
'Interaction1D', option__interaction1d__interaction_soft_coulomb, interact_1d)
337 call xc_f03_func_set_ext_params(functl%conf,
parameters(1))
353 assert(xc_f03_func_info_get_n_ext_params(functl%info) == 1)
355 call xc_f03_func_set_ext_params(functl%conf,
parameters(1))
356 write(
message(1),
'(a,i1)')
"Info: Setting the number of electrons for the functional for spin ", spin_channels
366 type(xc_functional_t),
intent(inout) :: functl
370 if (functl%family /= xc_family_none .and. functl%family /= xc_family_oep .and. &
371 functl%family /= xc_family_ks_inversion .and. functl%id /=
xc_lda_c_fbe &
373 call xc_f03_func_end(functl%conf)
387 type(xc_functional_t),
intent(in) :: functl
388 integer,
optional,
intent(in) :: iunit
389 type(namespace_t),
optional,
intent(in) :: namespace
391 character(len=1024) :: reference
392 character(len=120) :: family
393 integer :: ii, ind, istart, iend
397 if (functl%family == xc_family_oep)
then
400 select case (functl%id)
402 write(
message(1),
'(2x,a)')
'Exchange'
403 write(
message(2),
'(4x,a)')
'Exact exchange'
407 write(
message(1),
'(2x,a)')
'Exchange'
408 write(
message(2),
'(4x,a)')
'Slater exchange'
412 write(
message(1),
'(2x,a)')
'Exchange'
413 write(
message(2),
'(4x,a)')
'Force-based local exchange'
414 write(
message(3),
'(4x,a)')
'[1] Tancogne-Dejean et al., J. Chem. Phys. 160, 024103 (2024)'
418 write(
message(1),
'(2x,a)')
'Exchange'
419 write(
message(2),
'(4x,a)')
'Force-based local exchange - Sturm-Liouville'
423 write(
message(1),
'(2x,a)')
'Correlation'
424 write(
message(2),
'(4x,a)')
'Force-based local-density correlation - Sturm-Liouville'
432 select case (functl%id)
434 write(
message(1),
'(2x,a)')
'RDMFT'
435 write(
message(2),
'(4x,a)')
'Mueller functional'
439 else if (functl%family == xc_family_ks_inversion)
then
441 select case (functl%id)
443 write(
message(1),
'(2x,a)')
'Exchange-Correlation:'
444 write(
message(2),
'(4x,a)')
' KS Inversion'
452 write(
message(1),
'(2x,a)')
'Exchange'
453 write(
message(2),
'(4x,a)')
'Noncollinear Becke-Roussel (MGGA)'
454 write(
message(3),
'(4x,a)')
'[1] N. Tancogne-Dejean, A. Rubio, and C. A. Ullrich, Phys. Rev. B 107, 165111 (2023)'
458 write(
message(1),
'(2x,a)')
'Exchange'
459 write(
message(2),
'(4x,a)')
'Noncollinear Becke-Roussel, gamma = 1.0 (MGGA)'
460 write(
message(3),
'(4x,a)')
'[1] N. Tancogne-Dejean, A. Rubio, and C. A. Ullrich, Phys. Rev. B 107, 165111 (2023)'
464 write(
message(1),
'(2x,a)')
'Exchange'
465 write(
message(2),
'(4x,a)')
'Noncollinear Becke-Roussel (MGGA) with explicit inversion of x(y)'
466 write(
message(3),
'(4x,a)')
'[1] N. Tancogne-Dejean, A. Rubio, and C. A. Ullrich, Phys. Rev. B 107, 165111 (2023)'
467 write(
message(4),
'(4x,a)')
'[2] E. Proynov et al., Chemical Physics Letters 455, 103 (2008)'
471 write(
message(1),
'(2x,a)')
'Correlation'
472 write(
message(2),
'(4x,a)')
'Noncollinear Colle-Salvetti (MGGA)'
473 write(
message(3),
'(4x,a)')
'[1] N. Tancogne-Dejean, A. Rubio, and C. A. Ullrich, Phys. Rev. B 107, 165111 (2023)'
477 write(
message(1),
'(2x,a)')
'Correlation'
478 write(
message(2),
'(4x,a)')
'Force-based LDA correlation'
479 write(
message(3),
'(4x,a)')
'[1] N. Tancogne-Dejean, M. Penz, M. Ruggenthaler, A. Rubio, J. Phys. Chem. A 129, 3132 (2025)'
482 else if (functl%family /= xc_family_none)
then
483 select case (functl%type)
485 write(
message(1),
'(2x,a)')
'Exchange'
486 case (xc_correlation)
487 write(
message(1),
'(2x,a)')
'Correlation'
488 case (xc_exchange_correlation)
489 write(
message(1),
'(2x,a)')
'Exchange-correlation'
493 write(
message(1),
'(a,i6,a,i6)')
"Unknown functional type ", functl%type,
' for functional ', functl%id
497 select case (functl%family)
499 write(family,
'(a)')
"LDA"
501 write(family,
'(a)')
"GGA"
502 case (xc_family_mgga)
503 write(family,
'(a)')
"MGGA"
506 case (xc_family_hyb_lda)
507 write(family,
'(a)')
"Hybrid LDA"
508 case (xc_family_hyb_gga)
509 write(family,
'(a)')
"Hybrid GGA"
510 case (xc_family_hyb_mgga)
511 write(family,
'(a)')
"Hybrid MGGA"
513 write(
message(2),
'(4x,4a)') trim(xc_f03_func_info_get_name(functl%info)),
' (', trim(family),
')'
517 do while(ii >= 0 .and. ii < 256)
520 write(reference,
'(a)') trim(xc_f03_func_reference_get_ref(xc_f03_func_info_get_references(functl%info, ii)))
522 if (len_trim(reference) == 0) cycle
525 write(
message(1),
'(4x,a,i1,2a)')
'[', ind,
'] ', trim(reference(istart:iend))
527 do while (iend < len_trim(reference))
529 iend = min(istart + len(
message(1))-10, len_trim(reference))
530 write(
message(1),
'(7x,a)') trim(reference(istart:iend))
542 integer,
intent(in) :: dim
543 integer,
intent(in) :: pseudo_x_functional, pseudo_c_functional
550 default = pseudo_x_functional
556 default = xc_lda_x_2d
558 default = xc_lda_x_1d_soft
565 default = default + libxc_c_index*pseudo_c_functional
569 default = default + libxc_c_index * xc_lda_c_pz_mod
571 default = default + libxc_c_index * xc_lda_c_2d_amgb
573 default = default + libxc_c_index * xc_lda_c_1d_csc
584 type(xc_functional_t),
intent(in) :: functl
585 integer,
intent(in) :: ndim
586 type(namespace_t),
intent(in) :: namespace
593 ok =
bitand(functl%flags, xc_flags_1d) /= 0
594 if (ndim == 1 .and. (.not. ok))
then
595 message(1) =
'Cannot use the specified functionals in 1D.'
599 ok =
bitand(functl%flags, xc_flags_2d) /= 0
600 if (ndim == 2 .and. (.not. ok))
then
601 message(1) =
'Cannot use the specified functionals in 2D.'
605 ok =
bitand(functl%flags, xc_flags_3d) /= 0
606 if (ndim == 3 .and. (.not. ok))
then
607 message(1) =
'Cannot use the specified functionals in 3D.'
616 type(xc_functional_t),
intent(in) :: functl
617 type(namespace_t),
intent(in) :: namespace
619 integer :: n_ext_params, ip
620 character(len=128) :: ext_params_name
623 if (.not. functl%from_libxc)
return
628 n_ext_params = xc_f03_func_info_get_n_ext_params(functl%info)
629 do ip = 0, n_ext_params-1
630 ext_params_name = xc_f03_func_info_get_ext_params_name(functl%info, ip)
632 if (ext_params_name(1:1) ==
'_') cycle
633 if (trim(xc_f03_func_info_get_ext_params_description(functl%info, ip)) ==
'Number of electrons')
then
640 message(1) =
'The selected functional is currently not supported.'
647 logical pure function xc_functional_is_energy_functional(functl)
648 type(xc_functional_t),
intent(in) :: functl
650 xc_functional_is_energy_functional =
bitand(functl%flags, xc_flags_have_exc) /= 0
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_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
integer, parameter, public xc_ks_inversion
inversion of Kohn-Sham potential
integer, parameter, public xc_vdw_c_vdwdf
vdw-df correlation from libvdwxc
integer, parameter, public xc_family_rdmft
subroutine, public xc_functional_write_info(functl, iunit, namespace)
Write functional information.
integer function, public xc_get_default_functional(dim, pseudo_x_functional, pseudo_c_functional)
Returns the default functional given the one parsed from the pseudopotentials and the space dimension...
integer, parameter, public xc_mgga_c_nc_cs
Noncollinear version of the Colle-Salvetti correlation functional.
subroutine, public xc_functional_init_func(conf, func_id, nspin, on_cpu)
integer, parameter, public xc_hyb_gga_xc_mvorb_pbeh
Density-based mixing parameter of PBE0.
subroutine, public xc_functional_init(functl, namespace, id, ndim, nel, spin_channels, functionals_on_cpu)
integer, parameter, public xc_mgga_x_nc_br
Noncollinear version of the Becke-Roussel functional.
integer, parameter, public xc_vdw_c_vdwdfcx
vdw-df-cx correlation from libvdwxc
integer, parameter, public xc_lda_c_fbe
LDA correlation based ib the force-balance equation.
integer, parameter, public xc_family_nc_mgga
integer, parameter, public xc_vdw_c_vdwdf2
vdw-df2 correlation from libvdwxc
subroutine xc_check_dimension(functl, ndim, namespace)
Check that the selected functional is compatible with the space dimension.
integer, parameter, public xc_family_libvdwxc
integer, parameter, public xc_hyb_gga_xc_mvorb_hse06
Density-based mixing parameter of HSE06.
subroutine, public xc_functional_end(functl)
integer, parameter, public xc_lda_c_fbe_sl
LDA correlation based ib the force-balance equation - Sturm-Liouville version.
integer, parameter, public xc_rdmft_xc_m
RDMFT Mueller functional.
integer, parameter, public xc_mgga_x_nc_br_1
Noncollinear version of the Becke-Roussel functional, gamma=1.
logical function, public xc_functional_is_not_size_consistent(functl, namespace)
Does the functional depend on the number of electrons or not.
integer, parameter, public xc_mgga_x_nc_br_explicit
Noncollinear version of the Becke-Roussel functional.
integer, parameter, public xc_family_nc_lda
integer, parameter, public xc_oep_x_fbe_sl
Exchange approximation based on the force balance equation - Sturn-Liouville version.
integer, parameter, public xc_oep_x_fbe
Exchange approximation based on the force balance equation.
logical pure function, public xc_functional_is_energy_functional(functl)
integer, parameter, public xc_oep_x_slater
Slater approximation to the exact exchange.