32#ifdef HAVE_LIBXC_FUNCS
41#include "functionals_list.F90"
58 integer,
public,
parameter :: &
59 XC_OEP_X = 9901, & !< Exact exchange
80 integer,
public,
parameter :: &
81 XC_FAMILY_KS_INVERSION = 1024, &
89 integer :: family = xc_family_unknown
93 integer :: spin_channels = 0
96 logical,
private :: from_libxc = .false.
98 type(xc_f03_func_t) :: conf
99 type(xc_f03_func_info_t),
private :: info
100 type(libvdwxc_t) :: libvdwxc
103 integer,
public,
parameter :: LIBXC_C_INDEX = 10000
109 type(xc_f03_func_t),
intent(inout) :: conf
110 integer,
intent(in) :: func_id
111 integer,
intent(in) :: nspin
112 logical,
intent(in) :: on_cpu
114#ifdef HAVE_LIBXC_DEVICE
115 integer(c_int) :: xc_flag_host_device
118 xc_flag_host_device = xc_flags_on_host
120 xc_flag_host_device = xc_flags_on_device
123 call xc_f03_func_init_flags(conf, func_id, nspin, xc_flag_host_device)
125 if (.not. on_cpu)
then
126 message(1) =
"LibXC does not support device offloading,"
127 message(2) =
"but a functional was requested to be initialized on the device."
130 call xc_f03_func_init(conf, func_id, nspin)
135 subroutine xc_functional_init(functl, namespace, id, ndim, nel, spin_channels, functionals_on_cpu)
136 type(xc_functional_t),
intent(inout) :: functl
137 type(namespace_t),
intent(in) :: namespace
138 integer,
intent(in) :: id
139 integer,
intent(in) :: ndim
140 real(real64),
intent(in) :: nel
141 integer,
intent(in) :: spin_channels
142 logical,
intent(in) :: functionals_on_cpu
144 integer :: interact_1d
145 real(real64) :: alpha, parameters(2)
147 integer(c_int) :: xc_flag_host_device
153 functl%spin_channels = spin_channels
155 if (functl%id == 0)
then
156 functl%family = xc_family_none
159 functl%family = xc_f03_family_from_id(functl%id)
162 if (functl%family == xc_family_unknown)
then
164 select case (functl%id)
166 functl%family = xc_family_oep
169 functl%family = xc_family_lda
172 functl%family = xc_family_ks_inversion
182 functl%family = xc_family_hyb_gga
194#ifdef HAVE_LIBXC_DEVICE
195 if (functionals_on_cpu)
then
196 xc_flag_host_device = xc_flags_on_host
198 xc_flag_host_device = xc_flags_on_device
201 xc_flag_host_device = 0_c_int
204 if (functl%family == xc_family_oep)
then
205 functl%type = xc_exchange
206 functl%flags = xc_flags_1d + xc_flags_2d + xc_flags_3d + xc_flag_host_device
208 else if (functl%family == xc_family_ks_inversion .or. functl%family ==
xc_family_rdmft)
then
209 functl%type = xc_exchange_correlation
210 functl%flags = xc_flags_1d + xc_flags_2d + xc_flags_3d + xc_flag_host_device
214 functl%info = xc_f03_func_get_info(functl%conf)
215 functl%type = xc_f03_func_info_get_kind(functl%info)
216 functl%flags = xc_f03_func_info_get_flags(functl%info)
221 functl%type = xc_correlation
222 functl%flags = xc_flags_have_exc + xc_flags_have_vxc + xc_flags_3d
225 functl%type = xc_correlation
226 functl%flags = xc_flags_have_exc + xc_flags_have_vxc + xc_flags_3d + xc_flag_host_device
229 functl%type = xc_exchange
230 functl%flags = xc_flags_have_vxc + xc_flags_have_exc + xc_flags_3d + xc_flag_host_device
233 functl%type = xc_correlation
234 functl%flags = xc_flags_have_vxc + xc_flags_have_exc + xc_flags_3d + xc_flag_host_device
236 else if (functl%family == xc_family_none)
then
238 functl%flags = xc_flags_1d + xc_flags_2d + xc_flags_3d + xc_flag_host_device
242 functl%from_libxc = .
true.
245 select case (functl%id)
255 functl%info = xc_f03_func_get_info(functl%conf)
256 functl%type = xc_f03_func_info_get_kind(functl%info)
257 functl%flags = xc_f03_func_info_get_flags(functl%info)
260 if (
bitand(functl%flags, xc_flags_have_exc) == 0)
then
261 message(1) =
'Specified functional does not have total energy available.'
262 message(2) =
'Corresponding component of energy will just be left as zero.'
266 if (
bitand(functl%flags, xc_flags_have_vxc) == 0)
then
267 message(1) =
'Specified functional does not have XC potential available.'
268 message(2) =
'Cannot run calculations. Choose another XCFunctional.'
274 if (functl%family /= xc_family_none)
then
279 if (
bitand(functl%flags, xc_flags_hyb_camy) /= 0)
then
284 if (
bitand(functl%flags, xc_flags_vv10) /= 0)
then
290 select case (functl%id)
292 case (xc_lda_c_xalpha)
306 call xc_f03_func_set_ext_params(functl%conf,
parameters(1))
309 case (xc_lda_x_1d_soft, xc_lda_c_1d_csc)
324 call parse_variable(namespace,
'Interaction1D', option__interaction1d__interaction_soft_coulomb, interact_1d)
338 call xc_f03_func_set_ext_params(functl%conf,
parameters(1))
354 assert(xc_f03_func_info_get_n_ext_params(functl%info) == 1)
356 call xc_f03_func_set_ext_params(functl%conf,
parameters(1))
357 write(
message(1),
'(a,i1)')
"Info: Setting the number of electrons for the functional for spin ", spin_channels
367 type(xc_functional_t),
intent(inout) :: functl
371 if (functl%family /= xc_family_none .and. functl%family /= xc_family_oep .and. &
372 functl%family /= xc_family_ks_inversion .and. functl%id /=
xc_lda_c_fbe &
374 call xc_f03_func_end(functl%conf)
388 type(xc_functional_t),
intent(in) :: functl
389 integer,
optional,
intent(in) :: iunit
390 type(namespace_t),
optional,
intent(in) :: namespace
392 character(len=1024) :: reference
393 character(len=120) :: family
394 integer :: ii, ind, istart, iend
398 if (functl%family == xc_family_oep)
then
401 select case (functl%id)
403 write(
message(1),
'(2x,a)')
'Exchange'
404 write(
message(2),
'(4x,a)')
'Exact exchange'
408 write(
message(1),
'(2x,a)')
'Exchange'
409 write(
message(2),
'(4x,a)')
'Slater exchange'
413 write(
message(1),
'(2x,a)')
'Exchange'
414 write(
message(2),
'(4x,a)')
'Force-based local exchange'
415 write(
message(3),
'(4x,a)')
'[1] Tancogne-Dejean et al., J. Chem. Phys. 160, 024103 (2024)'
419 write(
message(1),
'(2x,a)')
'Exchange'
420 write(
message(2),
'(4x,a)')
'Force-based local exchange - Sturm-Liouville'
424 write(
message(1),
'(2x,a)')
'Correlation'
425 write(
message(2),
'(4x,a)')
'Force-based local-density correlation - Sturm-Liouville'
433 select case (functl%id)
435 write(
message(1),
'(2x,a)')
'RDMFT'
436 write(
message(2),
'(4x,a)')
'Mueller functional'
440 else if (functl%family == xc_family_ks_inversion)
then
442 select case (functl%id)
444 write(
message(1),
'(2x,a)')
'Exchange-Correlation:'
445 write(
message(2),
'(4x,a)')
' KS Inversion'
453 write(
message(1),
'(2x,a)')
'Exchange'
454 write(
message(2),
'(4x,a)')
'Noncollinear Becke-Roussel (MGGA)'
455 write(
message(3),
'(4x,a)')
'[1] N. Tancogne-Dejean, A. Rubio, and C. A. Ullrich, Phys. Rev. B 107, 165111 (2023)'
459 write(
message(1),
'(2x,a)')
'Exchange'
460 write(
message(2),
'(4x,a)')
'Noncollinear Becke-Roussel, gamma = 1.0 (MGGA)'
461 write(
message(3),
'(4x,a)')
'[1] N. Tancogne-Dejean, A. Rubio, and C. A. Ullrich, Phys. Rev. B 107, 165111 (2023)'
465 write(
message(1),
'(2x,a)')
'Exchange'
466 write(
message(2),
'(4x,a)')
'Noncollinear Becke-Roussel (MGGA) with explicit inversion of x(y)'
467 write(
message(3),
'(4x,a)')
'[1] N. Tancogne-Dejean, A. Rubio, and C. A. Ullrich, Phys. Rev. B 107, 165111 (2023)'
468 write(
message(4),
'(4x,a)')
'[2] E. Proynov et al., Chemical Physics Letters 455, 103 (2008)'
472 write(
message(1),
'(2x,a)')
'Correlation'
473 write(
message(2),
'(4x,a)')
'Noncollinear Colle-Salvetti (MGGA)'
474 write(
message(3),
'(4x,a)')
'[1] N. Tancogne-Dejean, A. Rubio, and C. A. Ullrich, Phys. Rev. B 107, 165111 (2023)'
478 write(
message(1),
'(2x,a)')
'Correlation'
479 write(
message(2),
'(4x,a)')
'Force-based LDA correlation'
480 write(
message(3),
'(4x,a)')
'[1] N. Tancogne-Dejean, M. Penz, M. Ruggenthaler, A. Rubio, J. Phys. Chem. A 129, 3132 (2025)'
483 else if (functl%family /= xc_family_none)
then
484 select case (functl%type)
486 write(
message(1),
'(2x,a)')
'Exchange'
487 case (xc_correlation)
488 write(
message(1),
'(2x,a)')
'Correlation'
489 case (xc_exchange_correlation)
490 write(
message(1),
'(2x,a)')
'Exchange-correlation'
494 write(
message(1),
'(a,i6,a,i6)')
"Unknown functional type ", functl%type,
' for functional ', functl%id
498 select case (functl%family)
500 write(family,
'(a)')
"LDA"
502 write(family,
'(a)')
"GGA"
503 case (xc_family_mgga)
504 write(family,
'(a)')
"MGGA"
507 case (xc_family_hyb_lda)
508 write(family,
'(a)')
"Hybrid LDA"
509 case (xc_family_hyb_gga)
510 write(family,
'(a)')
"Hybrid GGA"
511 case (xc_family_hyb_mgga)
512 write(family,
'(a)')
"Hybrid MGGA"
514 write(
message(2),
'(4x,4a)') trim(xc_f03_func_info_get_name(functl%info)),
' (', trim(family),
')'
518 do while(ii >= 0 .and. ii < 256)
521 write(reference,
'(a)') trim(xc_f03_func_reference_get_ref(xc_f03_func_info_get_references(functl%info, ii)))
523 if (len_trim(reference) == 0) cycle
526 write(
message(1),
'(4x,a,i1,2a)')
'[', ind,
'] ', trim(reference(istart:iend))
528 do while (iend < len_trim(reference))
530 iend = min(istart + len(
message(1))-10, len_trim(reference))
531 write(
message(1),
'(7x,a)') trim(reference(istart:iend))
543 integer,
intent(in) :: dim
544 integer,
intent(in) :: pseudo_x_functional, pseudo_c_functional
551 default = pseudo_x_functional
557 default = xc_lda_x_2d
559 default = xc_lda_x_1d_soft
566 default = default + libxc_c_index*pseudo_c_functional
570 default = default + libxc_c_index * xc_lda_c_pz_mod
572 default = default + libxc_c_index * xc_lda_c_2d_amgb
574 default = default + libxc_c_index * xc_lda_c_1d_csc
585 type(xc_functional_t),
intent(in) :: functl
586 integer,
intent(in) :: ndim
587 type(namespace_t),
intent(in) :: namespace
594 ok =
bitand(functl%flags, xc_flags_1d) /= 0
595 if (ndim == 1 .and. (.not. ok))
then
596 message(1) =
'Cannot use the specified functionals in 1D.'
600 ok =
bitand(functl%flags, xc_flags_2d) /= 0
601 if (ndim == 2 .and. (.not. ok))
then
602 message(1) =
'Cannot use the specified functionals in 2D.'
606 ok =
bitand(functl%flags, xc_flags_3d) /= 0
607 if (ndim == 3 .and. (.not. ok))
then
608 message(1) =
'Cannot use the specified functionals in 3D.'
617 type(xc_functional_t),
intent(in) :: functl
618 type(namespace_t),
intent(in) :: namespace
620 integer :: n_ext_params, ip
621 character(len=128) :: ext_params_name
624 if (.not. functl%from_libxc)
return
629 n_ext_params = xc_f03_func_info_get_n_ext_params(functl%info)
630 do ip = 0, n_ext_params-1
631 ext_params_name = xc_f03_func_info_get_ext_params_name(functl%info, ip)
633 if (ext_params_name(1:1) ==
'_') cycle
634 if (trim(xc_f03_func_info_get_ext_params_description(functl%info, ip)) ==
'Number of electrons')
then
641 message(1) =
'The selected functional is currently not supported.'
648 logical pure function xc_functional_is_energy_functional(functl)
649 type(xc_functional_t),
intent(in) :: functl
651 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.