LCOV - code coverage report
Current view: top level - src/xc - xc_libxc_wrap.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:123285f) Lines: 67.8 % 363 246
Test Date: 2026-11-04 00:58:17 Functions: 72.5 % 40 29

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Includes all necessary routines, functions and parameters from
      10              : !>        libxc. Provides CP2K routines/functions where the LibXC calling list
      11              : !>        is version dependent (>=4.0.3). The naming convention for such
      12              : !>        routines/functions is xc_f03_XXX --> 'xc_libxc_wrap_XXX'. All version
      13              : !>        independent routines/functions are just bypassed to higher level
      14              : !>        module file 'xc_libxc'.
      15              : !>
      16              : !> \par History
      17              : !>      08.2015 created [A. Gloess (agloess)]
      18              : !>      01.2018 refactoring [A. Gloess (agloess)]
      19              : !>      10.2018/04.2019 added hyb_mgga [S. Simko, included by F. Stein]
      20              : !> \author A. Gloess (agloess)
      21              : ! **************************************************************************************************
      22              : #:include 'xc_gamma.fypp'
      23              : 
      24              : #! Every staging buffer of a worker, so that the component count and the
      25              : #! release cannot fall out of step with the allocation.
      26              : #:set worker_1d = ["exc", "nd", "nda", "ndb"]
      27              : #:set worker_2d = ["rho", "sigma", "lapl", "tau", "vrho", "vsigma", "vlapl", "vtau", &
      28              :                  & "v2rho2", "v2rhosigma", "v2sigma2", "v2rholapl", "v2rhotau", &
      29              :                  & "v2sigmalapl", "v2sigmatau", "v2lapl2", "v2lapltau", "v2tau2", &
      30              :                  & "v3rho3", "v3rho2sigma", "v3rhosigma2", "v3sigma3"] + v3_new
      31              : 
      32              : MODULE xc_libxc_wrap
      33              : #if defined (__LIBXC)
      34              : #include <xc_version.h>
      35              : ! check for LibXC version - updated for LibXC 7.x
      36              : #if (XC_MAJOR_VERSION < 7)
      37              : #error "This version of CP2K requires libxc version 7.x or above for full functionality. Some features may not be available with older versions."
      38              : #else
      39              :    USE kinds, ONLY: dp
      40              :    USE input_constants, ONLY: do_libxc_cpu, do_libxc_gpu
      41              :    USE xc_f03_lib_m, ONLY: xc_f03_func_end, &
      42              :                            xc_f03_func_init, &
      43              :                            xc_f03_functional_get_name, &
      44              :                            xc_f03_func_set_ext_params, &
      45              :                            xc_f03_func_set_dens_threshold, &
      46              :                            xc_f03_func_set_tau_threshold, &
      47              :                            xc_f03_version_string, &
      48              :                            xc_f03_reference, &
      49              :                            xc_f03_reference_doi, &
      50              :                            xc_f03_functional_get_number, &
      51              :                            xc_f03_available_functional_numbers, &
      52              :                            xc_f03_available_functional_names, &
      53              :                            xc_f03_maximum_name_length, &
      54              :                            xc_f03_number_of_functionals, &
      55              :                            !
      56              :                            xc_f03_gga_exc, &
      57              :                            xc_f03_gga_exc_vxc, &
      58              :                            xc_f03_gga_exc_vxc_fxc, &
      59              :                            xc_f03_gga_exc_vxc_fxc_kxc, &
      60              :                            xc_f03_mgga_exc_vxc_fxc_kxc, &
      61              :                            xc_f03_mgga_vxc_fxc_kxc, &
      62              :                            xc_f03_gga_fxc, &
      63              :                            xc_f03_gga_vxc, &
      64              :                            xc_f03_gga_vxc_fxc, &
      65              :                            xc_f03_gga_vxc_fxc_kxc, &
      66              :                            !
      67              :                            xc_f03_func_get_info, &
      68              :                            xc_f03_func_info_get_family, &
      69              :                            xc_f03_func_info_get_kind, &
      70              :                            xc_f03_func_info_get_name, &
      71              :                            xc_f03_func_info_get_references, &
      72              :                            xc_f03_func_info_get_flags, &
      73              :                            xc_f03_func_info_get_n_ext_params, &
      74              :                            xc_f03_func_info_get_ext_params_name, &
      75              :                            xc_f03_func_info_get_ext_params_default_value, &
      76              :                            xc_f03_func_info_get_ext_params_description, &
      77              :                            !
      78              :                            xc_f03_func_reference_get_ref, &
      79              :                            xc_f03_func_reference_get_doi, &
      80              :                            !
      81              :                            xc_f03_lda_exc_vxc_fxc_kxc, &
      82              :                            xc_f03_lda_exc, &
      83              :                            xc_f03_lda_exc_vxc, &
      84              :                            xc_f03_lda_exc_vxc_fxc, &
      85              :                            xc_f03_lda_fxc, &
      86              :                            xc_f03_lda_kxc, &
      87              :                            xc_f03_lda_vxc, &
      88              :                            xc_f03_lda_vxc_fxc, &
      89              :                            xc_f03_lda_vxc_fxc_kxc, &
      90              :                            !
      91              :                            xc_f03_mgga_exc_vxc_fxc, &
      92              :                            xc_f03_mgga_exc, &
      93              :                            xc_f03_mgga_exc_vxc, &
      94              :                            xc_f03_mgga_fxc, &
      95              :                            xc_f03_mgga_vxc, &
      96              :                            xc_f03_mgga_vxc_fxc, &
      97              :                            !
      98              :                            xc_f03_func_t, &
      99              :                            xc_f03_func_info_t, &
     100              :                            xc_f03_func_reference_t, &
     101              :                            !
     102              :                            XC_FAMILY_LDA, &
     103              :                            XC_FAMILY_GGA, &
     104              :                            XC_FAMILY_MGGA, &
     105              :                            XC_FAMILY_HYB_LDA, &
     106              :                            XC_FAMILY_HYB_GGA, &
     107              :                            XC_FAMILY_HYB_MGGA, &
     108              :                            !
     109              :                            XC_UNPOLARIZED, &
     110              :                            XC_POLARIZED, &
     111              :                            !
     112              :                            XC_EXCHANGE, &
     113              :                            XC_CORRELATION, &
     114              :                            XC_EXCHANGE_CORRELATION, &
     115              :                            XC_KINETIC, &
     116              :                            !
     117              :                            XC_FLAGS_NEEDS_LAPLACIAN, &
     118              :                            XC_FLAGS_HAVE_EXC, &
     119              :                            XC_FLAGS_DEVELOPMENT, &
     120              :                            XC_FLAGS_ON_HOST, &
     121              :                            XC_FLAGS_ON_DEVICE, &
     122              :                            xc_f03_func_info_set_default_flags
     123              : 
     124              : #include "../base/base_uses.f90"
     125              :    USE ISO_C_BINDING, ONLY: C_PTR, C_NULL_PTR, C_SIZE_T, C_ASSOCIATED, C_LOC
     126              : #endif
     127              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_LIBXC)
     128              :    USE offload_api, ONLY: offload_buffer_type
     129              : #endif
     130              :    IMPLICIT NONE
     131              :    PRIVATE
     132              : #if defined (__LIBXC)
     133              : 
     134              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'xc_libxc_wrap'
     135              : 
     136              :    CHARACTER(LEN=*), PARAMETER, PUBLIC :: libxc_version = XC_VERSION
     137              : 
     138              :    PUBLIC :: xc_f03_func_t, xc_f03_func_info_t
     139              :    PUBLIC :: xc_f03_func_init, xc_f03_func_end, xc_f03_func_set_ext_params
     140              :    PUBLIC :: xc_f03_functional_get_name, xc_f03_available_functional_numbers, xc_f03_maximum_name_length, &
     141              :              xc_f03_number_of_functionals, xc_f03_available_functional_names
     142              :    PUBLIC :: xc_f03_func_get_info, xc_f03_func_info_get_family, xc_f03_func_info_get_kind, &
     143              :              xc_f03_func_info_get_name, xc_f03_func_info_get_ext_params_name, &
     144              :              xc_f03_func_info_get_ext_params_description, xc_f03_func_info_get_ext_params_default_value, &
     145              :              xc_f03_func_info_get_n_ext_params
     146              :    PUBLIC :: xc_f03_gga_exc, xc_f03_gga_exc_vxc, xc_f03_gga_exc_vxc_fxc, xc_f03_gga_fxc, &
     147              :              xc_f03_gga_vxc, xc_f03_gga_vxc_fxc, &
     148              :              xc_f03_gga_exc_vxc_fxc_kxc, xc_f03_gga_vxc_fxc_kxc
     149              :    PUBLIC :: xc_f03_mgga_exc_vxc_fxc_kxc, xc_f03_mgga_vxc_fxc_kxc, &
     150              :              xc_f03_mgga_exc, xc_f03_mgga_exc_vxc, xc_f03_mgga_exc_vxc_fxc, &
     151              :              xc_f03_mgga_fxc, xc_f03_mgga_vxc, xc_f03_mgga_vxc_fxc
     152              : 
     153              :    PUBLIC :: XC_FAMILY_LDA, XC_FAMILY_GGA, XC_FAMILY_MGGA, &
     154              :              XC_FAMILY_HYB_LDA, XC_FAMILY_HYB_GGA, XC_FAMILY_HYB_MGGA
     155              : 
     156              :    PUBLIC :: XC_UNPOLARIZED, XC_POLARIZED
     157              : 
     158              :    PUBLIC :: XC_EXCHANGE, XC_CORRELATION, XC_EXCHANGE_CORRELATION, XC_KINETIC
     159              :    PUBLIC :: XC_FLAGS_ON_HOST, XC_FLAGS_ON_DEVICE
     160              : 
     161              :    ! Create aliases for backward compatibility with the LibXC 6.x interface,
     162              :    ! which referenced xc_f03_lda / xc_f03_mgga as all-in-one evaluation entries.
     163              :    PUBLIC :: xc_f03_lda, xc_f03_mgga
     164              :    PUBLIC :: xc_f03_lda_exc, xc_f03_lda_exc_vxc, xc_f03_lda_exc_vxc_fxc, &
     165              :              xc_f03_lda_fxc, xc_f03_lda_kxc, xc_f03_lda_vxc
     166              : 
     167              :    ! Runtime backend selection. Whether a device backend can ever be selected is
     168              :    ! a compile-time property (__OFFLOAD and !__NO_OFFLOAD_LIBXC), but the flag
     169              :    ! itself is always compiled so that callers keep a single runtime branch; on
     170              :    ! CPU-only builds it can never become the GPU.
     171              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_LIBXC)
     172              :    LOGICAL, PARAMETER, PRIVATE :: libxc_have_device = .TRUE.
     173              : #else
     174              :    LOGICAL, PARAMETER, PRIVATE :: libxc_have_device = .FALSE.
     175              : #endif
     176              :    INTEGER, SAVE, PRIVATE :: libxc_backend = MERGE(do_libxc_gpu, do_libxc_cpu, libxc_have_device)
     177              : 
     178              :    ! Debug switch: test the freshly evaluated block for NaNs. Kept here because
     179              :    ! the per-block evaluation now runs inside this module.
     180              :    LOGICAL, PARAMETER, PRIVATE :: libxc_check_nan = .FALSE.
     181              : 
     182              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_LIBXC)
     183              :    ! Device buffer type for GPU memory management. It wraps an offload buffer so
     184              :    ! that the host-side pinned staging memory and the device allocation share a
     185              :    ! lifetime and are released exactly once, together.
     186              :    TYPE, PRIVATE :: libxc_device_buffer_type
     187              :       TYPE(offload_buffer_type) :: buffer
     188              :       INTEGER(KIND=C_SIZE_T) :: size = 0
     189              :    END TYPE libxc_device_buffer_type
     190              : #endif
     191              : 
     192              : ! wrappers for routines
     193              :    PUBLIC :: xc_libxc_wrap_info_refs, &
     194              :              xc_libxc_wrap_version, &
     195              :              xc_libxc_wrap_library_reference, &
     196              :              xc_libxc_wrap_info_needs_laplace, &
     197              :              xc_libxc_wrap_info_no_exc, &
     198              :              xc_libxc_wrap_set_thresholds, &
     199              :              xc_libxc_wrap_functional_get_number, &
     200              :              xc_libxc_wrap_is_under_development, &
     201              :              xc_libxc_get_reference_length, &
     202              :              xc_libxc_check_functional, &
     203              :              xc_libxc_wrap_init_safe, &
     204              :              libxc_set_backend, &
     205              :              libxc_func_init_wrapper, &
     206              :              libxc_gga_exc_vxc_wrapper, libxc_gga_exc_wrapper, &
     207              :              libxc_lda_exc_vxc_wrapper, libxc_lda_exc_wrapper, &
     208              :              libxc_mgga_exc_vxc_wrapper, libxc_mgga_exc_wrapper, &
     209              :              libxc_mgga_vxc_wrapper
     210              :    PUBLIC :: libxc_is_gpu
     211              : 
     212              :    ! Worker type: one LibXC functional object plus the host staging buffers used
     213              :    ! to hand it a block of grid points, together with the device buffers mirroring
     214              :    ! them on the GPU backend. It lives in the wrapper because it owns the device
     215              :    ! buffers; CPU-only builds compile an empty device section but the same type.
     216              :    ! One worker is kept per OpenMP thread, so neither the functional object nor
     217              :    ! the buffers are rebuilt between batches.
     218              :    INTEGER, PARAMETER, PRIVATE :: libxc_max_dev_buffers = 64
     219              : 
     220              :    TYPE, PUBLIC :: libxc_worker_type
     221              :       TYPE(xc_f03_func_t)                                :: func = xc_f03_func_t()
     222              :       TYPE(xc_f03_func_info_t)                           :: info = xc_f03_func_info_t()
     223              :       LOGICAL                                            :: is_init = .FALSE.
     224              :       ! number of points the staging buffers below were allocated for
     225              :       INTEGER                                            :: nb = 0
     226              :       ! staging buffers, dimensioned (component, point)
     227              :       REAL(KIND=dp), DIMENSION(:, :), ALLOCATABLE        :: rho, sigma, lapl, tau
     228              :       ! the floored gradient norms the spin-polarized chain rule is written in
     229              :       REAL(KIND=dp), DIMENSION(:), ALLOCATABLE           :: nd, nda, ndb
     230              :       REAL(KIND=dp), DIMENSION(:), ALLOCATABLE           :: exc
     231              :       REAL(KIND=dp), DIMENSION(:, :), ALLOCATABLE        :: vrho, vsigma, vlapl, vtau
     232              :       REAL(KIND=dp), DIMENSION(:, :), ALLOCATABLE        :: v2rho2, v2rhosigma, v2sigma2, &
     233              :                                                             v2rholapl, v2rhotau, v2sigmalapl, &
     234              :                                                             v2sigmatau, v2lapl2, v2lapltau, v2tau2
     235              :       REAL(KIND=dp), DIMENSION(:, :), ALLOCATABLE        :: v3rho3, v3rho2sigma, &
     236              :                                                             v3rhosigma2, v3sigma3
     237              :       #:for arr in v3_new
     238              :          REAL(KIND=dp), DIMENSION(:, :), ALLOCATABLE        :: ${arr}$
     239              :       #:endfor
     240              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_LIBXC)
     241              :       ! GPU device buffers for the active backend, indexed by the caller with the
     242              :       ! libxc_dev_* slot constants defined in this module.
     243              :       TYPE(libxc_device_buffer_type), DIMENSION(libxc_max_dev_buffers) :: dev
     244              : #endif
     245              :    END TYPE libxc_worker_type
     246              : 
     247              :    ! Slot integers naming the device buffers, used only by the host/device copy
     248              :    ! routines above; the generated third-derivative arrays continue after the
     249              :    ! hand-written ones.
     250              :    INTEGER, PARAMETER, PRIVATE :: libxc_dev_rho = 1, libxc_dev_sigma = 2, &
     251              :                                   libxc_dev_lapl = 3, libxc_dev_tau = 4, &
     252              :                                   libxc_dev_exc = 5, libxc_dev_vrho = 6, &
     253              :                                   libxc_dev_vsigma = 7, libxc_dev_vlapl = 8, &
     254              :                                   libxc_dev_vtau = 9, libxc_dev_v2rho2 = 10, &
     255              :                                   libxc_dev_v2rhosigma = 11, libxc_dev_v2sigma2 = 12, &
     256              :                                   libxc_dev_v2rholapl = 13, libxc_dev_v2rhotau = 14, &
     257              :                                   libxc_dev_v2sigmalapl = 15, libxc_dev_v2sigmatau = 16, &
     258              :                                   libxc_dev_v2lapl2 = 17, libxc_dev_v2lapltau = 18, &
     259              :                                   libxc_dev_v2tau2 = 19, libxc_dev_v3rho3 = 20, &
     260              :                                   libxc_dev_v3rho2sigma = 21, libxc_dev_v3rhosigma2 = 22, &
     261              :                                   libxc_dev_v3sigma3 = 23
     262              :    INTEGER, PARAMETER, PRIVATE :: libxc_dev_first_new3 = 24
     263              :    #:for i, arr in enumerate(v3_new)
     264              :       INTEGER, PARAMETER, PRIVATE :: libxc_dev_${arr}$ = libxc_dev_first_new3 + ${i}$
     265              :    #:endfor
     266              : 
     267              :    PUBLIC :: libxc_worker_alloc, libxc_worker_free_buffers, &
     268              :              libxc_worker_resize_cuda, libxc_worker_eval, libxc_family_flags
     269              : 
     270              :    ! Alias definitions for backward compatibility
     271              :    PROCEDURE(xc_f03_lda_exc_vxc_fxc_kxc), POINTER :: xc_f03_lda => xc_f03_lda_exc_vxc_fxc_kxc
     272              :    PROCEDURE(xc_f03_mgga_exc_vxc_fxc), POINTER :: xc_f03_mgga => xc_f03_mgga_exc_vxc_fxc
     273              : 
     274              : CONTAINS
     275              : 
     276              :    ! Backend selection: the runtime libxc_backend switch, fed by
     277              :    ! &XC/LIBXC_GPU_BACKEND (see libxc_set_backend). Whether a device backend can
     278              :    ! ever be selected is a compile-time property (__OFFLOAD and
     279              :    ! !defined(__NO_OFFLOAD_LIBXC)).
     280              : ! **************************************************************************************************
     281              : !> \brief Runtime switch for the LibXC backend, fed by &XC/LIBXC_GPU_BACKEND.
     282              : !> \param backend one of do_libxc_cpu / do_libxc_gpu
     283              : !> \note Whether a device backend can ever be selected is a compile-time property
     284              : !>       (__OFFLOAD and !defined(__NO_OFFLOAD_LIBXC)). A DEVICE request on a build
     285              : !>       without a device path is an error.
     286              : ! **************************************************************************************************
     287       166849 :    SUBROUTINE libxc_set_backend(backend)
     288              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_LIBXC)
     289              :       USE offload_api, ONLY: offload_get_device_count
     290              : #endif
     291              :       INTEGER, INTENT(IN)                                :: backend
     292              : 
     293              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_LIBXC)
     294              :       ! Honor the request only when an accelerator is usable at runtime;
     295              :       ! a DEVICE request without one is an error.
     296              :       SELECT CASE (backend)
     297              :       CASE (do_libxc_gpu)
     298              :          IF (offload_get_device_count() > 0) THEN
     299              :             libxc_backend = do_libxc_gpu
     300              :          ELSE
     301              :             CALL cp__b(__SHORT_FILE__, __LINE__, &
     302              :                        "&XC/LIBXC_GPU_BACKEND requests DEVICE, "// &
     303              :                        "but no usable device/GPU was found at runtime.")
     304              :          END IF
     305              :       CASE default
     306              :          libxc_backend = do_libxc_cpu
     307              :       END SELECT
     308              : #else
     309              :       ! Without a device path a DEVICE request is an error, HOST runs.
     310       166849 :       IF (backend == do_libxc_gpu) THEN
     311              :          CALL cp__b(__SHORT_FILE__, __LINE__, &
     312              :                     "LibXC was compiled without a device/GPU backend, "// &
     313            0 :                     "but &XC/LIBXC_GPU_BACKEND requests DEVICE.")
     314              :       END IF
     315       166849 :       libxc_backend = do_libxc_cpu
     316              : #endif
     317       166849 :    END SUBROUTINE libxc_set_backend
     318              : 
     319              : ! **************************************************************************************************
     320              : !> \brief Set the default LibXC functional flags to host.
     321              : ! **************************************************************************************************
     322          291 :    SUBROUTINE xc_libxc_wrap_init_safe()
     323              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'xc_libxc_wrap_init_safe'
     324              : 
     325              :       INTEGER                                            :: handle
     326              : 
     327          291 :       CALL timeset(routineN, handle)
     328              : 
     329              :       ! Set default flags
     330          291 :       CALL xc_f03_func_info_set_default_flags(XC_FLAGS_ON_HOST)
     331              : 
     332          291 :       CALL timestop(handle)
     333          291 :    END SUBROUTINE xc_libxc_wrap_init_safe
     334              : 
     335              : ! **************************************************************************************************
     336              : !> \brief Provides the reference(s) for this functional.
     337              : !> \param xc_info func_info object of the functional
     338              : !> \return upper bound for the length of the reference string
     339              : !> \author F. Stein
     340              : ! **************************************************************************************************
     341          121 :    FUNCTION xc_libxc_get_reference_length(xc_info) RESULT(length)
     342              : 
     343              :       TYPE(xc_f03_func_info_t), INTENT(IN)               :: xc_info
     344              :       INTEGER                                            :: length
     345              : 
     346              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'xc_libxc_get_reference_length'
     347              :       INTEGER, PARAMETER                                 :: maxlen = 67
     348              : 
     349              :       CHARACTER(LEN=1024)                                :: doi_string, ref_string
     350              :       CHARACTER(LEN=128)                                 :: descr_string
     351              :       INTEGER                                            :: handle, i, i_ref, i_ref_old, n_params
     352              :       TYPE(xc_f03_func_reference_t)                      :: xc_ref
     353              : 
     354          121 :       CALL timeset(routineN, handle)
     355              : 
     356              :       ! We are counting the number of necessary lines by carrying out a dry run of xc_libxc_wrap_info_refs
     357          121 :       i_ref = 0
     358          121 :       i_ref_old = -1
     359          121 :       length = 0
     360          242 :       DO WHILE (i_ref >= 0 .AND. i_ref /= i_ref_old)
     361              :          ! information about functional references
     362          121 :          xc_ref = xc_f03_func_info_get_references(xc_info, i_ref)
     363          121 :          ref_string = xc_f03_func_reference_get_ref(xc_ref)
     364          121 :          doi_string = xc_f03_func_reference_get_doi(xc_ref)
     365          121 :          length = length + LEN_TRIM(ref_string) + LEN_TRIM(doi_string) + 11
     366          121 :          IF (MOD(length, maxlen) /= 0) length = length + maxlen - MOD(length, maxlen)
     367              :          ! information about (optional) external parameters
     368          121 :          n_params = xc_f03_func_info_get_n_ext_params(xc_info)
     369          121 :          IF (n_params > 0) THEN
     370           94 :             length = length + maxlen
     371              :          END IF
     372          667 :          DO i = 1, n_params
     373          546 :             descr_string = xc_f03_func_info_get_ext_params_description(xc_info, i - 1)
     374          546 :             length = length + LEN_TRIM(descr_string) + 3
     375          667 :             IF (MOD(length, maxlen) /= 0) length = length + maxlen - MOD(length, maxlen)
     376              :          END DO
     377          121 :          i_ref_old = i_ref
     378              :       END DO
     379              :       ! two additional lines for spin polarization, scaling factor and buffer
     380          121 :       length = length + 2*maxlen
     381              : 
     382          121 :       CALL timestop(handle)
     383              : 
     384          121 :    END FUNCTION xc_libxc_get_reference_length
     385              : 
     386              : ! **************************************************************************************************
     387              : !> \brief Provides the reference(s) for this functional.
     388              : !> \param xc_info ...
     389              : !> \param polarized ...
     390              : !> \param sc ...
     391              : !> \param reference ...
     392              : !>
     393              : !> \author A. Gloess (agloess)
     394              : ! **************************************************************************************************
     395          121 :    SUBROUTINE xc_libxc_wrap_info_refs(xc_info, polarized, sc, reference)
     396              :       TYPE(xc_f03_func_info_t), INTENT(IN)               :: xc_info
     397              :       INTEGER, INTENT(IN)                                :: polarized
     398              :       REAL(KIND=dp), INTENT(IN)                          :: sc
     399              :       CHARACTER(LEN=*), INTENT(OUT)                      :: reference
     400              : 
     401              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'xc_libxc_wrap_info_refs'
     402              :       INTEGER, PARAMETER                                 :: maxlen = 67
     403              : 
     404              :       CHARACTER(LEN=1028)                                :: doi_string, ref_string
     405              :       CHARACTER(LEN=128)                                 :: descr_string
     406              :       CHARACTER(LEN=2067)                                :: tmp_string
     407              :       INTEGER                                            :: empty, first, handle, i, i_ref, &
     408              :                                                             i_ref_old, idx, last, n_params
     409              :       TYPE(xc_f03_func_reference_t)                      :: xc_ref
     410              : 
     411              : ! conservative estimate of the necessary length: 2*1028+11=2067
     412              : 
     413          121 :       CALL timeset(routineN, handle)
     414              : 
     415          121 :       i_ref = 0
     416          121 :       i_ref_old = -1
     417          121 :       idx = 1
     418          121 :       first = 1
     419          242 :       DO WHILE (i_ref >= 0 .AND. i_ref /= i_ref_old)
     420              :          ! information about functional references
     421          121 :          xc_ref = xc_f03_func_info_get_references(xc_info, i_ref)
     422          121 :          ref_string = xc_f03_func_reference_get_ref(xc_ref)
     423          121 :          doi_string = xc_f03_func_reference_get_doi(xc_ref)
     424          121 :          WRITE (tmp_string, '(a1,i1,a2,a,a7,a)') '[', idx, '] ', &
     425          242 :             TRIM(ref_string), ', doi: ', TRIM(doi_string)
     426          121 :          last = first + LEN_TRIM(tmp_string) - 1
     427          121 :          reference(first:last) = TRIM(tmp_string)
     428          121 :          first = last + 1
     429          121 :          empty = last + (maxlen - 1) - MOD(last - 1, maxlen)
     430              :          ! fill up line with 'spaces'
     431          121 :          IF (empty /= last) THEN
     432          121 :             reference(first:empty) = ' '
     433          121 :             first = empty + 1
     434              :          END IF
     435              :          ! information about (optional) external parameters
     436          121 :          n_params = xc_f03_func_info_get_n_ext_params(xc_info)
     437          121 :          IF (n_params > 0) THEN
     438           94 :             reference(first:first + maxlen - 1) = 'Optional external parameters:'//REPEAT(' ', maxlen - 28)
     439           94 :             first = first + maxlen
     440              :          END IF
     441          667 :          DO i = 1, n_params
     442          546 :             descr_string = xc_f03_func_info_get_ext_params_description(xc_info, i - 1)
     443          546 :             last = first + LEN_TRIM(descr_string) - 1 + 3
     444          546 :             reference(first:last) = ' * '//TRIM(descr_string)
     445          546 :             first = last + 1
     446          546 :             empty = last + (maxlen - 1) - MOD(last - 1, maxlen)
     447              :             ! fill up line with 'spaces'
     448              : 
     449          667 :             IF (empty /= last) THEN
     450          546 :                reference(first:empty) = ' '
     451          546 :                first = empty + 1
     452              :             END IF
     453              :          END DO
     454          121 :          idx = idx + 1
     455          121 :          i_ref_old = i_ref
     456              :       END DO
     457          185 :       SELECT CASE (polarized)
     458              :       CASE (XC_UNPOLARIZED)
     459           64 :          WRITE (tmp_string, "('{scale=',f5.3,', spin-unpolarized}')") sc
     460              :       CASE (XC_POLARIZED)
     461           57 :          WRITE (tmp_string, "('{scale=',f5.3,', spin-polarized}')") sc
     462              :       CASE default
     463          121 :          CPABORT("Unsupported value for variable 'polarized'.")
     464              :       END SELECT
     465          121 :       last = first + LEN_TRIM(tmp_string) - 1
     466          121 :       reference(first:last) = TRIM(tmp_string)
     467          121 :       first = last + 1
     468              :       ! fill with 'spaces'
     469          121 :       reference(first:LEN(reference)) = ' '
     470              : 
     471          121 :       IF (last > LEN(reference)) &
     472            0 :          CPABORT("Faulty reference length.")
     473              : 
     474          121 :       CALL timestop(handle)
     475              : 
     476          121 :    END SUBROUTINE xc_libxc_wrap_info_refs
     477              : 
     478              : ! **************************************************************************************************
     479              : !> \brief Provides the version of the LibXC library CP2K is running against.
     480              : !> \param version version string reported by the library at run time
     481              : !> \param compiled_version version of the headers CP2K was compiled against
     482              : !> \author A. Gloess (agloess)
     483              : !> \note The run-time and compile-time versions differ whenever CP2K is executed
     484              : !>       against a shared LibXC other than the one it was built with. Reporting
     485              : !>       the run-time version is what actually describes the numbers produced.
     486              : !>
     487              : ! **************************************************************************************************
     488           76 :    SUBROUTINE xc_libxc_wrap_version(version, compiled_version)
     489              :       CHARACTER(LEN=*), INTENT(OUT)                      :: version
     490              :       CHARACTER(LEN=*), INTENT(OUT), OPTIONAL            :: compiled_version
     491              : 
     492              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'xc_libxc_wrap_version'
     493              : 
     494              :       INTEGER                                            :: handle
     495              : 
     496           76 :       CALL timeset(routineN, handle)
     497              : 
     498           76 :       CALL xc_f03_version_string(version)
     499           76 :       IF (PRESENT(compiled_version)) compiled_version = TRIM(libxc_version)
     500              : 
     501           76 :       CALL timestop(handle)
     502              : 
     503           76 :    END SUBROUTINE xc_libxc_wrap_version
     504              : 
     505              : ! **************************************************************************************************
     506              : !> \brief Provides the citation LibXC asks to be given for the library itself.
     507              : !> \param reference bibliographic reference
     508              : !> \param doi digital object identifier of that reference
     509              : !> \author S. Lehtola
     510              : !> \note Taken from the library at run time rather than hard-coded, so that the
     511              : !>       citation stays correct when LibXC updates its own self-citation.
     512              : !>
     513              : ! **************************************************************************************************
     514           76 :    SUBROUTINE xc_libxc_wrap_library_reference(reference, doi)
     515              :       CHARACTER(LEN=*), INTENT(OUT)                      :: reference, doi
     516              : 
     517              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'xc_libxc_wrap_library_reference'
     518              : 
     519              :       INTEGER                                            :: handle
     520              : 
     521           76 :       CALL timeset(routineN, handle)
     522              : 
     523           76 :       CALL xc_f03_reference(reference)
     524           76 :       CALL xc_f03_reference_doi(doi)
     525              : 
     526           76 :       CALL timestop(handle)
     527              : 
     528           76 :    END SUBROUTINE xc_libxc_wrap_library_reference
     529              : 
     530              : ! **************************************************************************************************
     531              : !> \brief Applies the CP2K screening cutoffs to a LibXC functional object.
     532              : !> \param xc_func LibXC functional object
     533              : !> \param xc_info info object belonging to xc_func
     534              : !> \param epsilon_rho density cutoff (XC%DENSITY_CUTOFF)
     535              : !> \param epsilon_tau kinetic energy density cutoff (XC%TAU_CUTOFF)
     536              : !> \author S. Lehtola
     537              : !> \note LibXC screens every point against the density threshold internally, which
     538              : !>       is what allows CP2K to hand it whole blocks of points instead of filtering
     539              : !>       point by point. The sigma threshold is deliberately left at LibXC's own
     540              : !>       default: CP2K has no cutoff of its own on the gradient here, and raising
     541              : !>       it in step with the density cutoff would floor sigma for points with a
     542              : !>       small gradient that used to be evaluated as given.
     543              : !>
     544              : ! **************************************************************************************************
     545          580 :    SUBROUTINE xc_libxc_wrap_set_thresholds(xc_func, xc_info, epsilon_rho, epsilon_tau)
     546              :       TYPE(xc_f03_func_t), INTENT(INOUT)                 :: xc_func
     547              :       TYPE(xc_f03_func_info_t), INTENT(IN)               :: xc_info
     548              :       REAL(KIND=dp), INTENT(IN)                          :: epsilon_rho, epsilon_tau
     549              : 
     550              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'xc_libxc_wrap_set_thresholds'
     551              : 
     552              :       INTEGER                                            :: handle
     553              : 
     554          580 :       CALL timeset(routineN, handle)
     555              : 
     556          580 :       CALL xc_f03_func_set_dens_threshold(xc_func, epsilon_rho)
     557              : 
     558          178 :       SELECT CASE (xc_f03_func_info_get_family(xc_info))
     559              :       CASE (XC_FAMILY_MGGA, XC_FAMILY_HYB_MGGA)
     560          580 :          CALL xc_f03_func_set_tau_threshold(xc_func, epsilon_tau)
     561              :       END SELECT
     562              : 
     563          580 :       CALL timestop(handle)
     564              : 
     565          580 :    END SUBROUTINE xc_libxc_wrap_set_thresholds
     566              : 
     567              : ! **************************************************************************************************
     568              : !> \brief Checks existence of functional in LibXC
     569              : !> \param func_string ...
     570              : !> \return ...
     571              : !> \author F. Stein
     572              : !> \note Remove prefix to keep compatibility, functionals can be specified (in
     573              : !>       LIBXC section) as:
     574              : !>       GGA_X_...  or  XC_GGA_X_...
     575              : !>       Starting from version 2.2.0 both name conventions are allowed, before
     576              : !>       the 'XC_' prefix was necessary.
     577              : !>
     578              : ! **************************************************************************************************
     579         4276 :    LOGICAL FUNCTION xc_libxc_check_functional(func_string) RESULT(exists)
     580              :       CHARACTER(LEN=*), INTENT(IN)                       :: func_string
     581              : 
     582              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'xc_libxc_check_functional'
     583              : 
     584              :       INTEGER                                            :: func_id, handle
     585              : 
     586         4276 :       CALL timeset(routineN, handle)
     587              : 
     588         4276 :       IF (func_string(1:3) == "XC_") THEN
     589            0 :          func_id = xc_f03_functional_get_number(func_string(4:LEN_TRIM(func_string)))
     590              :       ELSE
     591         4276 :          func_id = xc_f03_functional_get_number(func_string(1:LEN_TRIM(func_string)))
     592              :       END IF
     593              : 
     594         4276 :       exists = .TRUE.
     595         4276 :       IF (func_id == -1) exists = .FALSE.
     596              : 
     597         4276 :       CALL timestop(handle)
     598              : 
     599         4276 :    END FUNCTION xc_libxc_check_functional
     600              : 
     601              : ! **************************************************************************************************
     602              : !> \brief Provides the functional ID.
     603              : !> \param func_string ...
     604              : !> \return ...
     605              : !> \author A. Gloess (agloess)
     606              : !> \note Remove prefix to keep compatibility, functionals can be specified (in
     607              : !>       LIBXC section) as:
     608              : !>       GGA_X_...  or  XC_GGA_X_...
     609              : !>       Starting from version 2.2.0 both name conventions are allowed, before
     610              : !>       the 'XC_' prefix was necessary.
     611              : !>
     612              : ! **************************************************************************************************
     613        47226 :    INTEGER FUNCTION xc_libxc_wrap_functional_get_number(func_string) RESULT(func_id)
     614              :       CHARACTER(LEN=*), INTENT(IN)                       :: func_string
     615              : 
     616              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'xc_libxc_wrap_functional_get_number'
     617              : 
     618              :       INTEGER                                            :: handle
     619              : 
     620        47226 :       CALL timeset(routineN, handle)
     621              : 
     622        47226 :       IF (func_string(1:3) == "XC_") THEN
     623            0 :          func_id = xc_f03_functional_get_number(func_string(4:LEN_TRIM(func_string)))
     624              :       ELSE
     625        47226 :          func_id = xc_f03_functional_get_number(func_string(1:LEN_TRIM(func_string)))
     626              :       END IF
     627        47226 :       IF (func_id == -1) THEN
     628            0 :          CPABORT(TRIM(func_string)//": wrong functional name")
     629              :       END IF
     630              : 
     631        47226 :       CALL timestop(handle)
     632              : 
     633        47226 :    END FUNCTION xc_libxc_wrap_functional_get_number
     634              : 
     635              : ! **************************************************************************************************
     636              : !> \brief Wrapper to test wether functional is considered under development in Libxc
     637              : !> \param xc_info ...
     638              : !>
     639              : !> \return ...
     640              : !> \author F. Stein (fstein93)
     641              : ! **************************************************************************************************
     642            0 :    LOGICAL FUNCTION xc_libxc_wrap_is_under_development(xc_info)
     643              :       TYPE(xc_f03_func_info_t)                           :: xc_info
     644              : 
     645            0 :       IF (IAND(xc_f03_func_info_get_flags(xc_info), XC_FLAGS_DEVELOPMENT) == XC_FLAGS_DEVELOPMENT) THEN
     646              :          xc_libxc_wrap_is_under_development = .TRUE.
     647              :       ELSE
     648            0 :          xc_libxc_wrap_is_under_development = .FALSE.
     649              :       END IF
     650              : 
     651            0 :    END FUNCTION xc_libxc_wrap_is_under_development
     652              : 
     653              : ! **************************************************************************************************
     654              : !> \brief Wrapper for functionals that need the Laplacian, all others can use
     655              : !>        a dummy array.
     656              : !> \param xc_info info object of an already initialized functional
     657              : !>
     658              : !> \return ...
     659              : !> \author A. Gloess (agloess)
     660              : !> \note Reads the flag off an info object the caller already holds. Creating a
     661              : !>       throw-away functional object just to look at one flag used to cost an
     662              : !>       extra xc_f03_func_init/xc_f03_func_end pair per evaluated batch.
     663              : ! **************************************************************************************************
     664         6026 :    LOGICAL FUNCTION xc_libxc_wrap_info_needs_laplace(xc_info)
     665              :       ! Only some MGGA functionals needs the laplacian
     666              :       TYPE(xc_f03_func_info_t), INTENT(IN)               :: xc_info
     667              : 
     668         6026 :       IF (IAND(xc_f03_func_info_get_flags(xc_info), XC_FLAGS_NEEDS_LAPLACIAN) == XC_FLAGS_NEEDS_LAPLACIAN) THEN
     669              :          xc_libxc_wrap_info_needs_laplace = .TRUE.
     670              :       ELSE
     671         4728 :          xc_libxc_wrap_info_needs_laplace = .FALSE.
     672              :       END IF
     673              : 
     674         6026 :    END FUNCTION xc_libxc_wrap_info_needs_laplace
     675              : 
     676              : ! **************************************************************************************************
     677              : !> \brief Whether the functional does not provide the energy density.
     678              : !> \param xc_info info object of an already initialized functional
     679              : !>
     680              : !> \return .TRUE. when LibXC cannot supply Exc for this functional
     681              : !> \author S. Lehtola
     682              : ! **************************************************************************************************
     683          580 :    LOGICAL FUNCTION xc_libxc_wrap_info_no_exc(xc_info)
     684              :       TYPE(xc_f03_func_info_t), INTENT(IN)               :: xc_info
     685              : 
     686          580 :       IF (IAND(xc_f03_func_info_get_flags(xc_info), XC_FLAGS_HAVE_EXC) == XC_FLAGS_HAVE_EXC) THEN
     687              :          xc_libxc_wrap_info_no_exc = .FALSE.
     688              :       ELSE
     689            0 :          xc_libxc_wrap_info_no_exc = .TRUE.
     690              :       END IF
     691              : 
     692          580 :    END FUNCTION xc_libxc_wrap_info_no_exc
     693              : 
     694              : ! **************************************************************************************************
     695              : !> \brief Initialize a LibXC functional honoring the runtime backend.
     696              : !> \param func the functional object to initialize
     697              : !> \param functional LibXC functional number
     698              : !> \param nspin XC_UNPOLARIZED or XC_POLARIZED (defaults to XC_UNPOLARIZED)
     699              : !> \param force_host initialize on the host even when the runtime backend is the
     700              : !>        device (used for query/metadata functional objects)
     701              : !> \note The functional's default flags are set to XC_FLAGS_ON_DEVICE when the
     702              : !>       device backend is active (and the initialization is not forced to the
     703              : !>       host), so that later evaluation calls run on the device.
     704              : ! **************************************************************************************************
     705     10363188 :    SUBROUTINE libxc_func_init_wrapper(func, functional, nspin, force_host)
     706              :       TYPE(xc_f03_func_t), INTENT(OUT)                   :: func
     707              :       INTEGER, INTENT(IN)                                :: functional
     708              :       INTEGER, INTENT(IN), OPTIONAL                      :: nspin
     709              :       LOGICAL, INTENT(IN), OPTIONAL                      :: force_host
     710              : 
     711              :       LOGICAL                                            :: my_force_host
     712              : 
     713     10363188 :       my_force_host = .FALSE.
     714     10363188 :       IF (PRESENT(force_host)) my_force_host = force_host
     715              : 
     716              :       ! Query/metadata initialization always runs on the host (force_host).
     717     10363188 :       IF (libxc_backend == do_libxc_gpu .AND. .NOT. my_force_host) THEN
     718            0 :          CALL xc_f03_func_info_set_default_flags(XC_FLAGS_ON_DEVICE)
     719            0 :          IF (PRESENT(nspin)) THEN
     720            0 :             CALL xc_f03_func_init(func, functional, nspin)
     721              :          ELSE
     722            0 :             CALL xc_f03_func_init(func, functional, XC_UNPOLARIZED)
     723              :          END IF
     724              :       ELSE
     725     10363188 :          CALL xc_f03_func_info_set_default_flags(XC_FLAGS_ON_HOST)
     726     10363188 :          IF (PRESENT(nspin)) THEN
     727     10363188 :             CALL xc_f03_func_init(func, functional, nspin)
     728              :          ELSE
     729            0 :             CALL xc_f03_func_init(func, functional, XC_UNPOLARIZED)
     730              :          END IF
     731              :       END IF
     732     10363188 :    END SUBROUTINE libxc_func_init_wrapper
     733              : 
     734              : #endif
     735              : 
     736              : ! **************************************************************************************************
     737              : !> \brief Whether the runtime LibXC backend is the GPU.
     738              : !> \return ...
     739              : !> \note Always available under __LIBXC: CPU-only/__NO_OFFLOAD_LIBXC builds
     740              : !>       compile the flag but can never select the device backend at runtime.
     741              : ! **************************************************************************************************
     742      2742512 :    FUNCTION libxc_is_gpu() RESULT(is_gpu)
     743              :       LOGICAL                                            :: is_gpu
     744              : 
     745      2742512 :       is_gpu = (libxc_backend == do_libxc_gpu)
     746      2742512 :    END FUNCTION libxc_is_gpu
     747              : 
     748              : ! **************************************************************************************************
     749              : !> \brief Allocates the staging buffers of a single worker, sizing the block so
     750              : !>        that they stay within the cache budget.
     751              : !> \param worker the worker
     752              : !> \param family LibXC functional family
     753              : !> \param nspin XC_UNPOLARIZED or XC_POLARIZED
     754              : !> \param grad_deriv highest derivative order the buffers must hold
     755              : !> \author S. Lehtola
     756              : ! **************************************************************************************************
     757          740 :    SUBROUTINE libxc_worker_alloc(worker, family, nspin, grad_deriv)
     758              :       TYPE(libxc_worker_type), INTENT(INOUT)             :: worker
     759              :       INTEGER, INTENT(IN)                                :: family, nspin, grad_deriv
     760              : 
     761              :       INTEGER, PARAMETER                                 :: libxc_block_bytes = 256*1024
     762              :       INTEGER, PARAMETER                                 :: libxc_block_min = 64
     763              :       INTEGER, PARAMETER                                 :: libxc_block_max = 512
     764              : 
     765              :       INTEGER                                            :: nb, ncomp
     766              : 
     767              :       ! How many doubles a point occupies spans a factor of twenty over the
     768              :       ! families, spin cases and derivative orders, so a block length fixed in
     769              :       ! points would size the buffers anywhere between 49 KiB and 950 KiB. Derive
     770              :       ! it from the footprint instead: build a one-point worker, ask it how wide
     771              :       ! a point is, and cut the real block to the byte budget. Taking the count
     772              :       ! from the buffers themselves is what stops it drifting away from the
     773              :       ! allocation it is meant to describe.
     774        31080 :       BLOCK
     775          740 :          TYPE(libxc_worker_type)                         :: probe
     776              :          ! The probe only counts host components, so skip the device buffers:
     777              :          ! they would otherwise be allocated and leaked for a worker that is
     778              :          ! discarded immediately.
     779              :          CALL libxc_worker_alloc_buffers(probe, family, nspin, grad_deriv, 1, &
     780          740 :                                          alloc_device=.FALSE.)
     781          740 :          ncomp = libxc_worker_ncomp(probe)
     782        31080 :          CALL libxc_worker_free_buffers(probe)
     783              :       END BLOCK
     784              :       nb = MIN(libxc_block_max, &
     785          740 :                MAX(libxc_block_min, libxc_block_bytes/(ncomp*(STORAGE_SIZE(0.0_dp)/8))))
     786              : 
     787          740 :       CALL libxc_worker_alloc_buffers(worker, family, nspin, grad_deriv, nb)
     788              : 
     789          740 :    END SUBROUTINE libxc_worker_alloc
     790              : 
     791              : ! **************************************************************************************************
     792              : !> \brief Number of buffer components a single grid point occupies in a worker.
     793              : !> \param worker the worker
     794              : !> \return components per point, summed over the buffers it actually carries
     795              : !> \author S. Lehtola
     796              : ! **************************************************************************************************
     797          740 :    FUNCTION libxc_worker_ncomp(worker) RESULT(ncomp)
     798              :       TYPE(libxc_worker_type), INTENT(IN)                :: worker
     799              :       INTEGER                                            :: ncomp
     800              : 
     801          740 :       ncomp = 0
     802              :       #:for arr in worker_1d
     803          740 :          IF (ALLOCATED(worker%${arr}$)) ncomp = ncomp + 1
     804              :       #:endfor
     805              :       #:for arr in worker_2d
     806          740 :          IF (ALLOCATED(worker%${arr}$)) ncomp = ncomp + SIZE(worker%${arr}$, 1)
     807              :       #:endfor
     808              : 
     809          740 :    END FUNCTION libxc_worker_ncomp
     810              : 
     811              : ! **************************************************************************************************
     812              : !> \brief Allocates the staging buffers of a single worker for a given block length.
     813              : !> \param worker the worker
     814              : !> \param family LibXC functional family
     815              : !> \param nspin XC_UNPOLARIZED or XC_POLARIZED
     816              : !> \param grad_deriv highest derivative order the buffers must hold
     817              : !> \param nb number of grid points per block
     818              : !> \param alloc_device whether to allocate the matching GPU device buffers
     819              : !> \author S. Lehtola
     820              : !> \note The buffers follow LibXC's own layout, i.e. the leading dimension is the
     821              : !>       number of components of the quantity and the points run along the second
     822              : !>       dimension. They are allocated once per worker and reused for every batch.
     823              : !>       Only the orders this evaluation asks for are allocated: the third
     824              : !>       derivatives alone are 130 components per point for a spin-polarized
     825              : !>       meta-GGA, which a ground-state calculation would never fill.
     826              : ! **************************************************************************************************
     827         1480 :    SUBROUTINE libxc_worker_alloc_buffers(worker, family, nspin, grad_deriv, nb, alloc_device)
     828              :       TYPE(libxc_worker_type), INTENT(INOUT)             :: worker
     829              :       INTEGER, INTENT(IN)                                :: family, nspin, grad_deriv, nb
     830              :       LOGICAL, INTENT(IN), OPTIONAL                      :: alloc_device
     831              : 
     832              :       INTEGER                                            :: nl, np, ns
     833              :       LOGICAL                                            :: pol, want_device
     834              : 
     835         1480 :       pol = (nspin == XC_POLARIZED)
     836         1480 :       want_device = .TRUE.
     837         1480 :       IF (PRESENT(alloc_device)) want_device = alloc_device
     838         1480 :       CALL libxc_worker_dims(nspin, np, ns, nl)
     839              : 
     840         1480 :       worker%nb = nb
     841              : 
     842              :       ! The energy density and the first derivatives are always staged: LibXC
     843              :       ! writes them whatever higher order was asked for.
     844         5920 :       ALLOCATE (worker%rho(np, nb))
     845         4440 :       ALLOCATE (worker%exc(nb))
     846         4440 :       ALLOCATE (worker%vrho(np, nb))
     847         3088 :       IF (grad_deriv >= 2) ALLOCATE (worker%v2rho2(ns, nb))
     848         1720 :       IF (grad_deriv >= 3) ALLOCATE (worker%v3rho3(nl, nb))
     849              : 
     850         2560 :       SELECT CASE (family)
     851              :       CASE (XC_FAMILY_GGA, XC_FAMILY_HYB_GGA, XC_FAMILY_MGGA, XC_FAMILY_HYB_MGGA)
     852         4320 :          ALLOCATE (worker%sigma(ns, nb))
     853         3240 :          ALLOCATE (worker%vsigma(ns, nb))
     854         1080 :          IF (pol) THEN
     855         1232 :             ALLOCATE (worker%nd(nb), worker%nda(nb), worker%ndb(nb))
     856              :          END IF
     857         1080 :          IF (grad_deriv >= 2) THEN
     858         1784 :             ALLOCATE (worker%v2rhosigma(MERGE(6, 1, pol), nb))
     859         1176 :             ALLOCATE (worker%v2sigma2(MERGE(6, 1, pol), nb))
     860              :          END IF
     861         2560 :          IF (grad_deriv >= 3) THEN
     862          268 :             ALLOCATE (worker%v3rho2sigma(MERGE(9, 1, pol), nb))
     863          268 :             ALLOCATE (worker%v3rhosigma2(MERGE(12, 1, pol), nb))
     864          268 :             ALLOCATE (worker%v3sigma3(MERGE(10, 1, pol), nb))
     865              :          END IF
     866              :       END SELECT
     867              : 
     868          528 :       SELECT CASE (family)
     869              :       CASE (XC_FAMILY_MGGA, XC_FAMILY_HYB_MGGA)
     870         1584 :          ALLOCATE (worker%lapl(np, nb))
     871         1584 :          ALLOCATE (worker%tau(np, nb))
     872         1584 :          ALLOCATE (worker%vlapl(np, nb))
     873         1584 :          ALLOCATE (worker%vtau(np, nb))
     874          528 :          IF (grad_deriv >= 2) THEN
     875          880 :             ALLOCATE (worker%v2rholapl(nl, nb))
     876          660 :             ALLOCATE (worker%v2rhotau(nl, nb))
     877         1016 :             ALLOCATE (worker%v2sigmalapl(MERGE(6, 1, pol), nb))
     878          660 :             ALLOCATE (worker%v2sigmatau(MERGE(6, 1, pol), nb))
     879          880 :             ALLOCATE (worker%v2lapl2(ns, nb))
     880          660 :             ALLOCATE (worker%v2lapltau(nl, nb))
     881          660 :             ALLOCATE (worker%v2tau2(ns, nb))
     882              :          END IF
     883          528 :          IF (grad_deriv >= 3) THEN
     884              :             #:for arr in v3_new
     885         1580 :                ALLOCATE (worker%${arr}$ (MERGE(${mgga_ncomp[arr]}$, 1, pol), nb))
     886              :             #:endfor
     887              :          END IF
     888              :          ! LibXC leaves vlapl untouched for functionals that do not use the
     889              :          ! Laplacian, and CP2K then ignores it; zero it once so it never holds
     890              :          ! uninitialized memory.
     891       308782 :          worker%vlapl = 0.0_dp
     892              :       END SELECT
     893              : 
     894              :       ! Allocate GPU device buffers when the GPU backend is active. They follow
     895              :       ! the host staging buffers, so the same derivative-order guards apply.
     896         1480 :       IF (want_device .AND. libxc_is_gpu()) THEN
     897              :          CALL libxc_worker_device_alloc(worker, family, pol, nl, np, ns, nb)
     898              :       END IF
     899              : 
     900         1480 :    END SUBROUTINE libxc_worker_alloc_buffers
     901              : 
     902              : ! **************************************************************************************************
     903              : !> \brief Releases the staging buffers of a worker, keeping its functional object.
     904              : !> \param worker the worker
     905              : !> \author S. Lehtola
     906              : !> \note Frees the host buffers and the matching device buffers, but leaves the
     907              : !>       LibXC functional object untouched so that it can be reused.
     908              : ! **************************************************************************************************
     909         1480 :    SUBROUTINE libxc_worker_free_buffers(worker)
     910              :       TYPE(libxc_worker_type), INTENT(INOUT)             :: worker
     911              : 
     912              :       #:for arr in worker_1d + worker_2d
     913         1480 :          IF (ALLOCATED(worker%${arr}$)) DEALLOCATE (worker%${arr}$)
     914              :       #:endfor
     915         1480 :       worker%nb = 0
     916              : 
     917              :       ! Freeing a buffer that was never allocated is a no-op, so this is done
     918              :       ! unconditionally rather than gating on the currently active backend.
     919              :       CALL libxc_worker_device_free(worker)
     920              : 
     921         1480 :    END SUBROUTINE libxc_worker_free_buffers
     922              : 
     923              : ! **************************************************************************************************
     924              : !> \brief Activates the rank's chosen device on the calling thread.
     925              : !> \note Needed because CUDA's current device is thread-local; a no-op without
     926              : !>       a device, so xc_libxc can call it unconditionally.
     927              : ! **************************************************************************************************
     928            0 :    SUBROUTINE libxc_activate_device()
     929              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_LIBXC)
     930              :       USE offload_api, ONLY: offload_activate_chosen_device
     931              : 
     932              :       CALL offload_activate_chosen_device()
     933              : #endif
     934            0 :    END SUBROUTINE libxc_activate_device
     935              : 
     936              : ! **************************************************************************************************
     937              : !> \brief Waits for all outstanding device-to-host copies to complete.
     938              : ! **************************************************************************************************
     939            0 :    SUBROUTINE libxc_sync_device()
     940              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_LIBXC)
     941              :       USE offload_api, ONLY: offload_device_synchronize
     942              : 
     943              :       CALL offload_device_synchronize()
     944              : #endif
     945            0 :    END SUBROUTINE libxc_sync_device
     946              : 
     947              : ! **************************************************************************************************
     948              : !> \brief Copies host staging data into a worker's device buffer.
     949              : !> \param worker the worker
     950              : !> \param slot device buffer to copy into (one of libxc_dev_*)
     951              : !> \param host host array to copy from
     952              : !> \param n number of elements
     953              : ! **************************************************************************************************
     954            0 :    SUBROUTINE libxc_worker_h2d(worker, slot, host, n)
     955              :       TYPE(libxc_worker_type), INTENT(INOUT)             :: worker
     956              :       INTEGER, INTENT(IN)                                :: slot
     957              :       REAL(KIND=dp), DIMENSION(*), INTENT(IN)            :: host
     958              :       INTEGER, INTENT(IN)                                :: n
     959              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_LIBXC)
     960              :       CALL libxc_host_to_device(worker%dev(slot), host, n)
     961              : #else
     962              :       MARK_USED(worker)
     963              :       MARK_USED(slot)
     964              :       IF (.FALSE.) THEN; DO; IF (ABS(host(1)) > ABS(host(1))) EXIT; END DO; END IF
     965              :       MARK_USED(n)
     966            0 :       CPABORT("libxc_worker_h2d: device backend not compiled in.")
     967              : #endif
     968            0 :    END SUBROUTINE libxc_worker_h2d
     969              : 
     970              : ! **************************************************************************************************
     971              : !> \brief Issues an async device-to-host copy of one of a worker's buffers.
     972              : ! **************************************************************************************************
     973            0 :    SUBROUTINE libxc_worker_d2h_issue(worker, slot, n)
     974              :       TYPE(libxc_worker_type), INTENT(INOUT)             :: worker
     975              :       INTEGER, INTENT(IN)                                :: slot
     976              :       INTEGER, INTENT(IN)                                :: n
     977              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_LIBXC)
     978              :       CALL libxc_d2h_issue(worker%dev(slot), n)
     979              : #else
     980              :       MARK_USED(worker)
     981              :       MARK_USED(slot)
     982              :       MARK_USED(n)
     983            0 :       CPABORT("libxc_worker_d2h_issue: device backend not compiled in.")
     984              : #endif
     985            0 :    END SUBROUTINE libxc_worker_d2h_issue
     986              : 
     987              : ! **************************************************************************************************
     988              : !> \brief Reads one of a worker's device buffers back into host memory.
     989              : ! **************************************************************************************************
     990            0 :    SUBROUTINE libxc_worker_d2h_read(worker, slot, host, n)
     991              :       TYPE(libxc_worker_type), INTENT(IN)                :: worker
     992              :       INTEGER, INTENT(IN)                                :: slot
     993              :       REAL(KIND=dp), DIMENSION(*), INTENT(OUT)           :: host
     994              :       INTEGER, INTENT(IN)                                :: n
     995              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_LIBXC)
     996              :       CALL libxc_d2h_read(host, worker%dev(slot), n)
     997              : #else
     998              :       MARK_USED(worker)
     999              :       MARK_USED(slot)
    1000              :       IF (.FALSE.) THEN; DO; IF (ABS(host(1)) > ABS(host(1))) EXIT; END DO; END IF
    1001              :       MARK_USED(n)
    1002            0 :       CPABORT("libxc_worker_d2h_read: device backend not compiled in.")
    1003              : #endif
    1004            0 :    END SUBROUTINE libxc_worker_d2h_read
    1005              : 
    1006              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_LIBXC)
    1007              : ! **************************************************************************************************
    1008              : !> \brief Allocates (or, with grow_only, grows) one device buffer.
    1009              : !> \param buffer the device buffer
    1010              : !> \param n required element count
    1011              : !> \param grow_only when true, leave the buffer alone if it is already large enough
    1012              : ! **************************************************************************************************
    1013              :    SUBROUTINE libxc_dev_alloc_maybe(buffer, n, grow_only)
    1014              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: buffer
    1015              :       INTEGER, INTENT(IN)                                :: n
    1016              :       LOGICAL, INTENT(IN)                                :: grow_only
    1017              : 
    1018              :       IF (grow_only .AND. INT(buffer%size) >= n) RETURN
    1019              :       CALL libxc_device_buffer_alloc(buffer, n)
    1020              :    END SUBROUTINE libxc_dev_alloc_maybe
    1021              : 
    1022              : ! **************************************************************************************************
    1023              : !> \brief Allocates the device buffers of a worker, sizing them for n points.
    1024              : !> \param worker the worker
    1025              : !> \param family LibXC functional family
    1026              : !> \param pol whether the functional is spin-polarized
    1027              : !> \param nl, np, ns leading dimensions from libxc_worker_dims
    1028              : !> \param n number of grid points the buffers must hold
    1029              : !> \param grow_only when true, only grow buffers that are too small (used on the
    1030              : !>        GPU path, where the buffers are regrown to the whole grid)
    1031              : !> \note Only the buffers whose host counterpart is allocated are touched, so the
    1032              : !>       derivative-order and family guards of libxc_worker_alloc_buffers hold.
    1033              : ! **************************************************************************************************
    1034              :    SUBROUTINE libxc_worker_device_alloc(worker, family, pol, nl, np, ns, n, grow_only)
    1035              :       TYPE(libxc_worker_type), INTENT(INOUT)             :: worker
    1036              :       INTEGER, INTENT(IN)                                :: family, nl, np, ns, n
    1037              :       LOGICAL, INTENT(IN)                                :: pol
    1038              :       LOGICAL, INTENT(IN), OPTIONAL                      :: grow_only
    1039              : 
    1040              :       INTEGER                                            :: base, i
    1041              :       LOGICAL                                            :: g
    1042              : 
    1043              :       g = .FALSE.
    1044              :       IF (PRESENT(grow_only)) g = grow_only
    1045              : 
    1046              :       CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_rho), np*n, g)
    1047              :       CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_exc), n, g)
    1048              :       CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_vrho), np*n, g)
    1049              :       IF (ALLOCATED(worker%v2rho2)) CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_v2rho2), ns*n, g)
    1050              :       IF (ALLOCATED(worker%v3rho3)) CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_v3rho3), nl*n, g)
    1051              : 
    1052              :       SELECT CASE (family)
    1053              :       CASE (XC_FAMILY_GGA, XC_FAMILY_HYB_GGA, XC_FAMILY_MGGA, XC_FAMILY_HYB_MGGA)
    1054              :          CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_sigma), ns*n, g)
    1055              :          CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_vsigma), ns*n, g)
    1056              :          IF (ALLOCATED(worker%v2rhosigma)) &
    1057              :             CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_v2rhosigma), MERGE(6, 1, pol)*n, g)
    1058              :          IF (ALLOCATED(worker%v2sigma2)) &
    1059              :             CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_v2sigma2), MERGE(6, 1, pol)*n, g)
    1060              :          IF (ALLOCATED(worker%v3rho2sigma)) &
    1061              :             CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_v3rho2sigma), MERGE(9, 1, pol)*n, g)
    1062              :          IF (ALLOCATED(worker%v3rhosigma2)) &
    1063              :             CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_v3rhosigma2), MERGE(12, 1, pol)*n, g)
    1064              :          IF (ALLOCATED(worker%v3sigma3)) &
    1065              :             CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_v3sigma3), MERGE(10, 1, pol)*n, g)
    1066              :       END SELECT
    1067              : 
    1068              :       SELECT CASE (family)
    1069              :       CASE (XC_FAMILY_MGGA, XC_FAMILY_HYB_MGGA)
    1070              :          CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_lapl), np*n, g)
    1071              :          CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_tau), np*n, g)
    1072              :          CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_vlapl), np*n, g)
    1073              :          CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_vtau), np*n, g)
    1074              :          IF (ALLOCATED(worker%v2rholapl)) &
    1075              :             CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_v2rholapl), nl*n, g)
    1076              :          IF (ALLOCATED(worker%v2rhotau)) &
    1077              :             CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_v2rhotau), nl*n, g)
    1078              :          IF (ALLOCATED(worker%v2sigmalapl)) &
    1079              :             CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_v2sigmalapl), MERGE(6, 1, pol)*n, g)
    1080              :          IF (ALLOCATED(worker%v2sigmatau)) &
    1081              :             CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_v2sigmatau), MERGE(6, 1, pol)*n, g)
    1082              :          IF (ALLOCATED(worker%v2lapl2)) &
    1083              :             CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_v2lapl2), ns*n, g)
    1084              :          IF (ALLOCATED(worker%v2lapltau)) &
    1085              :             CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_v2lapltau), nl*n, g)
    1086              :          IF (ALLOCATED(worker%v2tau2)) &
    1087              :             CALL libxc_dev_alloc_maybe(worker%dev(libxc_dev_v2tau2), ns*n, g)
    1088              :          base = libxc_dev_first_new3
    1089              :          #:for idx, arr in enumerate(v3_new)
    1090              :             IF (ALLOCATED(worker%${arr}$)) THEN
    1091              :                i = base + ${idx}$
    1092              :                CALL libxc_dev_alloc_maybe(worker%dev(i), MERGE(${mgga_ncomp[arr]}$, 1, pol)*n, g)
    1093              :             END IF
    1094              :          #:endfor
    1095              :       END SELECT
    1096              : 
    1097              :    END SUBROUTINE libxc_worker_device_alloc
    1098              : 
    1099              : ! **************************************************************************************************
    1100              : !> \brief Frees every device buffer of a worker.
    1101              : ! **************************************************************************************************
    1102              :    SUBROUTINE libxc_worker_device_free(worker)
    1103              :       TYPE(libxc_worker_type), INTENT(INOUT)             :: worker
    1104              : 
    1105              :       INTEGER                                            :: i
    1106              : 
    1107              :       DO i = 1, libxc_max_dev_buffers
    1108              :          CALL libxc_device_buffer_free(worker%dev(i))
    1109              :       END DO
    1110              : 
    1111              :    END SUBROUTINE libxc_worker_device_free
    1112              : 
    1113              : ! **************************************************************************************************
    1114              : !> \brief Runs the device evaluation matching the functional family and the
    1115              : !>        requested derivative order on a worker's device buffers.
    1116              : !> \param worker the worker owning the device buffers
    1117              : !> \param family LibXC functional family
    1118              : !> \param grad_deriv derivative order requested (0..3)
    1119              : !> \param no_exc functional does not provide the energy density
    1120              : !> \param np number of grid points in this block
    1121              : !> \note This is the only copy of the device dispatch; xc_libxc only has to
    1122              : !>       stage its host buffers and then read the results back.
    1123              : ! **************************************************************************************************
    1124              :    SUBROUTINE libxc_worker_eval_device(worker, family, grad_deriv, no_exc, np)
    1125              :       TYPE(libxc_worker_type), INTENT(INOUT)             :: worker
    1126              :       INTEGER, INTENT(IN)                                :: family, grad_deriv
    1127              :       LOGICAL, INTENT(IN)                                :: no_exc
    1128              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    1129              : 
    1130              :       LOGICAL                                            :: is_gga, is_mgga
    1131              : 
    1132              :       CALL libxc_family_flags(family, is_gga, is_mgga, "libxc_worker_eval_device")
    1133              : 
    1134              :       IF (is_mgga) THEN
    1135              :          SELECT CASE (grad_deriv)
    1136              :          CASE (0)
    1137              :             CALL libxc_mgga_exc_device(worker%func, worker%dev(libxc_dev_rho), worker%dev(libxc_dev_sigma), &
    1138              :                                        worker%dev(libxc_dev_lapl), worker%dev(libxc_dev_tau), &
    1139              :                                        worker%dev(libxc_dev_exc), np)
    1140              :          CASE (1)
    1141              :             IF (no_exc) THEN
    1142              :                CALL libxc_mgga_vxc_device(worker%func, worker%dev(libxc_dev_rho), worker%dev(libxc_dev_sigma), &
    1143              :                                           worker%dev(libxc_dev_lapl), worker%dev(libxc_dev_tau), &
    1144              :                                           worker%dev(libxc_dev_vrho), worker%dev(libxc_dev_vsigma), &
    1145              :                                           worker%dev(libxc_dev_vlapl), worker%dev(libxc_dev_vtau), np)
    1146              :                worker%exc = 0.0_dp
    1147              :             ELSE
    1148              :                CALL libxc_mgga_exc_vxc_device(worker%func, worker%dev(libxc_dev_rho), worker%dev(libxc_dev_sigma), &
    1149              :                                               worker%dev(libxc_dev_lapl), worker%dev(libxc_dev_tau), &
    1150              :                                               worker%dev(libxc_dev_exc), worker%dev(libxc_dev_vrho), &
    1151              :                                               worker%dev(libxc_dev_vsigma), worker%dev(libxc_dev_vlapl), &
    1152              :                                               worker%dev(libxc_dev_vtau), np)
    1153              :             END IF
    1154              :          CASE (2)
    1155              :             IF (no_exc) THEN
    1156              :                CALL libxc_mgga_vxc_fxc_device(worker%func, worker%dev(libxc_dev_rho), worker%dev(libxc_dev_sigma), &
    1157              :                                               worker%dev(libxc_dev_lapl), worker%dev(libxc_dev_tau), &
    1158              :                                               worker%dev(libxc_dev_vrho), worker%dev(libxc_dev_vsigma), &
    1159              :                                               worker%dev(libxc_dev_vlapl), worker%dev(libxc_dev_vtau), &
    1160              :                                               worker%dev(libxc_dev_v2rho2), worker%dev(libxc_dev_v2rhosigma), &
    1161              :                                               worker%dev(libxc_dev_v2rholapl), worker%dev(libxc_dev_v2rhotau), &
    1162              :                                               worker%dev(libxc_dev_v2sigma2), worker%dev(libxc_dev_v2sigmalapl), &
    1163              :                                               worker%dev(libxc_dev_v2sigmatau), worker%dev(libxc_dev_v2lapl2), &
    1164              :                                               worker%dev(libxc_dev_v2lapltau), worker%dev(libxc_dev_v2tau2), np)
    1165              :                worker%exc = 0.0_dp
    1166              :             ELSE
    1167              :                CALL libxc_mgga_exc_vxc_fxc_device(worker%func, worker%dev(libxc_dev_rho), worker%dev(libxc_dev_sigma), &
    1168              :                                                   worker%dev(libxc_dev_lapl), worker%dev(libxc_dev_tau), &
    1169              :                                                   worker%dev(libxc_dev_exc), worker%dev(libxc_dev_vrho), &
    1170              :                                                   worker%dev(libxc_dev_vsigma), worker%dev(libxc_dev_vlapl), &
    1171              :                                                   worker%dev(libxc_dev_vtau), worker%dev(libxc_dev_v2rho2), &
    1172              :                                                   worker%dev(libxc_dev_v2rhosigma), worker%dev(libxc_dev_v2rholapl), &
    1173              :                                                   worker%dev(libxc_dev_v2rhotau), worker%dev(libxc_dev_v2sigma2), &
    1174              :                                                   worker%dev(libxc_dev_v2sigmalapl), worker%dev(libxc_dev_v2sigmatau), &
    1175              :                                                   worker%dev(libxc_dev_v2lapl2), worker%dev(libxc_dev_v2lapltau), &
    1176              :                                                   worker%dev(libxc_dev_v2tau2), np)
    1177              :             END IF
    1178              :          CASE (3)
    1179              :             IF (no_exc) THEN
    1180              :                CALL libxc_mgga_vxc_fxc_kxc_device(worker%func, worker%dev(libxc_dev_rho), worker%dev(libxc_dev_sigma), &
    1181              :                                                   worker%dev(libxc_dev_lapl), worker%dev(libxc_dev_tau), &
    1182              :                                                   worker%dev(libxc_dev_vrho), worker%dev(libxc_dev_vsigma), &
    1183              :                                                   worker%dev(libxc_dev_vlapl), worker%dev(libxc_dev_vtau), &
    1184              :                                                   worker%dev(libxc_dev_v2rho2), worker%dev(libxc_dev_v2rhosigma), &
    1185              :                                                   worker%dev(libxc_dev_v2rholapl), worker%dev(libxc_dev_v2rhotau), &
    1186              :                                                   worker%dev(libxc_dev_v2sigma2), worker%dev(libxc_dev_v2sigmalapl), &
    1187              :                                                   worker%dev(libxc_dev_v2sigmatau), worker%dev(libxc_dev_v2lapl2), &
    1188              :                                                   worker%dev(libxc_dev_v2lapltau), worker%dev(libxc_dev_v2tau2), &
    1189              :                                                   worker%dev(libxc_dev_v3rho3), worker%dev(libxc_dev_v3rho2sigma), &
    1190              :                                                   worker%dev(libxc_dev_v3rho2lapl), worker%dev(libxc_dev_v3rho2tau), &
    1191              :                                                   worker%dev(libxc_dev_v3rhosigma2), worker%dev(libxc_dev_v3rhosigmalapl), &
    1192              :                                                   worker%dev(libxc_dev_v3rhosigmatau), worker%dev(libxc_dev_v3rholapl2), &
    1193              :                                                   worker%dev(libxc_dev_v3rholapltau), worker%dev(libxc_dev_v3rhotau2), &
    1194              :                                                   worker%dev(libxc_dev_v3sigma3), worker%dev(libxc_dev_v3sigma2lapl), &
    1195              :                                                   worker%dev(libxc_dev_v3sigma2tau), worker%dev(libxc_dev_v3sigmalapl2), &
    1196              :                                                   worker%dev(libxc_dev_v3sigmalapltau), worker%dev(libxc_dev_v3sigmatau2), &
    1197              :                                                   worker%dev(libxc_dev_v3lapl3), worker%dev(libxc_dev_v3lapl2tau), &
    1198              :                                                   worker%dev(libxc_dev_v3lapltau2), worker%dev(libxc_dev_v3tau3), np)
    1199              :                worker%exc = 0.0_dp
    1200              :             ELSE
    1201              :                CALL libxc_mgga_exc_vxc_fxc_kxc_device(worker%func, worker%dev(libxc_dev_rho), &
    1202              :                                                       worker%dev(libxc_dev_sigma), worker%dev(libxc_dev_lapl), &
    1203              :                                                       worker%dev(libxc_dev_tau), worker%dev(libxc_dev_exc), &
    1204              :                                                       worker%dev(libxc_dev_vrho), worker%dev(libxc_dev_vsigma), &
    1205              :                                                       worker%dev(libxc_dev_vlapl), worker%dev(libxc_dev_vtau), &
    1206              :                                                       worker%dev(libxc_dev_v2rho2), worker%dev(libxc_dev_v2rhosigma), &
    1207              :                                                       worker%dev(libxc_dev_v2rholapl), worker%dev(libxc_dev_v2rhotau), &
    1208              :                                                       worker%dev(libxc_dev_v2sigma2), worker%dev(libxc_dev_v2sigmalapl), &
    1209              :                                                       worker%dev(libxc_dev_v2sigmatau), worker%dev(libxc_dev_v2lapl2), &
    1210              :                                                       worker%dev(libxc_dev_v2lapltau), worker%dev(libxc_dev_v2tau2), &
    1211              :                                                       worker%dev(libxc_dev_v3rho3), worker%dev(libxc_dev_v3rho2sigma), &
    1212              :                                                       worker%dev(libxc_dev_v3rho2lapl), worker%dev(libxc_dev_v3rho2tau), &
    1213              :                                                       worker%dev(libxc_dev_v3rhosigma2), worker%dev(libxc_dev_v3rhosigmalapl), &
    1214              :                                                       worker%dev(libxc_dev_v3rhosigmatau), worker%dev(libxc_dev_v3rholapl2), &
    1215              :                                                       worker%dev(libxc_dev_v3rholapltau), worker%dev(libxc_dev_v3rhotau2), &
    1216              :                                                       worker%dev(libxc_dev_v3sigma3), worker%dev(libxc_dev_v3sigma2lapl), &
    1217              :                                                       worker%dev(libxc_dev_v3sigma2tau), worker%dev(libxc_dev_v3sigmalapl2), &
    1218              :                                                       worker%dev(libxc_dev_v3sigmalapltau), worker%dev(libxc_dev_v3sigmatau2), &
    1219              :                                                       worker%dev(libxc_dev_v3lapl3), worker%dev(libxc_dev_v3lapl2tau), &
    1220              :                                                       worker%dev(libxc_dev_v3lapltau2), worker%dev(libxc_dev_v3tau3), np)
    1221              :             END IF
    1222              :          END SELECT
    1223              :       ELSE IF (is_gga) THEN
    1224              :          SELECT CASE (grad_deriv)
    1225              :          CASE (0)
    1226              :             CALL libxc_gga_exc_device(worker%func, worker%dev(libxc_dev_rho), worker%dev(libxc_dev_sigma), &
    1227              :                                       worker%dev(libxc_dev_exc), np)
    1228              :          CASE (1)
    1229              :             IF (no_exc) THEN
    1230              :                CALL libxc_gga_vxc_device(worker%func, worker%dev(libxc_dev_rho), worker%dev(libxc_dev_sigma), &
    1231              :                                          worker%dev(libxc_dev_vrho), worker%dev(libxc_dev_vsigma), np)
    1232              :                worker%exc = 0.0_dp
    1233              :             ELSE
    1234              :                CALL libxc_gga_exc_vxc_device(worker%func, worker%dev(libxc_dev_rho), worker%dev(libxc_dev_sigma), &
    1235              :                                              worker%dev(libxc_dev_exc), worker%dev(libxc_dev_vrho), &
    1236              :                                              worker%dev(libxc_dev_vsigma), np)
    1237              :             END IF
    1238              :          CASE (2)
    1239              :             IF (no_exc) THEN
    1240              :                CALL libxc_gga_vxc_fxc_device(worker%func, worker%dev(libxc_dev_rho), worker%dev(libxc_dev_sigma), &
    1241              :                                              worker%dev(libxc_dev_vrho), worker%dev(libxc_dev_vsigma), &
    1242              :                                              worker%dev(libxc_dev_v2rho2), worker%dev(libxc_dev_v2rhosigma), &
    1243              :                                              worker%dev(libxc_dev_v2sigma2), np)
    1244              :                worker%exc = 0.0_dp
    1245              :             ELSE
    1246              :                CALL libxc_gga_exc_vxc_fxc_device(worker%func, worker%dev(libxc_dev_rho), worker%dev(libxc_dev_sigma), &
    1247              :                                                  worker%dev(libxc_dev_exc), worker%dev(libxc_dev_vrho), &
    1248              :                                                  worker%dev(libxc_dev_vsigma), worker%dev(libxc_dev_v2rho2), &
    1249              :                                                  worker%dev(libxc_dev_v2rhosigma), worker%dev(libxc_dev_v2sigma2), np)
    1250              :             END IF
    1251              :          CASE (3)
    1252              :             IF (no_exc) THEN
    1253              :                CALL libxc_gga_vxc_fxc_kxc_device(worker%func, worker%dev(libxc_dev_rho), worker%dev(libxc_dev_sigma), &
    1254              :                                                  worker%dev(libxc_dev_vrho), worker%dev(libxc_dev_vsigma), &
    1255              :                                                  worker%dev(libxc_dev_v2rho2), worker%dev(libxc_dev_v2rhosigma), &
    1256              :                                                  worker%dev(libxc_dev_v2sigma2), worker%dev(libxc_dev_v3rho3), &
    1257              :                                                  worker%dev(libxc_dev_v3rho2sigma), worker%dev(libxc_dev_v3rhosigma2), &
    1258              :                                                  worker%dev(libxc_dev_v3sigma3), np)
    1259              :                worker%exc = 0.0_dp
    1260              :             ELSE
    1261              :                CALL libxc_gga_exc_vxc_fxc_kxc_device(worker%func, worker%dev(libxc_dev_rho), &
    1262              :                                                      worker%dev(libxc_dev_sigma), worker%dev(libxc_dev_exc), &
    1263              :                                                      worker%dev(libxc_dev_vrho), worker%dev(libxc_dev_vsigma), &
    1264              :                                                      worker%dev(libxc_dev_v2rho2), worker%dev(libxc_dev_v2rhosigma), &
    1265              :                                                      worker%dev(libxc_dev_v2sigma2), worker%dev(libxc_dev_v3rho3), &
    1266              :                                                      worker%dev(libxc_dev_v3rho2sigma), worker%dev(libxc_dev_v3rhosigma2), &
    1267              :                                                      worker%dev(libxc_dev_v3sigma3), np)
    1268              :             END IF
    1269              :          END SELECT
    1270              :       ELSE
    1271              :          SELECT CASE (grad_deriv)
    1272              :          CASE (0)
    1273              :             CALL libxc_lda_exc_device(worker%func, worker%dev(libxc_dev_rho), worker%dev(libxc_dev_exc), np)
    1274              :          CASE (1)
    1275              :             CALL libxc_lda_exc_vxc_device(worker%func, worker%dev(libxc_dev_rho), worker%dev(libxc_dev_exc), &
    1276              :                                           worker%dev(libxc_dev_vrho), np)
    1277              :          CASE (2)
    1278              :             CALL libxc_lda_exc_vxc_fxc_device(worker%func, worker%dev(libxc_dev_rho), worker%dev(libxc_dev_exc), &
    1279              :                                               worker%dev(libxc_dev_vrho), worker%dev(libxc_dev_v2rho2), np)
    1280              :          CASE (3)
    1281              :             CALL libxc_lda_exc_vxc_fxc_kxc_device(worker%func, worker%dev(libxc_dev_rho), worker%dev(libxc_dev_exc), &
    1282              :                                                   worker%dev(libxc_dev_vrho), worker%dev(libxc_dev_v2rho2), &
    1283              :                                                   worker%dev(libxc_dev_v3rho3), np)
    1284              :          END SELECT
    1285              :       END IF
    1286              : 
    1287              :    END SUBROUTINE libxc_worker_eval_device
    1288              : 
    1289              : ! **************************************************************************************************
    1290              : !> \brief Grows a worker's staging and device buffers to hold at least npoints
    1291              : !>        grid points.
    1292              : !> \param worker the worker
    1293              : !> \param family LibXC functional family
    1294              : !> \param nspin XC_UNPOLARIZED or XC_POLARIZED
    1295              : !> \param npoints number of grid points the buffers must hold
    1296              : !> \author S. Lehtola
    1297              : !> \note Only used on the GPU path, where the whole grid is handed to LibXC in
    1298              : !>       a single call (no block cap), so the staging and device buffers have
    1299              : !>       to hold the entire grid. They grow to the largest point count seen and
    1300              : !>       are reused (never shrunk) for the run. Only the arrays the worker
    1301              : !>       actually carries are touched, mirroring libxc_worker_alloc_buffers.
    1302              : ! **************************************************************************************************
    1303              :    SUBROUTINE libxc_worker_resize_cuda(worker, family, nspin, npoints)
    1304              :       TYPE(libxc_worker_type), INTENT(INOUT)             :: worker
    1305              :       INTEGER, INTENT(IN)                                :: family, nspin, npoints
    1306              : 
    1307              :       INTEGER                                            :: nl, np, ns
    1308              :       LOGICAL                                            :: pol
    1309              : 
    1310              :       pol = (nspin == XC_POLARIZED)
    1311              :       CALL libxc_worker_dims(nspin, np, ns, nl)
    1312              : 
    1313              :       ! grow the host staging buffers that are actually allocated
    1314              :       IF (ALLOCATED(worker%rho)) THEN
    1315              :          IF (SIZE(worker%rho, 2) < npoints) THEN
    1316              :             DEALLOCATE (worker%rho)
    1317              :             ALLOCATE (worker%rho(np, npoints))
    1318              :          END IF
    1319              :       END IF
    1320              :       IF (ALLOCATED(worker%exc)) THEN
    1321              :          IF (SIZE(worker%exc) < npoints) THEN
    1322              :             DEALLOCATE (worker%exc)
    1323              :             ALLOCATE (worker%exc(npoints))
    1324              :          END IF
    1325              :       END IF
    1326              :       IF (ALLOCATED(worker%vrho)) THEN
    1327              :          IF (SIZE(worker%vrho, 2) < npoints) THEN
    1328              :             DEALLOCATE (worker%vrho)
    1329              :             ALLOCATE (worker%vrho(np, npoints))
    1330              :          END IF
    1331              :       END IF
    1332              :       IF (ALLOCATED(worker%v2rho2)) THEN
    1333              :          IF (SIZE(worker%v2rho2, 2) < npoints) THEN
    1334              :             DEALLOCATE (worker%v2rho2)
    1335              :             ALLOCATE (worker%v2rho2(ns, npoints))
    1336              :          END IF
    1337              :       END IF
    1338              :       IF (ALLOCATED(worker%v3rho3)) THEN
    1339              :          IF (SIZE(worker%v3rho3, 2) < npoints) THEN
    1340              :             DEALLOCATE (worker%v3rho3)
    1341              :             ALLOCATE (worker%v3rho3(nl, npoints))
    1342              :          END IF
    1343              :       END IF
    1344              : 
    1345              :       SELECT CASE (family)
    1346              :       CASE (XC_FAMILY_GGA, XC_FAMILY_HYB_GGA, XC_FAMILY_MGGA, XC_FAMILY_HYB_MGGA)
    1347              :          IF (ALLOCATED(worker%sigma)) THEN
    1348              :             IF (SIZE(worker%sigma, 2) < npoints) THEN
    1349              :                DEALLOCATE (worker%sigma)
    1350              :                ALLOCATE (worker%sigma(ns, npoints))
    1351              :             END IF
    1352              :          END IF
    1353              :          IF (ALLOCATED(worker%vsigma)) THEN
    1354              :             IF (SIZE(worker%vsigma, 2) < npoints) THEN
    1355              :                DEALLOCATE (worker%vsigma)
    1356              :                ALLOCATE (worker%vsigma(ns, npoints))
    1357              :             END IF
    1358              :          END IF
    1359              :          IF (pol) THEN
    1360              :             IF (ALLOCATED(worker%nd) .AND. SIZE(worker%nd) < npoints) THEN
    1361              :                DEALLOCATE (worker%nd, worker%nda, worker%ndb)
    1362              :                ALLOCATE (worker%nd(npoints), worker%nda(npoints), worker%ndb(npoints))
    1363              :             END IF
    1364              :          END IF
    1365              :          IF (ALLOCATED(worker%v2rhosigma)) THEN
    1366              :             IF (SIZE(worker%v2rhosigma, 2) < npoints) THEN
    1367              :                DEALLOCATE (worker%v2rhosigma)
    1368              :                ALLOCATE (worker%v2rhosigma(MERGE(6, 1, pol), npoints))
    1369              :             END IF
    1370              :          END IF
    1371              :          IF (ALLOCATED(worker%v2sigma2)) THEN
    1372              :             IF (SIZE(worker%v2sigma2, 2) < npoints) THEN
    1373              :                DEALLOCATE (worker%v2sigma2)
    1374              :                ALLOCATE (worker%v2sigma2(MERGE(6, 1, pol), npoints))
    1375              :             END IF
    1376              :          END IF
    1377              :          #:for arr, dim in [("v3rho2sigma", "MERGE(9, 1, pol)"), &
    1378              :             ("v3rhosigma2", "MERGE(12, 1, pol)"), &
    1379              :             ("v3sigma3", "MERGE(10, 1, pol)")]
    1380              :             IF (ALLOCATED(worker%${arr}$)) THEN
    1381              :                IF (SIZE(worker%${arr}$, 2) < npoints) THEN
    1382              :                   DEALLOCATE (worker%${arr}$)
    1383              :                   ALLOCATE (worker%${arr}$ (${dim}$, npoints))
    1384              :                END IF
    1385              :             END IF
    1386              :          #:endfor
    1387              :       END SELECT
    1388              : 
    1389              :       SELECT CASE (family)
    1390              :       CASE (XC_FAMILY_MGGA, XC_FAMILY_HYB_MGGA)
    1391              :          #:for arr, dim in [("lapl", "np"), ("tau", "np"), ("vlapl", "np"), ("vtau", "np")]
    1392              :             IF (ALLOCATED(worker%${arr}$)) THEN
    1393              :                IF (SIZE(worker%${arr}$, 2) < npoints) THEN
    1394              :                   DEALLOCATE (worker%${arr}$)
    1395              :                   ALLOCATE (worker%${arr}$ (${dim}$, npoints))
    1396              :                END IF
    1397              :             END IF
    1398              :          #:endfor
    1399              :          ! LibXC leaves vlapl untouched for functionals that do not use the
    1400              :          ! Laplacian; re-zero a freshly grown buffer as in the initial alloc.
    1401              :          IF (ALLOCATED(worker%vlapl)) worker%vlapl = 0.0_dp
    1402              :          #:for arr, dim in [("v2rholapl", "nl"), ("v2rhotau", "nl"), &
    1403              :             ("v2sigmalapl", "MERGE(6, 1, pol)"), &
    1404              :             ("v2sigmatau", "MERGE(6, 1, pol)"), &
    1405              :             ("v2lapl2", "ns"), ("v2lapltau", "nl"), ("v2tau2", "ns")]
    1406              :             IF (ALLOCATED(worker%${arr}$)) THEN
    1407              :                IF (SIZE(worker%${arr}$, 2) < npoints) THEN
    1408              :                   DEALLOCATE (worker%${arr}$)
    1409              :                   ALLOCATE (worker%${arr}$ (${dim}$, npoints))
    1410              :                END IF
    1411              :             END IF
    1412              :          #:endfor
    1413              :          #:for arr in v3_new
    1414              :             IF (ALLOCATED(worker%${arr}$)) THEN
    1415              :                IF (SIZE(worker%${arr}$, 2) < npoints) THEN
    1416              :                   DEALLOCATE (worker%${arr}$)
    1417              :                   ALLOCATE (worker%${arr}$ (MERGE(${mgga_ncomp[arr]}$, 1, pol), npoints))
    1418              :                END IF
    1419              :             END IF
    1420              :          #:endfor
    1421              :       END SELECT
    1422              : 
    1423              :       ! grow only the CUDA device buffers that are already large enough to be
    1424              :       ! reused; the grow-only guards keep the derivative-order and family
    1425              :       ! logic of libxc_worker_alloc_buffers intact.
    1426              :       CALL libxc_worker_device_alloc(worker, family, pol, nl, np, ns, npoints, grow_only=.TRUE.)
    1427              : 
    1428              :    END SUBROUTINE libxc_worker_resize_cuda
    1429              : 
    1430              : ! **************************************************************************************************
    1431              : !> \brief Allocate a device buffer for LibXC.
    1432              : !> \param buffer ...
    1433              : !> \param n ...
    1434              : ! **************************************************************************************************
    1435              :    SUBROUTINE libxc_device_buffer_alloc(buffer, n)
    1436              :       USE ISO_C_BINDING, ONLY: C_INT64_T
    1437              :       USE offload_api, ONLY: offload_create_buffer
    1438              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: buffer
    1439              :       INTEGER, INTENT(IN)                                :: n
    1440              : 
    1441              :       ! Release any previous allocation first: the GPU path regrows the device
    1442              :       ! buffers to the whole grid (libxc_worker_resize_cuda), and
    1443              :       ! offload_create_buffer does not free the old device pointer on its own.
    1444              :       ! Freeing a buffer that was never allocated is a no-op.
    1445              :       CALL libxc_device_buffer_free(buffer)
    1446              : 
    1447              :       buffer%size = INT(n, KIND=C_INT64_T)
    1448              :       CALL offload_create_buffer(n, buffer%buffer)
    1449              :    END SUBROUTINE libxc_device_buffer_alloc
    1450              : 
    1451              : ! **************************************************************************************************
    1452              : !> \brief Free a LibXC device buffer.
    1453              : !> \param buffer ...
    1454              : ! **************************************************************************************************
    1455              :    SUBROUTINE libxc_device_buffer_free(buffer)
    1456              :       USE offload_api, ONLY: offload_free_buffer
    1457              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: buffer
    1458              : 
    1459              :       CALL offload_free_buffer(buffer%buffer)
    1460              :       buffer%size = 0
    1461              :    END SUBROUTINE libxc_device_buffer_free
    1462              : 
    1463              : ! **************************************************************************************************
    1464              : !> \brief Copy host data into a LibXC device buffer.
    1465              : !> \param buffer ...
    1466              : !> \param host ...
    1467              : !> \param n ...
    1468              : ! **************************************************************************************************
    1469              :    SUBROUTINE libxc_host_to_device(buffer, host, n)
    1470              :       USE ISO_C_BINDING, ONLY: C_PTR, C_F_POINTER
    1471              :       USE offload_api, ONLY: offload_buffer_h2d, offload_get_buffer_host_pointer
    1472              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: buffer
    1473              :       REAL(KIND=dp), DIMENSION(*), INTENT(IN)            :: host
    1474              :       INTEGER, INTENT(IN)                                :: n
    1475              : 
    1476              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: host_p
    1477              :       TYPE(C_PTR)                                        :: hptr
    1478              : 
    1479              :       hptr = offload_get_buffer_host_pointer(buffer%buffer)
    1480              :       CALL C_F_POINTER(hptr, host_p, [n])
    1481              :       host_p(1:n) = host(1:n)
    1482              :       CALL offload_buffer_h2d(buffer%buffer, n)
    1483              :    END SUBROUTINE libxc_host_to_device
    1484              : ! **************************************************************************************************
    1485              : !> \brief Issue a device-to-host copy of a LibXC buffer.
    1486              : !> \param buffer ...
    1487              : !> \param n ...
    1488              : ! **************************************************************************************************
    1489              :    SUBROUTINE libxc_d2h_issue(buffer, n)
    1490              :       USE offload_api, ONLY: offload_buffer_d2h
    1491              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: buffer
    1492              :       INTEGER, INTENT(IN)                                :: n
    1493              : 
    1494              :       CALL offload_buffer_d2h(buffer%buffer, n)
    1495              :    END SUBROUTINE libxc_d2h_issue
    1496              : ! **************************************************************************************************
    1497              : !> \brief Read the host side of a LibXC device buffer after a copy.
    1498              : !> \param host ...
    1499              : !> \param buffer ...
    1500              : !> \param n ...
    1501              : ! **************************************************************************************************
    1502              :    SUBROUTINE libxc_d2h_read(host, buffer, n)
    1503              :       USE ISO_C_BINDING, ONLY: C_PTR, C_F_POINTER
    1504              :       USE offload_api, ONLY: offload_get_buffer_host_pointer
    1505              :       REAL(KIND=dp), DIMENSION(*), INTENT(OUT)           :: host
    1506              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: buffer
    1507              :       INTEGER, INTENT(IN)                                :: n
    1508              : 
    1509              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: host_p
    1510              :       TYPE(C_PTR)                                        :: hptr
    1511              : 
    1512              :       hptr = offload_get_buffer_host_pointer(buffer%buffer)
    1513              :       CALL C_F_POINTER(hptr, host_p, [n])
    1514              :       host(1:n) = host_p(1:n)
    1515              :    END SUBROUTINE libxc_d2h_read
    1516              : 
    1517              : ! **************************************************************************************************
    1518              : !> \brief Return a Fortran pointer to a device buffer's underlying GPU memory.
    1519              : !> \param buffer ...
    1520              : !> \param n ...
    1521              : !> \param fptr ...
    1522              : ! **************************************************************************************************
    1523              :    SUBROUTINE libxc_device_buffer_get_ptr(buffer, n, fptr)
    1524              :       USE ISO_C_BINDING, ONLY: C_F_POINTER, C_PTR
    1525              :       USE offload_api, ONLY: offload_get_buffer_device_pointer
    1526              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: buffer
    1527              :       INTEGER, INTENT(IN)                                :: n
    1528              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT), POINTER  :: fptr
    1529              : 
    1530              :       TYPE(C_PTR)                                        :: dptr
    1531              : 
    1532              :       dptr = offload_get_buffer_device_pointer(buffer%buffer)
    1533              :       CALL C_F_POINTER(dptr, fptr, [n])
    1534              :    END SUBROUTINE libxc_device_buffer_get_ptr
    1535              : 
    1536              : ! **************************************************************************************************
    1537              : !> \brief LDA exc and vxc on device buffers.
    1538              : !> \param func ...
    1539              : !> \param rho_d ...
    1540              : !> \param exc_d ...
    1541              : !> \param vrho_d ...
    1542              : !> \param np ...
    1543              : ! **************************************************************************************************
    1544              :    SUBROUTINE libxc_lda_exc_vxc_device(func, rho_d, exc_d, vrho_d, np)
    1545              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    1546              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    1547              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: rho_d
    1548              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: exc_d, vrho_d
    1549              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    1550              : 
    1551              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: exc_p, rho_p, vrho_p
    1552              : 
    1553              :       CALL libxc_device_buffer_get_ptr(rho_d, INT(rho_d%size), rho_p)
    1554              :       CALL libxc_device_buffer_get_ptr(exc_d, INT(exc_d%size), exc_p)
    1555              :       CALL libxc_device_buffer_get_ptr(vrho_d, INT(vrho_d%size), vrho_p)
    1556              : 
    1557              :       CALL xc_f03_lda_exc_vxc(func, np, rho_p, exc_p, vrho_p)
    1558              :    END SUBROUTINE libxc_lda_exc_vxc_device
    1559              : 
    1560              : ! **************************************************************************************************
    1561              : !> \brief LDA exc on device buffers.
    1562              : !> \param func ...
    1563              : !> \param rho_d ...
    1564              : !> \param exc_d ...
    1565              : !> \param np ...
    1566              : ! **************************************************************************************************
    1567              :    SUBROUTINE libxc_lda_exc_device(func, rho_d, exc_d, np)
    1568              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    1569              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    1570              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: rho_d
    1571              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: exc_d
    1572              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    1573              : 
    1574              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: exc_p, rho_p
    1575              : 
    1576              :       CALL libxc_device_buffer_get_ptr(rho_d, INT(rho_d%size), rho_p)
    1577              :       CALL libxc_device_buffer_get_ptr(exc_d, INT(exc_d%size), exc_p)
    1578              : 
    1579              :       CALL xc_f03_lda_exc(func, np, rho_p, exc_p)
    1580              :    END SUBROUTINE libxc_lda_exc_device
    1581              : 
    1582              : ! **************************************************************************************************
    1583              : !> \brief LDA exc, vxc and fxc on device buffers.
    1584              : !> \param func ...
    1585              : !> \param rho_d ...
    1586              : !> \param exc_d ...
    1587              : !> \param vrho_d ...
    1588              : !> \param v2rho2_d ...
    1589              : !> \param np ...
    1590              : ! **************************************************************************************************
    1591              :    SUBROUTINE libxc_lda_exc_vxc_fxc_device(func, rho_d, exc_d, vrho_d, v2rho2_d, np)
    1592              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    1593              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    1594              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: rho_d
    1595              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: exc_d, vrho_d, v2rho2_d
    1596              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    1597              : 
    1598              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: exc_p, rho_p, v2rho2_p, vrho_p
    1599              : 
    1600              :       CALL libxc_device_buffer_get_ptr(rho_d, INT(rho_d%size), rho_p)
    1601              :       CALL libxc_device_buffer_get_ptr(exc_d, INT(exc_d%size), exc_p)
    1602              :       CALL libxc_device_buffer_get_ptr(vrho_d, INT(vrho_d%size), vrho_p)
    1603              :       CALL libxc_device_buffer_get_ptr(v2rho2_d, INT(v2rho2_d%size), v2rho2_p)
    1604              : 
    1605              :       CALL xc_f03_lda_exc_vxc_fxc(func, np, rho_p, exc_p, vrho_p, v2rho2_p)
    1606              :    END SUBROUTINE libxc_lda_exc_vxc_fxc_device
    1607              : 
    1608              : ! **************************************************************************************************
    1609              : !> \brief LDA exc, vxc, fxc and kxc on device buffers.
    1610              : !> \param func ...
    1611              : !> \param rho_d ...
    1612              : !> \param exc_d ...
    1613              : !> \param vrho_d ...
    1614              : !> \param v2rho2_d ...
    1615              : !> \param v3rho3_d ...
    1616              : !> \param np ...
    1617              : ! **************************************************************************************************
    1618              :    SUBROUTINE libxc_lda_exc_vxc_fxc_kxc_device(func, rho_d, exc_d, vrho_d, v2rho2_d, v3rho3_d, np)
    1619              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    1620              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    1621              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: rho_d
    1622              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: exc_d, vrho_d, v2rho2_d, v3rho3_d
    1623              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    1624              : 
    1625              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: exc_p, rho_p, v2rho2_p, v3rho3_p, vrho_p
    1626              : 
    1627              :       CALL libxc_device_buffer_get_ptr(rho_d, INT(rho_d%size), rho_p)
    1628              :       CALL libxc_device_buffer_get_ptr(exc_d, INT(exc_d%size), exc_p)
    1629              :       CALL libxc_device_buffer_get_ptr(vrho_d, INT(vrho_d%size), vrho_p)
    1630              :       CALL libxc_device_buffer_get_ptr(v2rho2_d, INT(v2rho2_d%size), v2rho2_p)
    1631              :       CALL libxc_device_buffer_get_ptr(v3rho3_d, INT(v3rho3_d%size), v3rho3_p)
    1632              : 
    1633              :       CALL xc_f03_lda_exc_vxc_fxc_kxc(func, np, rho_p, exc_p, vrho_p, v2rho2_p, v3rho3_p)
    1634              :    END SUBROUTINE libxc_lda_exc_vxc_fxc_kxc_device
    1635              : 
    1636              : ! **************************************************************************************************
    1637              : !> \brief GGA exc on device buffers.
    1638              : !> \param func ...
    1639              : !> \param rho_d ...
    1640              : !> \param sigma_d ...
    1641              : !> \param exc_d ...
    1642              : !> \param np ...
    1643              : ! **************************************************************************************************
    1644              :    SUBROUTINE libxc_gga_exc_device(func, rho_d, sigma_d, exc_d, np)
    1645              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    1646              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    1647              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: rho_d, sigma_d
    1648              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: exc_d
    1649              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    1650              : 
    1651              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: exc_p, rho_p, sigma_p
    1652              : 
    1653              :       CALL libxc_device_buffer_get_ptr(rho_d, INT(rho_d%size), rho_p)
    1654              :       CALL libxc_device_buffer_get_ptr(sigma_d, INT(sigma_d%size), sigma_p)
    1655              :       CALL libxc_device_buffer_get_ptr(exc_d, INT(exc_d%size), exc_p)
    1656              : 
    1657              :       CALL xc_f03_gga_exc(func, np, rho_p, sigma_p, exc_p)
    1658              :    END SUBROUTINE libxc_gga_exc_device
    1659              : 
    1660              : ! **************************************************************************************************
    1661              : !> \brief GGA exc and vxc on device buffers.
    1662              : !> \param func ...
    1663              : !> \param rho_d ...
    1664              : !> \param sigma_d ...
    1665              : !> \param exc_d ...
    1666              : !> \param vrho_d ...
    1667              : !> \param vsigma_d ...
    1668              : !> \param np ...
    1669              : ! **************************************************************************************************
    1670              :    SUBROUTINE libxc_gga_exc_vxc_device(func, rho_d, sigma_d, exc_d, vrho_d, vsigma_d, np)
    1671              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    1672              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    1673              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: rho_d, sigma_d
    1674              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: exc_d, vrho_d, vsigma_d
    1675              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    1676              : 
    1677              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: exc_p, rho_p, sigma_p, vrho_p, vsigma_p
    1678              : 
    1679              :       CALL libxc_device_buffer_get_ptr(rho_d, INT(rho_d%size), rho_p)
    1680              :       CALL libxc_device_buffer_get_ptr(sigma_d, INT(sigma_d%size), sigma_p)
    1681              :       CALL libxc_device_buffer_get_ptr(exc_d, INT(exc_d%size), exc_p)
    1682              :       CALL libxc_device_buffer_get_ptr(vrho_d, INT(vrho_d%size), vrho_p)
    1683              :       CALL libxc_device_buffer_get_ptr(vsigma_d, INT(vsigma_d%size), vsigma_p)
    1684              : 
    1685              :       CALL xc_f03_gga_exc_vxc(func, np, rho_p, sigma_p, exc_p, vrho_p, vsigma_p)
    1686              :    END SUBROUTINE libxc_gga_exc_vxc_device
    1687              : 
    1688              : ! **************************************************************************************************
    1689              : !> \brief GGA exc, vxc and fxc on device buffers.
    1690              : !> \param func ...
    1691              : !> \param rho_d ...
    1692              : !> \param sigma_d ...
    1693              : !> \param exc_d ...
    1694              : !> \param vrho_d ...
    1695              : !> \param vsigma_d ...
    1696              : !> \param v2rho2_d ...
    1697              : !> \param v2rhosigma_d ...
    1698              : !> \param v2sigma2_d ...
    1699              : !> \param np ...
    1700              : ! **************************************************************************************************
    1701              :    SUBROUTINE libxc_gga_exc_vxc_fxc_device(func, rho_d, sigma_d, exc_d, vrho_d, vsigma_d, &
    1702              :                                            v2rho2_d, v2rhosigma_d, v2sigma2_d, np)
    1703              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    1704              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    1705              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: rho_d, sigma_d
    1706              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: exc_d, vrho_d, vsigma_d, v2rho2_d, &
    1707              :                                                             v2rhosigma_d, v2sigma2_d
    1708              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    1709              : 
    1710              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: exc_p, rho_p, sigma_p, v2rho2_p, &
    1711              :                                                             v2rhosigma_p, v2sigma2_p, vrho_p, &
    1712              :                                                             vsigma_p
    1713              : 
    1714              :       CALL libxc_device_buffer_get_ptr(rho_d, INT(rho_d%size), rho_p)
    1715              :       CALL libxc_device_buffer_get_ptr(sigma_d, INT(sigma_d%size), sigma_p)
    1716              :       CALL libxc_device_buffer_get_ptr(exc_d, INT(exc_d%size), exc_p)
    1717              :       CALL libxc_device_buffer_get_ptr(vrho_d, INT(vrho_d%size), vrho_p)
    1718              :       CALL libxc_device_buffer_get_ptr(vsigma_d, INT(vsigma_d%size), vsigma_p)
    1719              :       CALL libxc_device_buffer_get_ptr(v2rho2_d, INT(v2rho2_d%size), v2rho2_p)
    1720              :       CALL libxc_device_buffer_get_ptr(v2rhosigma_d, INT(v2rhosigma_d%size), v2rhosigma_p)
    1721              :       CALL libxc_device_buffer_get_ptr(v2sigma2_d, INT(v2sigma2_d%size), v2sigma2_p)
    1722              : 
    1723              :       CALL xc_f03_gga_exc_vxc_fxc(func, np, rho_p, sigma_p, exc_p, vrho_p, vsigma_p, &
    1724              :                                   v2rho2_p, v2rhosigma_p, v2sigma2_p)
    1725              :    END SUBROUTINE libxc_gga_exc_vxc_fxc_device
    1726              : 
    1727              : ! **************************************************************************************************
    1728              : !> \brief GGA vxc and fxc on device buffers.
    1729              : !> \param func ...
    1730              : !> \param rho_d ...
    1731              : !> \param sigma_d ...
    1732              : !> \param vrho_d ...
    1733              : !> \param vsigma_d ...
    1734              : !> \param v2rho2_d ...
    1735              : !> \param v2rhosigma_d ...
    1736              : !> \param v2sigma2_d ...
    1737              : !> \param np ...
    1738              : ! **************************************************************************************************
    1739              :    SUBROUTINE libxc_gga_vxc_fxc_device(func, rho_d, sigma_d, vrho_d, vsigma_d, &
    1740              :                                        v2rho2_d, v2rhosigma_d, v2sigma2_d, np)
    1741              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    1742              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    1743              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: rho_d, sigma_d
    1744              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: vrho_d, vsigma_d, v2rho2_d, &
    1745              :                                                             v2rhosigma_d, v2sigma2_d
    1746              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    1747              : 
    1748              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: rho_p, sigma_p, v2rho2_p, v2rhosigma_p, &
    1749              :                                                             v2sigma2_p, vrho_p, vsigma_p
    1750              : 
    1751              :       CALL libxc_device_buffer_get_ptr(rho_d, INT(rho_d%size), rho_p)
    1752              :       CALL libxc_device_buffer_get_ptr(sigma_d, INT(sigma_d%size), sigma_p)
    1753              :       CALL libxc_device_buffer_get_ptr(vrho_d, INT(vrho_d%size), vrho_p)
    1754              :       CALL libxc_device_buffer_get_ptr(vsigma_d, INT(vsigma_d%size), vsigma_p)
    1755              :       CALL libxc_device_buffer_get_ptr(v2rho2_d, INT(v2rho2_d%size), v2rho2_p)
    1756              :       CALL libxc_device_buffer_get_ptr(v2rhosigma_d, INT(v2rhosigma_d%size), v2rhosigma_p)
    1757              :       CALL libxc_device_buffer_get_ptr(v2sigma2_d, INT(v2sigma2_d%size), v2sigma2_p)
    1758              : 
    1759              :       CALL xc_f03_gga_vxc_fxc(func, np, rho_p, sigma_p, vrho_p, vsigma_p, &
    1760              :                               v2rho2_p, v2rhosigma_p, v2sigma2_p)
    1761              :    END SUBROUTINE libxc_gga_vxc_fxc_device
    1762              : 
    1763              : ! **************************************************************************************************
    1764              : !> \brief GGA exc, vxc, fxc and kxc on device buffers.
    1765              : !> \param func ...
    1766              : !> \param rho_d ...
    1767              : !> \param sigma_d ...
    1768              : !> \param exc_d ...
    1769              : !> \param vrho_d ...
    1770              : !> \param vsigma_d ...
    1771              : !> \param v2rho2_d ...
    1772              : !> \param v2rhosigma_d ...
    1773              : !> \param v2sigma2_d ...
    1774              : !> \param v3rho3_d ...
    1775              : !> \param v3rho2sigma_d ...
    1776              : !> \param v3rhosigma2_d ...
    1777              : !> \param v3sigma3_d ...
    1778              : !> \param np ...
    1779              : ! **************************************************************************************************
    1780              :    SUBROUTINE libxc_gga_exc_vxc_fxc_kxc_device(func, rho_d, sigma_d, exc_d, vrho_d, vsigma_d, &
    1781              :                                                v2rho2_d, v2rhosigma_d, v2sigma2_d, &
    1782              :                                                v3rho3_d, v3rho2sigma_d, v3rhosigma2_d, v3sigma3_d, np)
    1783              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    1784              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    1785              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: rho_d, sigma_d
    1786              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: exc_d, vrho_d, vsigma_d, v2rho2_d, &
    1787              :                                                             v2rhosigma_d, v2sigma2_d, v3rho3_d, &
    1788              :                                                             v3rho2sigma_d, v3rhosigma2_d, &
    1789              :                                                             v3sigma3_d
    1790              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    1791              : 
    1792              :       REAL(KIND=dp), DIMENSION(:), POINTER :: exc_p, rho_p, sigma_p, v2rho2_p, v2rhosigma_p, &
    1793              :                                               v2sigma2_p, v3rho2sigma_p, v3rho3_p, v3rhosigma2_p, v3sigma3_p, vrho_p, vsigma_p
    1794              : 
    1795              :       CALL libxc_device_buffer_get_ptr(rho_d, INT(rho_d%size), rho_p)
    1796              :       CALL libxc_device_buffer_get_ptr(sigma_d, INT(sigma_d%size), sigma_p)
    1797              :       CALL libxc_device_buffer_get_ptr(exc_d, INT(exc_d%size), exc_p)
    1798              :       CALL libxc_device_buffer_get_ptr(vrho_d, INT(vrho_d%size), vrho_p)
    1799              :       CALL libxc_device_buffer_get_ptr(vsigma_d, INT(vsigma_d%size), vsigma_p)
    1800              :       CALL libxc_device_buffer_get_ptr(v2rho2_d, INT(v2rho2_d%size), v2rho2_p)
    1801              :       CALL libxc_device_buffer_get_ptr(v2rhosigma_d, INT(v2rhosigma_d%size), v2rhosigma_p)
    1802              :       CALL libxc_device_buffer_get_ptr(v2sigma2_d, INT(v2sigma2_d%size), v2sigma2_p)
    1803              :       CALL libxc_device_buffer_get_ptr(v3rho3_d, INT(v3rho3_d%size), v3rho3_p)
    1804              :       CALL libxc_device_buffer_get_ptr(v3rho2sigma_d, INT(v3rho2sigma_d%size), v3rho2sigma_p)
    1805              :       CALL libxc_device_buffer_get_ptr(v3rhosigma2_d, INT(v3rhosigma2_d%size), v3rhosigma2_p)
    1806              :       CALL libxc_device_buffer_get_ptr(v3sigma3_d, INT(v3sigma3_d%size), v3sigma3_p)
    1807              : 
    1808              :       CALL xc_f03_gga_exc_vxc_fxc_kxc(func, np, rho_p, sigma_p, exc_p, vrho_p, vsigma_p, &
    1809              :                                       v2rho2_p, v2rhosigma_p, v2sigma2_p, v3rho3_p, &
    1810              :                                       v3rho2sigma_p, v3rhosigma2_p, v3sigma3_p)
    1811              :    END SUBROUTINE libxc_gga_exc_vxc_fxc_kxc_device
    1812              : 
    1813              : ! **************************************************************************************************
    1814              : !> \brief GGA vxc, fxc and kxc on device buffers.
    1815              : !> \param func ...
    1816              : !> \param rho_d ...
    1817              : !> \param sigma_d ...
    1818              : !> \param vrho_d ...
    1819              : !> \param vsigma_d ...
    1820              : !> \param v2rho2_d ...
    1821              : !> \param v2rhosigma_d ...
    1822              : !> \param v2sigma2_d ...
    1823              : !> \param v3rho3_d ...
    1824              : !> \param v3rho2sigma_d ...
    1825              : !> \param v3rhosigma2_d ...
    1826              : !> \param v3sigma3_d ...
    1827              : !> \param np ...
    1828              : ! **************************************************************************************************
    1829              :    SUBROUTINE libxc_gga_vxc_fxc_kxc_device(func, rho_d, sigma_d, vrho_d, vsigma_d, &
    1830              :                                            v2rho2_d, v2rhosigma_d, v2sigma2_d, &
    1831              :                                            v3rho3_d, v3rho2sigma_d, v3rhosigma2_d, v3sigma3_d, np)
    1832              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    1833              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    1834              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: rho_d, sigma_d
    1835              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: vrho_d, vsigma_d, v2rho2_d, &
    1836              :                                                             v2rhosigma_d, v2sigma2_d, v3rho3_d, &
    1837              :                                                             v3rho2sigma_d, v3rhosigma2_d, &
    1838              :                                                             v3sigma3_d
    1839              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    1840              : 
    1841              :       REAL(KIND=dp), DIMENSION(:), POINTER :: rho_p, sigma_p, v2rho2_p, v2rhosigma_p, v2sigma2_p, &
    1842              :                                               v3rho2sigma_p, v3rho3_p, v3rhosigma2_p, v3sigma3_p, vrho_p, vsigma_p
    1843              : 
    1844              :       CALL libxc_device_buffer_get_ptr(rho_d, INT(rho_d%size), rho_p)
    1845              :       CALL libxc_device_buffer_get_ptr(sigma_d, INT(sigma_d%size), sigma_p)
    1846              :       CALL libxc_device_buffer_get_ptr(vrho_d, INT(vrho_d%size), vrho_p)
    1847              :       CALL libxc_device_buffer_get_ptr(vsigma_d, INT(vsigma_d%size), vsigma_p)
    1848              :       CALL libxc_device_buffer_get_ptr(v2rho2_d, INT(v2rho2_d%size), v2rho2_p)
    1849              :       CALL libxc_device_buffer_get_ptr(v2rhosigma_d, INT(v2rhosigma_d%size), v2rhosigma_p)
    1850              :       CALL libxc_device_buffer_get_ptr(v2sigma2_d, INT(v2sigma2_d%size), v2sigma2_p)
    1851              :       CALL libxc_device_buffer_get_ptr(v3rho3_d, INT(v3rho3_d%size), v3rho3_p)
    1852              :       CALL libxc_device_buffer_get_ptr(v3rho2sigma_d, INT(v3rho2sigma_d%size), v3rho2sigma_p)
    1853              :       CALL libxc_device_buffer_get_ptr(v3rhosigma2_d, INT(v3rhosigma2_d%size), v3rhosigma2_p)
    1854              :       CALL libxc_device_buffer_get_ptr(v3sigma3_d, INT(v3sigma3_d%size), v3sigma3_p)
    1855              : 
    1856              :       CALL xc_f03_gga_vxc_fxc_kxc(func, np, rho_p, sigma_p, vrho_p, vsigma_p, &
    1857              :                                   v2rho2_p, v2rhosigma_p, v2sigma2_p, v3rho3_p, &
    1858              :                                   v3rho2sigma_p, v3rhosigma2_p, v3sigma3_p)
    1859              :    END SUBROUTINE libxc_gga_vxc_fxc_kxc_device
    1860              : 
    1861              : ! **************************************************************************************************
    1862              : !> \brief GGA vxc on device buffers.
    1863              : !> \param func ...
    1864              : !> \param rho_d ...
    1865              : !> \param sigma_d ...
    1866              : !> \param vrho_d ...
    1867              : !> \param vsigma_d ...
    1868              : !> \param np ...
    1869              : ! **************************************************************************************************
    1870              :    SUBROUTINE libxc_gga_vxc_device(func, rho_d, sigma_d, vrho_d, vsigma_d, np)
    1871              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    1872              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    1873              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: rho_d, sigma_d
    1874              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: vrho_d, vsigma_d
    1875              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    1876              : 
    1877              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: rho_p, sigma_p, vrho_p, vsigma_p
    1878              : 
    1879              :       CALL libxc_device_buffer_get_ptr(rho_d, INT(rho_d%size), rho_p)
    1880              :       CALL libxc_device_buffer_get_ptr(sigma_d, INT(sigma_d%size), sigma_p)
    1881              :       CALL libxc_device_buffer_get_ptr(vrho_d, INT(vrho_d%size), vrho_p)
    1882              :       CALL libxc_device_buffer_get_ptr(vsigma_d, INT(vsigma_d%size), vsigma_p)
    1883              : 
    1884              :       CALL xc_f03_gga_vxc(func, np, rho_p, sigma_p, vrho_p, vsigma_p)
    1885              :    END SUBROUTINE libxc_gga_vxc_device
    1886              : 
    1887              : ! **************************************************************************************************
    1888              : !> \brief MGGA exc on device buffers.
    1889              : !> \param func ...
    1890              : !> \param rho_d ...
    1891              : !> \param sigma_d ...
    1892              : !> \param lapl_d ...
    1893              : !> \param tau_d ...
    1894              : !> \param exc_d ...
    1895              : !> \param np ...
    1896              : ! **************************************************************************************************
    1897              :    SUBROUTINE libxc_mgga_exc_device(func, rho_d, sigma_d, lapl_d, tau_d, exc_d, np)
    1898              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    1899              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    1900              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: rho_d, sigma_d, lapl_d, tau_d
    1901              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: exc_d
    1902              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    1903              : 
    1904              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: exc_p, lapl_p, rho_p, sigma_p, tau_p
    1905              : 
    1906              :       CALL libxc_device_buffer_get_ptr(rho_d, INT(rho_d%size), rho_p)
    1907              :       CALL libxc_device_buffer_get_ptr(sigma_d, INT(sigma_d%size), sigma_p)
    1908              :       CALL libxc_device_buffer_get_ptr(lapl_d, INT(lapl_d%size), lapl_p)
    1909              :       CALL libxc_device_buffer_get_ptr(tau_d, INT(tau_d%size), tau_p)
    1910              :       CALL libxc_device_buffer_get_ptr(exc_d, INT(exc_d%size), exc_p)
    1911              : 
    1912              :       CALL xc_f03_mgga_exc(func, np, rho_p, sigma_p, lapl_p, tau_p, exc_p)
    1913              :    END SUBROUTINE libxc_mgga_exc_device
    1914              : 
    1915              : ! **************************************************************************************************
    1916              : !> \brief MGGA exc and vxc on device buffers.
    1917              : !> \param func ...
    1918              : !> \param rho_d ...
    1919              : !> \param sigma_d ...
    1920              : !> \param lapl_d ...
    1921              : !> \param tau_d ...
    1922              : !> \param exc_d ...
    1923              : !> \param vrho_d ...
    1924              : !> \param vsigma_d ...
    1925              : !> \param vlapl_d ...
    1926              : !> \param vtau_d ...
    1927              : !> \param np ...
    1928              : ! **************************************************************************************************
    1929              :    SUBROUTINE libxc_mgga_exc_vxc_device(func, rho_d, sigma_d, lapl_d, tau_d, exc_d, vrho_d, vsigma_d, vlapl_d, vtau_d, np)
    1930              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    1931              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    1932              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: rho_d, sigma_d, lapl_d, tau_d
    1933              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: exc_d, vrho_d, vsigma_d, vlapl_d, vtau_d
    1934              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    1935              : 
    1936              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: exc_p, lapl_p, rho_p, sigma_p, tau_p, &
    1937              :                                                             vlapl_p, vrho_p, vsigma_p, vtau_p
    1938              : 
    1939              :       CALL libxc_device_buffer_get_ptr(rho_d, INT(rho_d%size), rho_p)
    1940              :       CALL libxc_device_buffer_get_ptr(sigma_d, INT(sigma_d%size), sigma_p)
    1941              :       CALL libxc_device_buffer_get_ptr(lapl_d, INT(lapl_d%size), lapl_p)
    1942              :       CALL libxc_device_buffer_get_ptr(tau_d, INT(tau_d%size), tau_p)
    1943              :       CALL libxc_device_buffer_get_ptr(exc_d, INT(exc_d%size), exc_p)
    1944              :       CALL libxc_device_buffer_get_ptr(vrho_d, INT(vrho_d%size), vrho_p)
    1945              :       CALL libxc_device_buffer_get_ptr(vsigma_d, INT(vsigma_d%size), vsigma_p)
    1946              :       CALL libxc_device_buffer_get_ptr(vlapl_d, INT(vlapl_d%size), vlapl_p)
    1947              :       CALL libxc_device_buffer_get_ptr(vtau_d, INT(vtau_d%size), vtau_p)
    1948              : 
    1949              :       CALL xc_f03_mgga_exc_vxc(func, np, rho_p, sigma_p, lapl_p, tau_p, &
    1950              :                                exc_p, vrho_p, vsigma_p, vlapl_p, vtau_p)
    1951              :    END SUBROUTINE libxc_mgga_exc_vxc_device
    1952              : 
    1953              : ! **************************************************************************************************
    1954              : !> \brief MGGA exc, vxc and fxc on device buffers.
    1955              : !> \param func ...
    1956              : !> \param rho_d ...
    1957              : !> \param sigma_d ...
    1958              : !> \param lapl_d ...
    1959              : !> \param tau_d ...
    1960              : !> \param exc_d ...
    1961              : !> \param vrho_d ...
    1962              : !> \param vsigma_d ...
    1963              : !> \param vlapl_d ...
    1964              : !> \param vtau_d ...
    1965              : !> \param v2rho2_d ...
    1966              : !> \param v2rhosigma_d ...
    1967              : !> \param v2rholapl_d ...
    1968              : !> \param v2rhotau_d ...
    1969              : !> \param v2sigma2_d ...
    1970              : !> \param v2sigmalapl_d ...
    1971              : !> \param v2sigmatau_d ...
    1972              : !> \param v2lapl2_d ...
    1973              : !> \param v2lapltau_d ...
    1974              : !> \param v2tau2_d ...
    1975              : !> \param np ...
    1976              : ! **************************************************************************************************
    1977              :    SUBROUTINE libxc_mgga_exc_vxc_fxc_device(func, rho_d, sigma_d, lapl_d, tau_d, exc_d, &
    1978              :                                             vrho_d, vsigma_d, vlapl_d, vtau_d, v2rho2_d, &
    1979              :                                             v2rhosigma_d, v2rholapl_d, v2rhotau_d, v2sigma2_d, &
    1980              :                                             v2sigmalapl_d, v2sigmatau_d, v2lapl2_d, v2lapltau_d, &
    1981              :                                             v2tau2_d, np)
    1982              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    1983              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    1984              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: rho_d, sigma_d, lapl_d, tau_d
    1985              :       TYPE(libxc_device_buffer_type), INTENT(INOUT) :: exc_d, vrho_d, vsigma_d, vlapl_d, vtau_d, &
    1986              :                                          v2rho2_d, v2rhosigma_d, v2rholapl_d, v2rhotau_d, v2sigma2_d, v2sigmalapl_d, v2sigmatau_d, &
    1987              :                                                        v2lapl2_d, v2lapltau_d, v2tau2_d
    1988              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    1989              : 
    1990              :       REAL(KIND=dp), DIMENSION(:), POINTER :: exc_p, lapl_p, rho_p, sigma_p, tau_p, v2lapl2_p, &
    1991              :                                           v2lapltau_p, v2rho2_p, v2rholapl_p, v2rhosigma_p, v2rhotau_p, v2sigma2_p, v2sigmalapl_p, &
    1992              :                                               v2sigmatau_p, v2tau2_p, vlapl_p, vrho_p, vsigma_p, vtau_p
    1993              : 
    1994              :       CALL libxc_device_buffer_get_ptr(rho_d, INT(rho_d%size), rho_p)
    1995              :       CALL libxc_device_buffer_get_ptr(sigma_d, INT(sigma_d%size), sigma_p)
    1996              :       CALL libxc_device_buffer_get_ptr(lapl_d, INT(lapl_d%size), lapl_p)
    1997              :       CALL libxc_device_buffer_get_ptr(tau_d, INT(tau_d%size), tau_p)
    1998              :       CALL libxc_device_buffer_get_ptr(exc_d, INT(exc_d%size), exc_p)
    1999              :       CALL libxc_device_buffer_get_ptr(vrho_d, INT(vrho_d%size), vrho_p)
    2000              :       CALL libxc_device_buffer_get_ptr(vsigma_d, INT(vsigma_d%size), vsigma_p)
    2001              :       CALL libxc_device_buffer_get_ptr(vlapl_d, INT(vlapl_d%size), vlapl_p)
    2002              :       CALL libxc_device_buffer_get_ptr(vtau_d, INT(vtau_d%size), vtau_p)
    2003              :       CALL libxc_device_buffer_get_ptr(v2rho2_d, INT(v2rho2_d%size), v2rho2_p)
    2004              :       CALL libxc_device_buffer_get_ptr(v2rhosigma_d, INT(v2rhosigma_d%size), v2rhosigma_p)
    2005              :       CALL libxc_device_buffer_get_ptr(v2rholapl_d, INT(v2rholapl_d%size), v2rholapl_p)
    2006              :       CALL libxc_device_buffer_get_ptr(v2rhotau_d, INT(v2rhotau_d%size), v2rhotau_p)
    2007              :       CALL libxc_device_buffer_get_ptr(v2sigma2_d, INT(v2sigma2_d%size), v2sigma2_p)
    2008              :       CALL libxc_device_buffer_get_ptr(v2sigmalapl_d, INT(v2sigmalapl_d%size), v2sigmalapl_p)
    2009              :       CALL libxc_device_buffer_get_ptr(v2sigmatau_d, INT(v2sigmatau_d%size), v2sigmatau_p)
    2010              :       CALL libxc_device_buffer_get_ptr(v2lapl2_d, INT(v2lapl2_d%size), v2lapl2_p)
    2011              :       CALL libxc_device_buffer_get_ptr(v2lapltau_d, INT(v2lapltau_d%size), v2lapltau_p)
    2012              :       CALL libxc_device_buffer_get_ptr(v2tau2_d, INT(v2tau2_d%size), v2tau2_p)
    2013              : 
    2014              :       CALL xc_f03_mgga_exc_vxc_fxc(func, np, rho_p, sigma_p, lapl_p, tau_p, &
    2015              :                                    exc_p, vrho_p, vsigma_p, vlapl_p, vtau_p, &
    2016              :                                    v2rho2_p, v2rhosigma_p, v2rholapl_p, &
    2017              :                                    v2rhotau_p, v2sigma2_p, v2sigmalapl_p, &
    2018              :                                    v2sigmatau_p, v2lapl2_p, v2lapltau_p, v2tau2_p)
    2019              :    END SUBROUTINE libxc_mgga_exc_vxc_fxc_device
    2020              : 
    2021              : ! **************************************************************************************************
    2022              : !> \brief MGGA vxc and fxc on device buffers.
    2023              : !> \param func ...
    2024              : !> \param rho_d ...
    2025              : !> \param sigma_d ...
    2026              : !> \param lapl_d ...
    2027              : !> \param tau_d ...
    2028              : !> \param vrho_d ...
    2029              : !> \param vsigma_d ...
    2030              : !> \param vlapl_d ...
    2031              : !> \param vtau_d ...
    2032              : !> \param v2rho2_d ...
    2033              : !> \param v2rhosigma_d ...
    2034              : !> \param v2rholapl_d ...
    2035              : !> \param v2rhotau_d ...
    2036              : !> \param v2sigma2_d ...
    2037              : !> \param v2sigmalapl_d ...
    2038              : !> \param v2sigmatau_d ...
    2039              : !> \param v2lapl2_d ...
    2040              : !> \param v2lapltau_d ...
    2041              : !> \param v2tau2_d ...
    2042              : !> \param np ...
    2043              : ! **************************************************************************************************
    2044              :    SUBROUTINE libxc_mgga_vxc_fxc_device(func, rho_d, sigma_d, lapl_d, tau_d, vrho_d, &
    2045              :                                         vsigma_d, vlapl_d, vtau_d, v2rho2_d, &
    2046              :                                         v2rhosigma_d, v2rholapl_d, v2rhotau_d, v2sigma2_d, &
    2047              :                                         v2sigmalapl_d, v2sigmatau_d, v2lapl2_d, v2lapltau_d, &
    2048              :                                         v2tau2_d, np)
    2049              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    2050              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    2051              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: rho_d, sigma_d, lapl_d, tau_d
    2052              :       TYPE(libxc_device_buffer_type), INTENT(INOUT) :: vrho_d, vsigma_d, vlapl_d, vtau_d, &
    2053              :                                          v2rho2_d, v2rhosigma_d, v2rholapl_d, v2rhotau_d, v2sigma2_d, v2sigmalapl_d, v2sigmatau_d, &
    2054              :                                                        v2lapl2_d, v2lapltau_d, v2tau2_d
    2055              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    2056              : 
    2057              :       REAL(KIND=dp), DIMENSION(:), POINTER :: lapl_p, rho_p, sigma_p, tau_p, v2lapl2_p, &
    2058              :                                           v2lapltau_p, v2rho2_p, v2rholapl_p, v2rhosigma_p, v2rhotau_p, v2sigma2_p, v2sigmalapl_p, &
    2059              :                                               v2sigmatau_p, v2tau2_p, vlapl_p, vrho_p, vsigma_p, vtau_p
    2060              : 
    2061              :       CALL libxc_device_buffer_get_ptr(rho_d, INT(rho_d%size), rho_p)
    2062              :       CALL libxc_device_buffer_get_ptr(sigma_d, INT(sigma_d%size), sigma_p)
    2063              :       CALL libxc_device_buffer_get_ptr(lapl_d, INT(lapl_d%size), lapl_p)
    2064              :       CALL libxc_device_buffer_get_ptr(tau_d, INT(tau_d%size), tau_p)
    2065              :       CALL libxc_device_buffer_get_ptr(vrho_d, INT(vrho_d%size), vrho_p)
    2066              :       CALL libxc_device_buffer_get_ptr(vsigma_d, INT(vsigma_d%size), vsigma_p)
    2067              :       CALL libxc_device_buffer_get_ptr(vlapl_d, INT(vlapl_d%size), vlapl_p)
    2068              :       CALL libxc_device_buffer_get_ptr(vtau_d, INT(vtau_d%size), vtau_p)
    2069              :       CALL libxc_device_buffer_get_ptr(v2rho2_d, INT(v2rho2_d%size), v2rho2_p)
    2070              :       CALL libxc_device_buffer_get_ptr(v2rhosigma_d, INT(v2rhosigma_d%size), v2rhosigma_p)
    2071              :       CALL libxc_device_buffer_get_ptr(v2rholapl_d, INT(v2rholapl_d%size), v2rholapl_p)
    2072              :       CALL libxc_device_buffer_get_ptr(v2rhotau_d, INT(v2rhotau_d%size), v2rhotau_p)
    2073              :       CALL libxc_device_buffer_get_ptr(v2sigma2_d, INT(v2sigma2_d%size), v2sigma2_p)
    2074              :       CALL libxc_device_buffer_get_ptr(v2sigmalapl_d, INT(v2sigmalapl_d%size), v2sigmalapl_p)
    2075              :       CALL libxc_device_buffer_get_ptr(v2sigmatau_d, INT(v2sigmatau_d%size), v2sigmatau_p)
    2076              :       CALL libxc_device_buffer_get_ptr(v2lapl2_d, INT(v2lapl2_d%size), v2lapl2_p)
    2077              :       CALL libxc_device_buffer_get_ptr(v2lapltau_d, INT(v2lapltau_d%size), v2lapltau_p)
    2078              :       CALL libxc_device_buffer_get_ptr(v2tau2_d, INT(v2tau2_d%size), v2tau2_p)
    2079              : 
    2080              :       CALL xc_f03_mgga_vxc_fxc(func, np, rho_p, sigma_p, lapl_p, tau_p, &
    2081              :                                vrho_p, vsigma_p, vlapl_p, vtau_p, &
    2082              :                                v2rho2_p, v2rhosigma_p, v2rholapl_p, &
    2083              :                                v2rhotau_p, v2sigma2_p, v2sigmalapl_p, &
    2084              :                                v2sigmatau_p, v2lapl2_p, v2lapltau_p, v2tau2_p)
    2085              :    END SUBROUTINE libxc_mgga_vxc_fxc_device
    2086              : 
    2087              : ! **************************************************************************************************
    2088              : !> \brief MGGA exc, vxc, fxc and kxc on device buffers.
    2089              : !> \param func ...
    2090              : !> \param rho_d ...
    2091              : !> \param sigma_d ...
    2092              : !> \param lapl_d ...
    2093              : !> \param tau_d ...
    2094              : !> \param exc_d ...
    2095              : !> \param vrho_d ...
    2096              : !> \param vsigma_d ...
    2097              : !> \param vlapl_d ...
    2098              : !> \param vtau_d ...
    2099              : !> \param v2rho2_d ...
    2100              : !> \param v2rhosigma_d ...
    2101              : !> \param v2rholapl_d ...
    2102              : !> \param v2rhotau_d ...
    2103              : !> \param v2sigma2_d ...
    2104              : !> \param v2sigmalapl_d ...
    2105              : !> \param v2sigmatau_d ...
    2106              : !> \param v2lapl2_d ...
    2107              : !> \param v2lapltau_d ...
    2108              : !> \param v2tau2_d ...
    2109              : !> \param v3rho3_d ...
    2110              : !> \param v3rho2sigma_d ...
    2111              : !> \param v3rho2lapl_d ...
    2112              : !> \param v3rho2tau_d ...
    2113              : !> \param v3rhosigma2_d ...
    2114              : !> \param v3rhosigmalapl_d ...
    2115              : !> \param v3rhosigmatau_d ...
    2116              : !> \param v3rholapl2_d ...
    2117              : !> \param v3rholapltau_d ...
    2118              : !> \param v3rhotau2_d ...
    2119              : !> \param v3sigma3_d ...
    2120              : !> \param v3sigma2lapl_d ...
    2121              : !> \param v3sigma2tau_d ...
    2122              : !> \param v3sigmalapl2_d ...
    2123              : !> \param v3sigmalapltau_d ...
    2124              : !> \param v3sigmatau2_d ...
    2125              : !> \param v3lapl3_d ...
    2126              : !> \param v3lapl2tau_d ...
    2127              : !> \param v3lapltau2_d ...
    2128              : !> \param v3tau3_d ...
    2129              : !> \param np ...
    2130              : ! **************************************************************************************************
    2131              :    SUBROUTINE libxc_mgga_exc_vxc_fxc_kxc_device(func, rho_d, sigma_d, lapl_d, tau_d, exc_d, &
    2132              :                                                 vrho_d, vsigma_d, vlapl_d, vtau_d, v2rho2_d, &
    2133              :                                                 v2rhosigma_d, v2rholapl_d, v2rhotau_d, v2sigma2_d, &
    2134              :                                                 v2sigmalapl_d, v2sigmatau_d, v2lapl2_d, v2lapltau_d, &
    2135              :                                                 v2tau2_d, v3rho3_d, v3rho2sigma_d, v3rho2lapl_d, &
    2136              :                                                 v3rho2tau_d, v3rhosigma2_d, v3rhosigmalapl_d, &
    2137              :                                                 v3rhosigmatau_d, v3rholapl2_d, v3rholapltau_d, &
    2138              :                                                 v3rhotau2_d, v3sigma3_d, v3sigma2lapl_d, v3sigma2tau_d, &
    2139              :                                                 v3sigmalapl2_d, v3sigmalapltau_d, v3sigmatau2_d, &
    2140              :                                                 v3lapl3_d, v3lapl2tau_d, v3lapltau2_d, v3tau3_d, np)
    2141              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    2142              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    2143              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: rho_d, sigma_d, lapl_d, tau_d
    2144              :       TYPE(libxc_device_buffer_type), INTENT(INOUT) :: exc_d, vrho_d, vsigma_d, vlapl_d, vtau_d, &
    2145              :                                          v2rho2_d, v2rhosigma_d, v2rholapl_d, v2rhotau_d, v2sigma2_d, v2sigmalapl_d, v2sigmatau_d, &
    2146              :                                              v2lapl2_d, v2lapltau_d, v2tau2_d, v3rho3_d, v3rho2sigma_d, v3rho2lapl_d, v3rho2tau_d, &
    2147              :                                                    v3rhosigma2_d, v3rhosigmalapl_d, v3rhosigmatau_d, v3rholapl2_d, v3rholapltau_d, &
    2148              :                                          v3rhotau2_d, v3sigma3_d, v3sigma2lapl_d, v3sigma2tau_d, v3sigmalapl2_d, v3sigmalapltau_d, &
    2149              :                                                        v3sigmatau2_d, v3lapl3_d, v3lapl2tau_d, v3lapltau2_d, v3tau3_d
    2150              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    2151              : 
    2152              :       REAL(KIND=dp), DIMENSION(:), POINTER :: exc_p, lapl_p, rho_p, sigma_p, tau_p, v2lapl2_p, &
    2153              :                                           v2lapltau_p, v2rho2_p, v2rholapl_p, v2rhosigma_p, v2rhotau_p, v2sigma2_p, v2sigmalapl_p, &
    2154              :                                               v2sigmatau_p, v2tau2_p, v3lapl2tau_p, v3lapl3_p, v3lapltau2_p, v3rho2lapl_p, &
    2155              :                                               v3rho2sigma_p, v3rho2tau_p, v3rho3_p, v3rholapl2_p, v3rholapltau_p, v3rhosigma2_p, &
    2156              :                                               v3rhosigmalapl_p, v3rhosigmatau_p, v3rhotau2_p, v3sigma2lapl_p, v3sigma2tau_p, &
    2157              :                                            v3sigma3_p, v3sigmalapl2_p, v3sigmalapltau_p, v3sigmatau2_p, v3tau3_p, vlapl_p, vrho_p, &
    2158              :                                               vsigma_p, vtau_p
    2159              : 
    2160              :       CALL libxc_device_buffer_get_ptr(rho_d, INT(rho_d%size), rho_p)
    2161              :       CALL libxc_device_buffer_get_ptr(sigma_d, INT(sigma_d%size), sigma_p)
    2162              :       CALL libxc_device_buffer_get_ptr(lapl_d, INT(lapl_d%size), lapl_p)
    2163              :       CALL libxc_device_buffer_get_ptr(tau_d, INT(tau_d%size), tau_p)
    2164              :       CALL libxc_device_buffer_get_ptr(exc_d, INT(exc_d%size), exc_p)
    2165              :       CALL libxc_device_buffer_get_ptr(vrho_d, INT(vrho_d%size), vrho_p)
    2166              :       CALL libxc_device_buffer_get_ptr(vsigma_d, INT(vsigma_d%size), vsigma_p)
    2167              :       CALL libxc_device_buffer_get_ptr(vlapl_d, INT(vlapl_d%size), vlapl_p)
    2168              :       CALL libxc_device_buffer_get_ptr(vtau_d, INT(vtau_d%size), vtau_p)
    2169              :       CALL libxc_device_buffer_get_ptr(v2rho2_d, INT(v2rho2_d%size), v2rho2_p)
    2170              :       CALL libxc_device_buffer_get_ptr(v2rhosigma_d, INT(v2rhosigma_d%size), v2rhosigma_p)
    2171              :       CALL libxc_device_buffer_get_ptr(v2rholapl_d, INT(v2rholapl_d%size), v2rholapl_p)
    2172              :       CALL libxc_device_buffer_get_ptr(v2rhotau_d, INT(v2rhotau_d%size), v2rhotau_p)
    2173              :       CALL libxc_device_buffer_get_ptr(v2sigma2_d, INT(v2sigma2_d%size), v2sigma2_p)
    2174              :       CALL libxc_device_buffer_get_ptr(v2sigmalapl_d, INT(v2sigmalapl_d%size), v2sigmalapl_p)
    2175              :       CALL libxc_device_buffer_get_ptr(v2sigmatau_d, INT(v2sigmatau_d%size), v2sigmatau_p)
    2176              :       CALL libxc_device_buffer_get_ptr(v2lapl2_d, INT(v2lapl2_d%size), v2lapl2_p)
    2177              :       CALL libxc_device_buffer_get_ptr(v2lapltau_d, INT(v2lapltau_d%size), v2lapltau_p)
    2178              :       CALL libxc_device_buffer_get_ptr(v2tau2_d, INT(v2tau2_d%size), v2tau2_p)
    2179              :       CALL libxc_device_buffer_get_ptr(v3rho3_d, INT(v3rho3_d%size), v3rho3_p)
    2180              :       CALL libxc_device_buffer_get_ptr(v3rho2sigma_d, INT(v3rho2sigma_d%size), v3rho2sigma_p)
    2181              :       CALL libxc_device_buffer_get_ptr(v3rho2lapl_d, INT(v3rho2lapl_d%size), v3rho2lapl_p)
    2182              :       CALL libxc_device_buffer_get_ptr(v3rho2tau_d, INT(v3rho2tau_d%size), v3rho2tau_p)
    2183              :       CALL libxc_device_buffer_get_ptr(v3rhosigma2_d, INT(v3rhosigma2_d%size), v3rhosigma2_p)
    2184              :       CALL libxc_device_buffer_get_ptr(v3rhosigmalapl_d, INT(v3rhosigmalapl_d%size), v3rhosigmalapl_p)
    2185              :       CALL libxc_device_buffer_get_ptr(v3rhosigmatau_d, INT(v3rhosigmatau_d%size), v3rhosigmatau_p)
    2186              :       CALL libxc_device_buffer_get_ptr(v3rholapl2_d, INT(v3rholapl2_d%size), v3rholapl2_p)
    2187              :       CALL libxc_device_buffer_get_ptr(v3rholapltau_d, INT(v3rholapltau_d%size), v3rholapltau_p)
    2188              :       CALL libxc_device_buffer_get_ptr(v3rhotau2_d, INT(v3rhotau2_d%size), v3rhotau2_p)
    2189              :       CALL libxc_device_buffer_get_ptr(v3sigma3_d, INT(v3sigma3_d%size), v3sigma3_p)
    2190              :       CALL libxc_device_buffer_get_ptr(v3sigma2lapl_d, INT(v3sigma2lapl_d%size), v3sigma2lapl_p)
    2191              :       CALL libxc_device_buffer_get_ptr(v3sigma2tau_d, INT(v3sigma2tau_d%size), v3sigma2tau_p)
    2192              :       CALL libxc_device_buffer_get_ptr(v3sigmalapl2_d, INT(v3sigmalapl2_d%size), v3sigmalapl2_p)
    2193              :       CALL libxc_device_buffer_get_ptr(v3sigmalapltau_d, INT(v3sigmalapltau_d%size), v3sigmalapltau_p)
    2194              :       CALL libxc_device_buffer_get_ptr(v3sigmatau2_d, INT(v3sigmatau2_d%size), v3sigmatau2_p)
    2195              :       CALL libxc_device_buffer_get_ptr(v3lapl3_d, INT(v3lapl3_d%size), v3lapl3_p)
    2196              :       CALL libxc_device_buffer_get_ptr(v3lapl2tau_d, INT(v3lapl2tau_d%size), v3lapl2tau_p)
    2197              :       CALL libxc_device_buffer_get_ptr(v3lapltau2_d, INT(v3lapltau2_d%size), v3lapltau2_p)
    2198              :       CALL libxc_device_buffer_get_ptr(v3tau3_d, INT(v3tau3_d%size), v3tau3_p)
    2199              : 
    2200              :       CALL xc_f03_mgga_exc_vxc_fxc_kxc(func, np, rho_p, sigma_p, lapl_p, tau_p, &
    2201              :                                        exc_p, vrho_p, vsigma_p, vlapl_p, vtau_p, &
    2202              :                                        v2rho2_p, v2rhosigma_p, v2rholapl_p, &
    2203              :                                        v2rhotau_p, v2sigma2_p, v2sigmalapl_p, &
    2204              :                                        v2sigmatau_p, v2lapl2_p, v2lapltau_p, v2tau2_p, &
    2205              :                                        v3rho3_p, v3rho2sigma_p, v3rho2lapl_p, v3rho2tau_p, &
    2206              :                                        v3rhosigma2_p, v3rhosigmalapl_p, v3rhosigmatau_p, &
    2207              :                                        v3rholapl2_p, v3rholapltau_p, v3rhotau2_p, &
    2208              :                                        v3sigma3_p, v3sigma2lapl_p, v3sigma2tau_p, &
    2209              :                                        v3sigmalapl2_p, v3sigmalapltau_p, v3sigmatau2_p, &
    2210              :                                        v3lapl3_p, v3lapl2tau_p, v3lapltau2_p, v3tau3_p)
    2211              :    END SUBROUTINE libxc_mgga_exc_vxc_fxc_kxc_device
    2212              : 
    2213              : ! **************************************************************************************************
    2214              : !> \brief MGGA vxc, fxc and kxc on device buffers.
    2215              : !> \param func ...
    2216              : !> \param rho_d ...
    2217              : !> \param sigma_d ...
    2218              : !> \param lapl_d ...
    2219              : !> \param tau_d ...
    2220              : !> \param vrho_d ...
    2221              : !> \param vsigma_d ...
    2222              : !> \param vlapl_d ...
    2223              : !> \param vtau_d ...
    2224              : !> \param v2rho2_d ...
    2225              : !> \param v2rhosigma_d ...
    2226              : !> \param v2rholapl_d ...
    2227              : !> \param v2rhotau_d ...
    2228              : !> \param v2sigma2_d ...
    2229              : !> \param v2sigmalapl_d ...
    2230              : !> \param v2sigmatau_d ...
    2231              : !> \param v2lapl2_d ...
    2232              : !> \param v2lapltau_d ...
    2233              : !> \param v2tau2_d ...
    2234              : !> \param v3rho3_d ...
    2235              : !> \param v3rho2sigma_d ...
    2236              : !> \param v3rho2lapl_d ...
    2237              : !> \param v3rho2tau_d ...
    2238              : !> \param v3rhosigma2_d ...
    2239              : !> \param v3rhosigmalapl_d ...
    2240              : !> \param v3rhosigmatau_d ...
    2241              : !> \param v3rholapl2_d ...
    2242              : !> \param v3rholapltau_d ...
    2243              : !> \param v3rhotau2_d ...
    2244              : !> \param v3sigma3_d ...
    2245              : !> \param v3sigma2lapl_d ...
    2246              : !> \param v3sigma2tau_d ...
    2247              : !> \param v3sigmalapl2_d ...
    2248              : !> \param v3sigmalapltau_d ...
    2249              : !> \param v3sigmatau2_d ...
    2250              : !> \param v3lapl3_d ...
    2251              : !> \param v3lapl2tau_d ...
    2252              : !> \param v3lapltau2_d ...
    2253              : !> \param v3tau3_d ...
    2254              : !> \param np ...
    2255              : ! **************************************************************************************************
    2256              :    SUBROUTINE libxc_mgga_vxc_fxc_kxc_device(func, rho_d, sigma_d, lapl_d, tau_d, vrho_d, &
    2257              :                                             vsigma_d, vlapl_d, vtau_d, v2rho2_d, &
    2258              :                                             v2rhosigma_d, v2rholapl_d, v2rhotau_d, v2sigma2_d, &
    2259              :                                             v2sigmalapl_d, v2sigmatau_d, v2lapl2_d, v2lapltau_d, &
    2260              :                                             v2tau2_d, v3rho3_d, v3rho2sigma_d, v3rho2lapl_d, &
    2261              :                                             v3rho2tau_d, v3rhosigma2_d, v3rhosigmalapl_d, &
    2262              :                                             v3rhosigmatau_d, v3rholapl2_d, v3rholapltau_d, &
    2263              :                                             v3rhotau2_d, v3sigma3_d, v3sigma2lapl_d, v3sigma2tau_d, &
    2264              :                                             v3sigmalapl2_d, v3sigmalapltau_d, v3sigmatau2_d, &
    2265              :                                             v3lapl3_d, v3lapl2tau_d, v3lapltau2_d, v3tau3_d, np)
    2266              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    2267              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    2268              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: rho_d, sigma_d, lapl_d, tau_d
    2269              :       TYPE(libxc_device_buffer_type), INTENT(INOUT) :: vrho_d, vsigma_d, vlapl_d, vtau_d, &
    2270              :                                          v2rho2_d, v2rhosigma_d, v2rholapl_d, v2rhotau_d, v2sigma2_d, v2sigmalapl_d, v2sigmatau_d, &
    2271              :                                              v2lapl2_d, v2lapltau_d, v2tau2_d, v3rho3_d, v3rho2sigma_d, v3rho2lapl_d, v3rho2tau_d, &
    2272              :                                                    v3rhosigma2_d, v3rhosigmalapl_d, v3rhosigmatau_d, v3rholapl2_d, v3rholapltau_d, &
    2273              :                                          v3rhotau2_d, v3sigma3_d, v3sigma2lapl_d, v3sigma2tau_d, v3sigmalapl2_d, v3sigmalapltau_d, &
    2274              :                                                        v3sigmatau2_d, v3lapl3_d, v3lapl2tau_d, v3lapltau2_d, v3tau3_d
    2275              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    2276              : 
    2277              :       REAL(KIND=dp), DIMENSION(:), POINTER :: lapl_p, rho_p, sigma_p, tau_p, v2lapl2_p, &
    2278              :                                           v2lapltau_p, v2rho2_p, v2rholapl_p, v2rhosigma_p, v2rhotau_p, v2sigma2_p, v2sigmalapl_p, &
    2279              :                                               v2sigmatau_p, v2tau2_p, v3lapl2tau_p, v3lapl3_p, v3lapltau2_p, v3rho2lapl_p, &
    2280              :                                               v3rho2sigma_p, v3rho2tau_p, v3rho3_p, v3rholapl2_p, v3rholapltau_p, v3rhosigma2_p, &
    2281              :                                               v3rhosigmalapl_p, v3rhosigmatau_p, v3rhotau2_p, v3sigma2lapl_p, v3sigma2tau_p, &
    2282              :                                            v3sigma3_p, v3sigmalapl2_p, v3sigmalapltau_p, v3sigmatau2_p, v3tau3_p, vlapl_p, vrho_p, &
    2283              :                                               vsigma_p, vtau_p
    2284              : 
    2285              :       CALL libxc_device_buffer_get_ptr(rho_d, INT(rho_d%size), rho_p)
    2286              :       CALL libxc_device_buffer_get_ptr(sigma_d, INT(sigma_d%size), sigma_p)
    2287              :       CALL libxc_device_buffer_get_ptr(lapl_d, INT(lapl_d%size), lapl_p)
    2288              :       CALL libxc_device_buffer_get_ptr(tau_d, INT(tau_d%size), tau_p)
    2289              :       CALL libxc_device_buffer_get_ptr(vrho_d, INT(vrho_d%size), vrho_p)
    2290              :       CALL libxc_device_buffer_get_ptr(vsigma_d, INT(vsigma_d%size), vsigma_p)
    2291              :       CALL libxc_device_buffer_get_ptr(vlapl_d, INT(vlapl_d%size), vlapl_p)
    2292              :       CALL libxc_device_buffer_get_ptr(vtau_d, INT(vtau_d%size), vtau_p)
    2293              :       CALL libxc_device_buffer_get_ptr(v2rho2_d, INT(v2rho2_d%size), v2rho2_p)
    2294              :       CALL libxc_device_buffer_get_ptr(v2rhosigma_d, INT(v2rhosigma_d%size), v2rhosigma_p)
    2295              :       CALL libxc_device_buffer_get_ptr(v2rholapl_d, INT(v2rholapl_d%size), v2rholapl_p)
    2296              :       CALL libxc_device_buffer_get_ptr(v2rhotau_d, INT(v2rhotau_d%size), v2rhotau_p)
    2297              :       CALL libxc_device_buffer_get_ptr(v2sigma2_d, INT(v2sigma2_d%size), v2sigma2_p)
    2298              :       CALL libxc_device_buffer_get_ptr(v2sigmalapl_d, INT(v2sigmalapl_d%size), v2sigmalapl_p)
    2299              :       CALL libxc_device_buffer_get_ptr(v2sigmatau_d, INT(v2sigmatau_d%size), v2sigmatau_p)
    2300              :       CALL libxc_device_buffer_get_ptr(v2lapl2_d, INT(v2lapl2_d%size), v2lapl2_p)
    2301              :       CALL libxc_device_buffer_get_ptr(v2lapltau_d, INT(v2lapltau_d%size), v2lapltau_p)
    2302              :       CALL libxc_device_buffer_get_ptr(v2tau2_d, INT(v2tau2_d%size), v2tau2_p)
    2303              :       CALL libxc_device_buffer_get_ptr(v3rho3_d, INT(v3rho3_d%size), v3rho3_p)
    2304              :       CALL libxc_device_buffer_get_ptr(v3rho2sigma_d, INT(v3rho2sigma_d%size), v3rho2sigma_p)
    2305              :       CALL libxc_device_buffer_get_ptr(v3rho2lapl_d, INT(v3rho2lapl_d%size), v3rho2lapl_p)
    2306              :       CALL libxc_device_buffer_get_ptr(v3rho2tau_d, INT(v3rho2tau_d%size), v3rho2tau_p)
    2307              :       CALL libxc_device_buffer_get_ptr(v3rhosigma2_d, INT(v3rhosigma2_d%size), v3rhosigma2_p)
    2308              :       CALL libxc_device_buffer_get_ptr(v3rhosigmalapl_d, INT(v3rhosigmalapl_d%size), v3rhosigmalapl_p)
    2309              :       CALL libxc_device_buffer_get_ptr(v3rhosigmatau_d, INT(v3rhosigmatau_d%size), v3rhosigmatau_p)
    2310              :       CALL libxc_device_buffer_get_ptr(v3rholapl2_d, INT(v3rholapl2_d%size), v3rholapl2_p)
    2311              :       CALL libxc_device_buffer_get_ptr(v3rholapltau_d, INT(v3rholapltau_d%size), v3rholapltau_p)
    2312              :       CALL libxc_device_buffer_get_ptr(v3rhotau2_d, INT(v3rhotau2_d%size), v3rhotau2_p)
    2313              :       CALL libxc_device_buffer_get_ptr(v3sigma3_d, INT(v3sigma3_d%size), v3sigma3_p)
    2314              :       CALL libxc_device_buffer_get_ptr(v3sigma2lapl_d, INT(v3sigma2lapl_d%size), v3sigma2lapl_p)
    2315              :       CALL libxc_device_buffer_get_ptr(v3sigma2tau_d, INT(v3sigma2tau_d%size), v3sigma2tau_p)
    2316              :       CALL libxc_device_buffer_get_ptr(v3sigmalapl2_d, INT(v3sigmalapl2_d%size), v3sigmalapl2_p)
    2317              :       CALL libxc_device_buffer_get_ptr(v3sigmalapltau_d, INT(v3sigmalapltau_d%size), v3sigmalapltau_p)
    2318              :       CALL libxc_device_buffer_get_ptr(v3sigmatau2_d, INT(v3sigmatau2_d%size), v3sigmatau2_p)
    2319              :       CALL libxc_device_buffer_get_ptr(v3lapl3_d, INT(v3lapl3_d%size), v3lapl3_p)
    2320              :       CALL libxc_device_buffer_get_ptr(v3lapl2tau_d, INT(v3lapl2tau_d%size), v3lapl2tau_p)
    2321              :       CALL libxc_device_buffer_get_ptr(v3lapltau2_d, INT(v3lapltau2_d%size), v3lapltau2_p)
    2322              :       CALL libxc_device_buffer_get_ptr(v3tau3_d, INT(v3tau3_d%size), v3tau3_p)
    2323              : 
    2324              :       CALL xc_f03_mgga_vxc_fxc_kxc(func, np, rho_p, sigma_p, lapl_p, tau_p, &
    2325              :                                    vrho_p, vsigma_p, vlapl_p, vtau_p, &
    2326              :                                    v2rho2_p, v2rhosigma_p, v2rholapl_p, &
    2327              :                                    v2rhotau_p, v2sigma2_p, v2sigmalapl_p, &
    2328              :                                    v2sigmatau_p, v2lapl2_p, v2lapltau_p, v2tau2_p, &
    2329              :                                    v3rho3_p, v3rho2sigma_p, v3rho2lapl_p, v3rho2tau_p, &
    2330              :                                    v3rhosigma2_p, v3rhosigmalapl_p, v3rhosigmatau_p, &
    2331              :                                    v3rholapl2_p, v3rholapltau_p, v3rhotau2_p, &
    2332              :                                    v3sigma3_p, v3sigma2lapl_p, v3sigma2tau_p, &
    2333              :                                    v3sigmalapl2_p, v3sigmalapltau_p, v3sigmatau2_p, &
    2334              :                                    v3lapl3_p, v3lapl2tau_p, v3lapltau2_p, v3tau3_p)
    2335              :    END SUBROUTINE libxc_mgga_vxc_fxc_kxc_device
    2336              : 
    2337              : ! **************************************************************************************************
    2338              : !> \brief MGGA vxc on device buffers.
    2339              : !> \param func ...
    2340              : !> \param rho_d ...
    2341              : !> \param sigma_d ...
    2342              : !> \param lapl_d ...
    2343              : !> \param tau_d ...
    2344              : !> \param vrho_d ...
    2345              : !> \param vsigma_d ...
    2346              : !> \param vlapl_d ...
    2347              : !> \param vtau_d ...
    2348              : !> \param np ...
    2349              : ! **************************************************************************************************
    2350              :    SUBROUTINE libxc_mgga_vxc_device(func, rho_d, sigma_d, lapl_d, tau_d, vrho_d, vsigma_d, vlapl_d, vtau_d, np)
    2351              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    2352              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    2353              :       TYPE(libxc_device_buffer_type), INTENT(IN)         :: rho_d, sigma_d, lapl_d, tau_d
    2354              :       TYPE(libxc_device_buffer_type), INTENT(INOUT)      :: vrho_d, vsigma_d, vlapl_d, vtau_d
    2355              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    2356              : 
    2357              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: lapl_p, rho_p, sigma_p, tau_p, vlapl_p, &
    2358              :                                                             vrho_p, vsigma_p, vtau_p
    2359              : 
    2360              :       CALL libxc_device_buffer_get_ptr(rho_d, INT(rho_d%size), rho_p)
    2361              :       CALL libxc_device_buffer_get_ptr(sigma_d, INT(sigma_d%size), sigma_p)
    2362              :       CALL libxc_device_buffer_get_ptr(lapl_d, INT(lapl_d%size), lapl_p)
    2363              :       CALL libxc_device_buffer_get_ptr(tau_d, INT(tau_d%size), tau_p)
    2364              :       CALL libxc_device_buffer_get_ptr(vrho_d, INT(vrho_d%size), vrho_p)
    2365              :       CALL libxc_device_buffer_get_ptr(vsigma_d, INT(vsigma_d%size), vsigma_p)
    2366              :       CALL libxc_device_buffer_get_ptr(vlapl_d, INT(vlapl_d%size), vlapl_p)
    2367              :       CALL libxc_device_buffer_get_ptr(vtau_d, INT(vtau_d%size), vtau_p)
    2368              : 
    2369              :       CALL xc_f03_mgga_vxc(func, np, rho_p, sigma_p, lapl_p, tau_p, vrho_p, vsigma_p, vlapl_p, vtau_p)
    2370              :    END SUBROUTINE libxc_mgga_vxc_device
    2371              : 
    2372              : #else
    2373              : ! **************************************************************************************************
    2374              : !> \brief CPU-only build: a worker never carries device buffers. The device
    2375              : !>        entry points libxc_worker_eval calls are compiled as no-ops/aborts so
    2376              : !>        that no __OFFLOAD guards are needed above; the runtime backend
    2377              : !>        selection prevents them from ever being reached.
    2378              : ! **************************************************************************************************
    2379              :    SUBROUTINE libxc_worker_device_alloc(worker, family, pol, nl, np, ns, n, grow_only)
    2380              :       TYPE(libxc_worker_type), INTENT(INOUT)             :: worker
    2381              :       INTEGER, INTENT(IN)                                :: family, nl, np, ns, n
    2382              :       LOGICAL, INTENT(IN)                                :: pol
    2383              :       LOGICAL, INTENT(IN), OPTIONAL                      :: grow_only
    2384              : 
    2385              :       MARK_USED(worker)
    2386              :       MARK_USED(family)
    2387              :       MARK_USED(pol)
    2388              :       MARK_USED(nl)
    2389              :       MARK_USED(np)
    2390              :       MARK_USED(ns)
    2391              :       MARK_USED(n)
    2392              :       MARK_USED(grow_only)
    2393              :    END SUBROUTINE libxc_worker_device_alloc
    2394              : 
    2395              :    SUBROUTINE libxc_worker_device_free(worker)
    2396              :       TYPE(libxc_worker_type), INTENT(INOUT)             :: worker
    2397              : 
    2398              :       MARK_USED(worker)
    2399              :    END SUBROUTINE libxc_worker_device_free
    2400              : 
    2401              : ! **************************************************************************************************
    2402              : !> \brief CPU-only build: the whole dispatch is a single abort. The runtime
    2403              : !>        backend selection can never route here.
    2404              : ! **************************************************************************************************
    2405              :    SUBROUTINE libxc_worker_eval_device(worker, family, grad_deriv, no_exc, np)
    2406              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    2407              :       TYPE(libxc_worker_type), INTENT(INOUT)             :: worker
    2408              :       INTEGER, INTENT(IN)                                :: family, grad_deriv
    2409              :       LOGICAL, INTENT(IN)                                :: no_exc
    2410              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    2411              : 
    2412              :       MARK_USED(worker)
    2413              :       MARK_USED(family)
    2414              :       MARK_USED(grad_deriv)
    2415              :       MARK_USED(no_exc)
    2416              :       MARK_USED(np)
    2417              :       CPABORT("libxc_worker_eval_device: device backend not compiled in.")
    2418              :    END SUBROUTINE libxc_worker_eval_device
    2419              : 
    2420              : ! **************************************************************************************************
    2421              : !> \brief CPU-only build: growing the device buffers is a no-op.
    2422              : ! **************************************************************************************************
    2423              :    SUBROUTINE libxc_worker_resize_cuda(worker, family, nspin, npoints)
    2424              :       TYPE(libxc_worker_type), INTENT(INOUT)             :: worker
    2425              :       INTEGER, INTENT(IN)                                :: family, nspin, npoints
    2426              : 
    2427              :       MARK_USED(worker)
    2428              :       MARK_USED(family)
    2429              :       MARK_USED(nspin)
    2430              :       MARK_USED(npoints)
    2431              :    END SUBROUTINE libxc_worker_resize_cuda
    2432              : #endif
    2433              : ! **************************************************************************************************
    2434              : !> \brief Natural family classification: whether a family carries the gradient
    2435              : !>        (GGA) and the kinetic-energy density/Laplacian (MGGA) variables.
    2436              : !> \param family LibXC functional family
    2437              : !> \param is_gga the family has sigma/gradient components
    2438              : !> \param is_mgga the family has tau/laplacian components
    2439              : !> \param where optional routine name used in the abort message
    2440              : ! **************************************************************************************************
    2441              :    SUBROUTINE libxc_family_flags(family, is_gga, is_mgga, where)
    2442              :       INTEGER, INTENT(IN)                                :: family
    2443              :       LOGICAL, INTENT(OUT)                               :: is_gga, is_mgga
    2444              :       CHARACTER(LEN=*), INTENT(IN), OPTIONAL             :: where
    2445              : 
    2446              :       SELECT CASE (family)
    2447              :       CASE (XC_FAMILY_LDA, XC_FAMILY_HYB_LDA)
    2448              :          is_gga = .FALSE.
    2449              :          is_mgga = .FALSE.
    2450              :       CASE (XC_FAMILY_GGA, XC_FAMILY_HYB_GGA)
    2451              :          is_gga = .TRUE.
    2452              :          is_mgga = .FALSE.
    2453              :       CASE (XC_FAMILY_MGGA, XC_FAMILY_HYB_MGGA)
    2454              :          is_gga = .TRUE.
    2455              :          is_mgga = .TRUE.
    2456              :       CASE default
    2457              :          is_gga = .FALSE.
    2458              :          is_mgga = .FALSE.
    2459              :          IF (PRESENT(where)) THEN
    2460              :             CPABORT(TRIM(where)//": this XC_FAMILY is currently not supported.")
    2461              :          ELSE
    2462              :             CPABORT("libxc_family_flags: unsupported XC_FAMILY.")
    2463              :          END IF
    2464              :       END SELECT
    2465              :    END SUBROUTINE libxc_family_flags
    2466              : 
    2467              : ! **************************************************************************************************
    2468              : !> \brief Leading dimension (number of components per point) of the worker
    2469              : !>        buffers for a spin polarization, cf. the LibXC manual.
    2470              : !> \param nspin XC_UNPOLARIZED or XC_POLARIZED
    2471              : !> \param np number of rho-like components (rho, vrho, lapl, tau, vlapl, vtau)
    2472              : !> \param ns number of sigma-like components (sigma, vsigma, v2rho2, ...)
    2473              : !> \param nl number of rho-lapl/tau-like components (v2rholapl, v3rho3, ...)
    2474              : ! **************************************************************************************************
    2475              :    SUBROUTINE libxc_worker_dims(nspin, np, ns, nl)
    2476              :       INTEGER, INTENT(IN)                                :: nspin
    2477              :       INTEGER, INTENT(OUT)                               :: np, ns, nl
    2478              : 
    2479              :       IF (nspin == XC_POLARIZED) THEN
    2480              :          np = 2
    2481              :          ns = 3
    2482              :          nl = 4
    2483              :       ELSE
    2484              :          np = 1
    2485              :          ns = 1
    2486              :          nl = 1
    2487              :       END IF
    2488              :    END SUBROUTINE libxc_worker_dims
    2489              : 
    2490              : ! **************************************************************************************************
    2491              : !> \brief Aborts when a freshly evaluated block contains a NaN, if checking is on.
    2492              : !> \param worker the worker
    2493              : !> \param npoints number of points in this block
    2494              : !> \param grad_deriv derivative order requested
    2495              : !> \param no_exc functional does not provide the energy density
    2496              : !> \param family LibXC functional family
    2497              : ! **************************************************************************************************
    2498              :    SUBROUTINE libxc_worker_check_nan(worker, npoints, grad_deriv, no_exc, family)
    2499              :       TYPE(libxc_worker_type), INTENT(IN)                :: worker
    2500              :       INTEGER, INTENT(IN)                                :: npoints, grad_deriv
    2501              :       LOGICAL, INTENT(IN)                                :: no_exc
    2502              :       INTEGER, INTENT(IN)                                :: family
    2503              : 
    2504              :       CHARACTER(len=256)                                 :: message
    2505              :       LOGICAL                                            :: exc_has_nan, vrho_has_nan
    2506              : 
    2507              :       IF (.NOT. libxc_check_nan) RETURN
    2508              :       exc_has_nan = ANY(worker%exc(1:npoints) /= worker%exc(1:npoints))
    2509              :       vrho_has_nan = .FALSE.
    2510              :       IF (grad_deriv >= 1) THEN
    2511              :          vrho_has_nan = ANY(worker%vrho(:, 1:npoints) /= worker%vrho(:, 1:npoints))
    2512              :       END IF
    2513              :       IF (exc_has_nan .OR. vrho_has_nan) THEN
    2514              :          WRITE (message, '(A,I0,A,I0,A,L1,A,I0,A,L1,A,L1)') &
    2515              :             "NaN after device_to_host: family=", family, " grad_deriv=", grad_deriv, &
    2516              :             " no_exc=", no_exc, " nb=", npoints, &
    2517              :             " exc has NaN=", exc_has_nan, " vrho has NaN=", vrho_has_nan
    2518              :          CPABORT(TRIM(message))
    2519              :       END IF
    2520              :    END SUBROUTINE libxc_worker_check_nan
    2521              : 
    2522              : ! **************************************************************************************************
    2523              : !> \brief Evaluates one block of points for a worker, on the device when the GPU
    2524              : !>        backend is active and on the host otherwise.
    2525              : !> \param worker the worker holding the functional and the staging buffers
    2526              : !> \param family LibXC functional family
    2527              : !> \param nspin XC_UNPOLARIZED or XC_POLARIZED
    2528              : !> \param grad_deriv derivative order requested
    2529              : !> \param no_exc functional does not provide the energy density
    2530              : !> \param npoints number of points in this block; on the GPU path the whole grid
    2531              : !>        is one block, so this is also the full grid size
    2532              : !> \note The staged inputs (worker%rho/sigma/lapl/tau) must already be filled by
    2533              : !>       the caller; the outputs (worker%exc/vrho/...) are filled on return.
    2534              : ! **************************************************************************************************
    2535              :    SUBROUTINE libxc_worker_eval(worker, family, nspin, grad_deriv, no_exc, npoints)
    2536              :       TYPE(libxc_worker_type), INTENT(INOUT)             :: worker
    2537              :       INTEGER, INTENT(IN)                                :: family, nspin, grad_deriv, npoints
    2538              :       LOGICAL, INTENT(IN)                                :: no_exc
    2539              : 
    2540              :       INTEGER                                            :: nl, ns, np
    2541              :       INTEGER(KIND=C_SIZE_T)                             :: npts
    2542              :       LOGICAL                                            :: is_gga, is_mgga, pol
    2543              : 
    2544              :       CALL libxc_family_flags(family, is_gga, is_mgga)
    2545              :       CALL libxc_worker_dims(nspin, np, ns, nl)
    2546              :       pol = (nspin == XC_POLARIZED)
    2547              :       npts = INT(npoints, KIND=C_SIZE_T)
    2548              : 
    2549              :       ! CUDA's current device is thread-local; make sure every thread that runs
    2550              :       ! this block uses the rank's selected device. No-op without a device.
    2551              :       CALL libxc_activate_device()
    2552              : 
    2553              :       IF (libxc_is_gpu()) THEN
    2554              :          ! Copy the staged block to the worker's device buffers.
    2555              :          CALL libxc_worker_h2d(worker, libxc_dev_rho, worker%rho(1, 1), INT(np*npts))
    2556              :          IF (is_gga) THEN
    2557              :             CALL libxc_worker_h2d(worker, libxc_dev_sigma, worker%sigma(1, 1), INT(ns*npts))
    2558              :          END IF
    2559              :          IF (is_mgga) THEN
    2560              :             CALL libxc_worker_h2d(worker, libxc_dev_lapl, worker%lapl(1, 1), INT(np*npts))
    2561              :             CALL libxc_worker_h2d(worker, libxc_dev_tau, worker%tau(1, 1), INT(np*npts))
    2562              :          END IF
    2563              : 
    2564              :          ! One device call for the whole block; worker%exc is zeroed there if the
    2565              :          ! functional does not provide it.
    2566              :          CALL libxc_worker_eval_device(worker, family, grad_deriv, no_exc, npts)
    2567              : 
    2568              :          ! Issue all D2H copies first (async), then a single synchronize() covers
    2569              :          ! all of them, then read every result.
    2570              :          IF (.NOT. no_exc) THEN
    2571              :             CALL libxc_worker_d2h_issue(worker, libxc_dev_exc, npoints)
    2572              :          END IF
    2573              :          IF (grad_deriv >= 1) THEN
    2574              :             CALL libxc_worker_d2h_issue(worker, libxc_dev_vrho, np*npoints)
    2575              :             IF (is_gga) THEN
    2576              :                CALL libxc_worker_d2h_issue(worker, libxc_dev_vsigma, ns*npoints)
    2577              :             END IF
    2578              :             IF (is_mgga) THEN
    2579              :                CALL libxc_worker_d2h_issue(worker, libxc_dev_vlapl, np*npoints)
    2580              :                CALL libxc_worker_d2h_issue(worker, libxc_dev_vtau, np*npoints)
    2581              :             END IF
    2582              :          END IF
    2583              :          IF (grad_deriv >= 2) THEN
    2584              :             CALL libxc_worker_d2h_issue(worker, libxc_dev_v2rho2, ns*npoints)
    2585              :             IF (is_gga) THEN
    2586              :                CALL libxc_worker_d2h_issue(worker, libxc_dev_v2rhosigma, MERGE(6, 1, pol)*npoints)
    2587              :                CALL libxc_worker_d2h_issue(worker, libxc_dev_v2sigma2, MERGE(6, 1, pol)*npoints)
    2588              :             END IF
    2589              :             IF (is_mgga) THEN
    2590              :                CALL libxc_worker_d2h_issue(worker, libxc_dev_v2rholapl, nl*npoints)
    2591              :                CALL libxc_worker_d2h_issue(worker, libxc_dev_v2rhotau, nl*npoints)
    2592              :                CALL libxc_worker_d2h_issue(worker, libxc_dev_v2sigmalapl, MERGE(6, 1, pol)*npoints)
    2593              :                CALL libxc_worker_d2h_issue(worker, libxc_dev_v2sigmatau, MERGE(6, 1, pol)*npoints)
    2594              :                CALL libxc_worker_d2h_issue(worker, libxc_dev_v2lapl2, ns*npoints)
    2595              :                CALL libxc_worker_d2h_issue(worker, libxc_dev_v2lapltau, nl*npoints)
    2596              :                CALL libxc_worker_d2h_issue(worker, libxc_dev_v2tau2, ns*npoints)
    2597              :             END IF
    2598              :          END IF
    2599              :          IF (grad_deriv >= 3) THEN
    2600              :             CALL libxc_worker_d2h_issue(worker, libxc_dev_v3rho3, nl*npoints)
    2601              :             IF (is_gga) THEN
    2602              :                CALL libxc_worker_d2h_issue(worker, libxc_dev_v3rho2sigma, MERGE(9, 1, pol)*npoints)
    2603              :                CALL libxc_worker_d2h_issue(worker, libxc_dev_v3rhosigma2, MERGE(12, 1, pol)*npoints)
    2604              :                CALL libxc_worker_d2h_issue(worker, libxc_dev_v3sigma3, MERGE(10, 1, pol)*npoints)
    2605              :             END IF
    2606              :             #:for arr in v3_new
    2607            0 :                IF (is_mgga) THEN
    2608            0 :                   CALL libxc_worker_d2h_issue(worker, libxc_dev_${arr}$, MERGE(${mgga_ncomp[arr]}$, 1, pol)*npoints)
    2609              :                END IF
    2610              :             #:endfor
    2611              :          END IF
    2612              : 
    2613              :          CALL libxc_sync_device()
    2614              : 
    2615            0 :          IF (.NOT. no_exc) THEN
    2616            0 :             CALL libxc_worker_d2h_read(worker, libxc_dev_exc, worker%exc(1:npoints), npoints)
    2617              :          END IF
    2618            0 :          IF (grad_deriv >= 1) THEN
    2619            0 :             CALL libxc_worker_d2h_read(worker, libxc_dev_vrho, worker%vrho(1, 1), np*npoints)
    2620            0 :             IF (is_gga) THEN
    2621            0 :                CALL libxc_worker_d2h_read(worker, libxc_dev_vsigma, worker%vsigma(1, 1), ns*npoints)
    2622              :             END IF
    2623            0 :             IF (is_mgga) THEN
    2624            0 :                CALL libxc_worker_d2h_read(worker, libxc_dev_vlapl, worker%vlapl(1, 1), np*npoints)
    2625            0 :                CALL libxc_worker_d2h_read(worker, libxc_dev_vtau, worker%vtau(1, 1), np*npoints)
    2626              :             END IF
    2627              :          END IF
    2628            0 :          IF (grad_deriv >= 2) THEN
    2629            0 :             CALL libxc_worker_d2h_read(worker, libxc_dev_v2rho2, worker%v2rho2(1, 1), ns*npoints)
    2630            0 :             IF (is_gga) THEN
    2631            0 :                CALL libxc_worker_d2h_read(worker, libxc_dev_v2rhosigma, worker%v2rhosigma(1, 1), MERGE(6, 1, pol)*npoints)
    2632            0 :                CALL libxc_worker_d2h_read(worker, libxc_dev_v2sigma2, worker%v2sigma2(1, 1), MERGE(6, 1, pol)*npoints)
    2633              :             END IF
    2634            0 :             IF (is_mgga) THEN
    2635            0 :                CALL libxc_worker_d2h_read(worker, libxc_dev_v2rholapl, worker%v2rholapl(1, 1), nl*npoints)
    2636            0 :                CALL libxc_worker_d2h_read(worker, libxc_dev_v2rhotau, worker%v2rhotau(1, 1), nl*npoints)
    2637              :                CALL libxc_worker_d2h_read(worker, libxc_dev_v2sigmalapl, worker%v2sigmalapl(1, 1), &
    2638            0 :                                           MERGE(6, 1, pol)*npoints)
    2639              :                CALL libxc_worker_d2h_read(worker, libxc_dev_v2sigmatau, worker%v2sigmatau(1, 1), &
    2640            0 :                                           MERGE(6, 1, pol)*npoints)
    2641            0 :                CALL libxc_worker_d2h_read(worker, libxc_dev_v2lapl2, worker%v2lapl2(1, 1), ns*npoints)
    2642            0 :                CALL libxc_worker_d2h_read(worker, libxc_dev_v2lapltau, worker%v2lapltau(1, 1), nl*npoints)
    2643            0 :                CALL libxc_worker_d2h_read(worker, libxc_dev_v2tau2, worker%v2tau2(1, 1), ns*npoints)
    2644              :             END IF
    2645            0 :          END IF
    2646            0 :          IF (grad_deriv >= 3) THEN
    2647            0 :             CALL libxc_worker_d2h_read(worker, libxc_dev_v3rho3, worker%v3rho3(1, 1), nl*npoints)
    2648            0 :             IF (is_gga) THEN
    2649              :                CALL libxc_worker_d2h_read(worker, libxc_dev_v3rho2sigma, worker%v3rho2sigma(1, 1), &
    2650            0 :                                           MERGE(9, 1, pol)*npoints)
    2651            0 :                CALL libxc_worker_d2h_read(worker, libxc_dev_v3rhosigma2, worker%v3rhosigma2(1, 1), &
    2652            0 :                                           MERGE(12, 1, pol)*npoints)
    2653              :                CALL libxc_worker_d2h_read(worker, libxc_dev_v3sigma3, worker%v3sigma3(1, 1), &
    2654            0 :                                           MERGE(10, 1, pol)*npoints)
    2655              :             END IF
    2656              :             #:for arr in v3_new
    2657            0 :                IF (is_mgga) THEN
    2658              :                   CALL libxc_worker_d2h_read(worker, libxc_dev_${arr}$, worker%${arr}$ (1, 1), &
    2659            0 :                                              MERGE(${mgga_ncomp[arr]}$, 1, pol)*npoints)
    2660              :                END IF
    2661              :             #:endfor
    2662              :          END IF
    2663              :       ELSE
    2664              :          ! Host evaluation. The staging buffers already hold the block; these
    2665              :          ! wrappers write the requested derivatives in place.
    2666      1357294 :          IF (is_mgga) THEN
    2667       277526 :             SELECT CASE (grad_deriv)
    2668              :             CASE (0)
    2669            0 :                CALL libxc_mgga_exc_wrapper(worker%func, npts, worker%rho(1, 1), worker%sigma(1, 1), &
    2670         8310 :                                            worker%lapl(1, 1), worker%tau(1, 1), worker%exc(1))
    2671              :             CASE (1)
    2672       240670 :                IF (no_exc) THEN
    2673              :                   CALL libxc_mgga_vxc_wrapper(worker%func, npts, worker%rho(1, 1), worker%sigma(1, 1), &
    2674              :                                               worker%lapl(1, 1), worker%tau(1, 1), worker%vrho(1, 1), &
    2675            0 :                                               worker%vsigma(1, 1), worker%vlapl(1, 1), worker%vtau(1, 1))
    2676            0 :                   worker%exc(1:npoints) = 0.0_dp
    2677              :                ELSE
    2678              :                   CALL libxc_mgga_exc_vxc_wrapper(worker%func, npts, worker%rho(1, 1), worker%sigma(1, 1), &
    2679              :                                                   worker%lapl(1, 1), worker%tau(1, 1), worker%exc(1), &
    2680              :                                                   worker%vrho(1, 1), worker%vsigma(1, 1), &
    2681       240670 :                                                   worker%vlapl(1, 1), worker%vtau(1, 1))
    2682              :                END IF
    2683            0 :             CASE (2)
    2684        18014 :                IF (no_exc) THEN
    2685              :                   CALL xc_f03_mgga_vxc_fxc(worker%func, npts, worker%rho(1, 1), worker%sigma(1, 1), &
    2686              :                                            worker%lapl(1, 1), worker%tau(1, 1), worker%vrho(1, 1), &
    2687              :                                            worker%vsigma(1, 1), worker%vlapl(1, 1), worker%vtau(1, 1), &
    2688              :                                            worker%v2rho2(1, 1), worker%v2rhosigma(1, 1), worker%v2rholapl(1, 1), &
    2689              :                                            worker%v2rhotau(1, 1), worker%v2sigma2(1, 1), worker%v2sigmalapl(1, 1), &
    2690              :                                            worker%v2sigmatau(1, 1), worker%v2lapl2(1, 1), worker%v2lapltau(1, 1), &
    2691            0 :                                            worker%v2tau2(1, 1))
    2692            0 :                   worker%exc(1:npoints) = 0.0_dp
    2693      1384478 :                ELSE
    2694              :                   CALL xc_f03_mgga(worker%func, npts, worker%rho(1, 1), worker%sigma(1, 1), &
    2695              :                                    worker%lapl(1, 1), worker%tau(1, 1), worker%exc(1), &
    2696              :                                    worker%vrho(1, 1), worker%vsigma(1, 1), worker%vlapl(1, 1), worker%vtau(1, 1), &
    2697              :                                    worker%v2rho2(1, 1), worker%v2rhosigma(1, 1), worker%v2rholapl(1, 1), &
    2698      1972978 :                                    worker%v2rhotau(1, 1), worker%v2sigma2(1, 1), worker%v2sigmalapl(1, 1), &
    2699              :                                    worker%v2sigmatau(1, 1), worker%v2lapl2(1, 1), worker%v2lapltau(1, 1), &
    2700        18014 :                                    worker%v2tau2(1, 1))
    2701       588500 :                END IF
    2702              :             CASE (3)
    2703       269216 :                IF (no_exc) THEN
    2704       519672 :                   CALL xc_f03_mgga_vxc_fxc_kxc(worker%func, npts, worker%rho(1, 1), worker%sigma(1, 1), &
    2705              :                                                worker%lapl(1, 1), worker%tau(1, 1), worker%vrho(1, 1), &
    2706       276306 :                                                worker%vsigma(1, 1), worker%vlapl(1, 1), worker%vtau(1, 1), &
    2707       276306 :                                                worker%v2rho2(1, 1), worker%v2rhosigma(1, 1), worker%v2rholapl(1, 1), &
    2708              :                                                worker%v2rhotau(1, 1), worker%v2sigma2(1, 1), worker%v2sigmalapl(1, 1), &
    2709            0 :                                                worker%v2sigmatau(1, 1), worker%v2lapl2(1, 1), worker%v2lapltau(1, 1), &
    2710            0 :                                                worker%v2tau2(1, 1), worker%v3rho3(1, 1), worker%v3rho2sigma(1, 1), &
    2711      1384478 :                                                worker%v3rho2lapl(1, 1), worker%v3rho2tau(1, 1), &
    2712            0 :                                                worker%v3rhosigma2(1, 1), worker%v3rhosigmalapl(1, 1), &
    2713              :                                                worker%v3rhosigmatau(1, 1), worker%v3rholapl2(1, 1), &
    2714            0 :                                                worker%v3rholapltau(1, 1), worker%v3rhotau2(1, 1), &
    2715              :                                                worker%v3sigma3(1, 1), worker%v3sigma2lapl(1, 1), &
    2716              :                                                worker%v3sigma2tau(1, 1), worker%v3sigmalapl2(1, 1), &
    2717      1384478 :                                                worker%v3sigmalapltau(1, 1), worker%v3sigmatau2(1, 1), &
    2718              :                                                worker%v3lapl3(1, 1), worker%v3lapl2tau(1, 1), &
    2719            0 :                                                worker%v3lapltau2(1, 1), worker%v3tau3(1, 1))
    2720            0 :                   worker%exc(1:npoints) = 0.0_dp
    2721              :                ELSE
    2722              :                   CALL xc_f03_mgga_exc_vxc_fxc_kxc(worker%func, npts, worker%rho(1, 1), worker%sigma(1, 1), &
    2723              :                                                    worker%lapl(1, 1), worker%tau(1, 1), worker%exc(1), &
    2724              :                                                    worker%vrho(1, 1), worker%vsigma(1, 1), worker%vlapl(1, 1), &
    2725              :                                                    worker%vtau(1, 1), worker%v2rho2(1, 1), worker%v2rhosigma(1, 1), &
    2726              :                                                    worker%v2rholapl(1, 1), worker%v2rhotau(1, 1), &
    2727      1358774 :                                                    worker%v2sigma2(1, 1), worker%v2sigmalapl(1, 1), &
    2728              :                                                    worker%v2sigmatau(1, 1), worker%v2lapl2(1, 1), &
    2729              :                                                    worker%v2lapltau(1, 1), worker%v2tau2(1, 1), &
    2730              :                                                    worker%v3rho3(1, 1), worker%v3rho2sigma(1, 1), &
    2731      1358774 :                                                    worker%v3rho2lapl(1, 1), worker%v3rho2tau(1, 1), &
    2732       205680 :                                                    worker%v3rhosigma2(1, 1), worker%v3rhosigmalapl(1, 1), &
    2733       205680 :                                                    worker%v3rhosigmatau(1, 1), worker%v3rholapl2(1, 1), &
    2734       205680 :                                                    worker%v3rholapltau(1, 1), worker%v3rhotau2(1, 1), &
    2735              :                                                    worker%v3sigma3(1, 1), worker%v3sigma2lapl(1, 1), &
    2736      1153094 :                                                    worker%v3sigma2tau(1, 1), worker%v3sigmalapl2(1, 1), &
    2737      1153094 :                                                    worker%v3sigmalapltau(1, 1), worker%v3sigmatau2(1, 1), &
    2738      1153094 :                                                    worker%v3lapl3(1, 1), worker%v3lapl2tau(1, 1), &
    2739         2222 :                                                    worker%v3lapltau2(1, 1), worker%v3tau3(1, 1))
    2740      1358774 :                END IF
    2741              :             END SELECT
    2742      1088078 :          ELSE IF (is_gga) THEN
    2743       523858 :             SELECT CASE (grad_deriv)
    2744              :             CASE (0)
    2745        12474 :                CALL libxc_gga_exc_wrapper(worker%func, npts, worker%rho(1, 1), worker%sigma(1, 1), worker%exc(1))
    2746              :             CASE (1)
    2747       483410 :                IF (no_exc) THEN
    2748              :                   CALL xc_f03_gga_vxc(worker%func, npts, worker%rho(1, 1), worker%sigma(1, 1), &
    2749            0 :                                       worker%vrho(1, 1), worker%vsigma(1, 1))
    2750            0 :                   worker%exc(1:npoints) = 0.0_dp
    2751              :                ELSE
    2752              :                   CALL libxc_gga_exc_vxc_wrapper(worker%func, npts, worker%rho(1, 1), worker%sigma(1, 1), &
    2753       483410 :                                                  worker%exc(1), worker%vrho(1, 1), worker%vsigma(1, 1))
    2754              :                END IF
    2755              :             CASE (2)
    2756        14056 :                IF (no_exc) THEN
    2757              :                   CALL xc_f03_gga_vxc_fxc(worker%func, npts, worker%rho(1, 1), worker%sigma(1, 1), &
    2758              :                                           worker%vrho(1, 1), worker%vsigma(1, 1), &
    2759            0 :                                           worker%v2rho2(1, 1), worker%v2rhosigma(1, 1), worker%v2sigma2(1, 1))
    2760            0 :                   worker%exc(1:npoints) = 0.0_dp
    2761              :                ELSE
    2762              :                   CALL xc_f03_gga_exc_vxc_fxc(worker%func, npts, worker%rho(1, 1), worker%sigma(1, 1), &
    2763              :                                               worker%exc(1), worker%vrho(1, 1), worker%vsigma(1, 1), &
    2764        14056 :                                               worker%v2rho2(1, 1), worker%v2rhosigma(1, 1), worker%v2sigma2(1, 1))
    2765              :                END IF
    2766              :             CASE (3)
    2767       511384 :                IF (no_exc) THEN
    2768              :                   CALL xc_f03_gga_vxc_fxc_kxc(worker%func, npts, worker%rho(1, 1), worker%sigma(1, 1), &
    2769              :                                               worker%vrho(1, 1), worker%vsigma(1, 1), &
    2770              :                                               worker%v2rho2(1, 1), worker%v2rhosigma(1, 1), worker%v2sigma2(1, 1), &
    2771              :                                               worker%v3rho3(1, 1), worker%v3rho2sigma(1, 1), &
    2772            0 :                                               worker%v3rhosigma2(1, 1), worker%v3sigma3(1, 1))
    2773            0 :                   worker%exc(1:npoints) = 0.0_dp
    2774              :                ELSE
    2775              :                   CALL xc_f03_gga_exc_vxc_fxc_kxc(worker%func, npts, worker%rho(1, 1), worker%sigma(1, 1), &
    2776              :                                                   worker%exc(1), worker%vrho(1, 1), worker%vsigma(1, 1), &
    2777              :                                                   worker%v2rho2(1, 1), worker%v2rhosigma(1, 1), worker%v2sigma2(1, 1), &
    2778              :                                                   worker%v3rho3(1, 1), worker%v3rho2sigma(1, 1), &
    2779         1444 :                                                   worker%v3rhosigma2(1, 1), worker%v3sigma3(1, 1))
    2780              :                END IF
    2781              :             END SELECT
    2782              :          ELSE
    2783       589236 :             SELECT CASE (grad_deriv)
    2784              :             CASE (0)
    2785        12542 :                CALL libxc_lda_exc_wrapper(worker%func, npts, worker%rho(1, 1), worker%exc(1))
    2786              :             CASE (1)
    2787       535102 :                CALL libxc_lda_exc_vxc_wrapper(worker%func, npts, worker%rho(1, 1), worker%exc(1), worker%vrho(1, 1))
    2788              :             CASE (2)
    2789              :                CALL xc_f03_lda_exc_vxc_fxc(worker%func, npts, worker%rho(1, 1), &
    2790        27606 :                                            worker%exc(1), worker%vrho(1, 1), worker%v2rho2(1, 1))
    2791              :             CASE (3)
    2792              :                CALL xc_f03_lda(worker%func, npts, worker%rho(1, 1), &
    2793       576694 :                                worker%exc(1), worker%vrho(1, 1), worker%v2rho2(1, 1), worker%v3rho3(1, 1))
    2794              :             END SELECT
    2795              :          END IF
    2796      1357294 :       END IF
    2797      1357294 : 
    2798      1357294 :       CALL libxc_worker_check_nan(worker, npoints, grad_deriv, no_exc, family)
    2799      1357294 : 
    2800      1357294 :    END SUBROUTINE libxc_worker_eval
    2801              : 
    2802              : ! **************************************************************************************************
    2803              : !> \brief GGA exc and vxc on host arrays.
    2804              : !> \param func ...
    2805      1357294 : !> \param np ...
    2806              : !> \param rho ...
    2807            0 : !> \param sigma ...
    2808            0 : !> \param exc ...
    2809            0 : !> \param vrho ...
    2810              : !> \param vsigma ...
    2811            0 : ! **************************************************************************************************
    2812            0 :    SUBROUTINE libxc_gga_exc_vxc_wrapper(func, np, rho, sigma, exc, vrho, vsigma)
    2813            0 :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    2814              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    2815              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    2816              :       REAL(KIND=dp), DIMENSION(*), INTENT(IN)            :: rho, sigma
    2817              :       REAL(KIND=dp), DIMENSION(*), INTENT(OUT)           :: exc, vrho, vsigma
    2818            0 : 
    2819       483410 :       CALL xc_f03_gga_exc_vxc(func, np, rho, sigma, exc, vrho, vsigma)
    2820       483410 :    END SUBROUTINE libxc_gga_exc_vxc_wrapper
    2821              : 
    2822            0 : ! **************************************************************************************************
    2823            0 : !> \brief GGA exc on host arrays.
    2824              : !> \param func ...
    2825            0 : !> \param np ...
    2826            0 : !> \param rho ...
    2827            0 : !> \param sigma ...
    2828            0 : !> \param exc ...
    2829              : ! **************************************************************************************************
    2830            0 :    SUBROUTINE libxc_gga_exc_wrapper(func, np, rho, sigma, exc)
    2831            0 :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    2832            0 :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    2833              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    2834              :       REAL(KIND=dp), DIMENSION(*), INTENT(IN)            :: rho, sigma
    2835            0 :       REAL(KIND=dp), DIMENSION(*), INTENT(OUT)           :: exc
    2836            0 : 
    2837        12474 :       CALL xc_f03_gga_exc(func, np, rho, sigma, exc)
    2838            0 :    END SUBROUTINE libxc_gga_exc_wrapper
    2839            0 : 
    2840              : ! **************************************************************************************************
    2841            0 : !> \brief LDA exc and vxc on host arrays.
    2842            0 : !> \param func ...
    2843            0 : !> \param np ...
    2844            0 : !> \param rho ...
    2845            0 : !> \param exc ...
    2846            0 : !> \param vrho ...
    2847            0 : ! **************************************************************************************************
    2848            0 :    SUBROUTINE libxc_lda_exc_vxc_wrapper(func, np, rho, exc, vrho)
    2849              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    2850              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    2851            0 :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    2852            0 :       REAL(KIND=dp), DIMENSION(*), INTENT(IN)            :: rho
    2853            0 :       REAL(KIND=dp), DIMENSION(*), INTENT(OUT)           :: exc, vrho
    2854            0 : 
    2855       535102 :       CALL xc_f03_lda_exc_vxc(func, np, rho, exc, vrho)
    2856            0 :    END SUBROUTINE libxc_lda_exc_vxc_wrapper
    2857              : 
    2858              : ! **************************************************************************************************
    2859              : !> \brief LDA exc on host arrays.
    2860              : !> \param func ...
    2861              : !> \param np ...
    2862              : !> \param rho ...
    2863              : !> \param exc ...
    2864              : ! **************************************************************************************************
    2865        12542 :    SUBROUTINE libxc_lda_exc_wrapper(func, np, rho, exc)
    2866              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    2867              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    2868              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    2869              :       REAL(KIND=dp), DIMENSION(*), INTENT(IN)            :: rho
    2870              :       REAL(KIND=dp), DIMENSION(*), INTENT(OUT)           :: exc
    2871              : 
    2872        12542 :       CALL xc_f03_lda_exc(func, np, rho, exc)
    2873        12542 :    END SUBROUTINE libxc_lda_exc_wrapper
    2874              : 
    2875              : ! **************************************************************************************************
    2876              : !> \brief MGGA exc and vxc on host arrays.
    2877              : !> \param func ...
    2878              : !> \param np ...
    2879              : !> \param rho ...
    2880              : !> \param sigma ...
    2881              : !> \param lapl ...
    2882              : !> \param tau ...
    2883              : !> \param exc ...
    2884              : !> \param vrho ...
    2885              : !> \param vsigma ...
    2886              : !> \param vlapl ...
    2887              : !> \param vtau ...
    2888              : ! **************************************************************************************************
    2889       240670 :    SUBROUTINE libxc_mgga_exc_vxc_wrapper(func, np, rho, sigma, lapl, tau, exc, vrho, vsigma, vlapl, vtau)
    2890              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    2891              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    2892              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    2893              :       REAL(KIND=dp), DIMENSION(*), INTENT(IN)            :: rho, sigma, lapl, tau
    2894              :       REAL(KIND=dp), DIMENSION(*), INTENT(OUT)           :: exc, vrho, vsigma, vlapl, vtau
    2895              : 
    2896       240670 :       CALL xc_f03_mgga_exc_vxc(func, np, rho, sigma, lapl, tau, exc, vrho, vsigma, vlapl, vtau)
    2897       240670 :    END SUBROUTINE libxc_mgga_exc_vxc_wrapper
    2898              : 
    2899              : ! **************************************************************************************************
    2900              : !> \brief MGGA exc on host arrays.
    2901              : !> \param func ...
    2902              : !> \param np ...
    2903              : !> \param rho ...
    2904              : !> \param sigma ...
    2905              : !> \param lapl ...
    2906              : !> \param tau ...
    2907              : !> \param exc ...
    2908              : ! **************************************************************************************************
    2909         8310 :    SUBROUTINE libxc_mgga_exc_wrapper(func, np, rho, sigma, lapl, tau, exc)
    2910              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    2911              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    2912              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    2913              :       REAL(KIND=dp), DIMENSION(*), INTENT(IN)            :: rho, sigma, lapl, tau
    2914              :       REAL(KIND=dp), DIMENSION(*), INTENT(OUT)           :: exc
    2915              : 
    2916         8310 :       CALL xc_f03_mgga_exc(func, np, rho, sigma, lapl, tau, exc)
    2917         8310 :    END SUBROUTINE libxc_mgga_exc_wrapper
    2918              : 
    2919              : ! **************************************************************************************************
    2920              : !> \brief MGGA vxc on host arrays.
    2921              : !> \param func ...
    2922              : !> \param np ...
    2923              : !> \param rho ...
    2924              : !> \param sigma ...
    2925              : !> \param lapl ...
    2926              : !> \param tau ...
    2927              : !> \param vrho ...
    2928              : !> \param vsigma ...
    2929              : !> \param vlapl ...
    2930              : !> \param vtau ...
    2931              : ! **************************************************************************************************
    2932            0 :    SUBROUTINE libxc_mgga_vxc_wrapper(func, np, rho, sigma, lapl, tau, vrho, vsigma, vlapl, vtau)
    2933              :       USE ISO_C_BINDING, ONLY: C_SIZE_T
    2934              :       TYPE(xc_f03_func_t), INTENT(IN)                    :: func
    2935              :       INTEGER(KIND=C_SIZE_T), INTENT(IN)                 :: np
    2936              :       REAL(KIND=dp), DIMENSION(*), INTENT(IN)            :: rho, sigma, lapl, tau
    2937              :       REAL(KIND=dp), DIMENSION(*), INTENT(OUT)           :: vrho, vsigma, vlapl, vtau
    2938              : 
    2939            0 :       CALL xc_f03_mgga_vxc(func, np, rho, sigma, lapl, tau, vrho, vsigma, vlapl, vtau)
    2940            0 :    END SUBROUTINE libxc_mgga_vxc_wrapper
    2941              : 
    2942              : #endif
    2943              : 
    2944            0 : END MODULE xc_libxc_wrap
        

Generated by: LCOV version 2.0-1