LCOV - code coverage report
Current view: top level - src - qs_fgxc.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:62906da) Lines: 53.3 % 347 185
Test Date: 2026-10-24 01:17:15 Functions: 80.0 % 5 4

            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  https://en.wikipedia.org/wiki/Finite_difference_coefficient
      10              : !---------------------------------------------------------------------------------------------------
      11              : !Derivative    Accuracy            4       3       2       1       0       1       2      3       4
      12              : !---------------------------------------------------------------------------------------------------
      13              : !    1             2                                    -1/2       0     1/2
      14              : !                  4                            1/12    -2/3       0     2/3   -1/12
      15              : !                  6                   -1/60    3/20    -3/4       0     3/4   -3/20   1/60
      16              : !                  8           1/280  -4/105     1/5    -4/5       0     4/5    -1/5  4/105  -1/280
      17              : !---------------------------------------------------------------------------------------------------
      18              : !    2             2                                       1      -2       1
      19              : !                  4                           -1/12     4/3    -5/2     4/3   -1/12
      20              : !                  6                    1/90   -3/20     3/2  -49/18     3/2   -3/20   1/90
      21              : !                  8          -1/560   8/315    -1/5     8/5 -205/72     8/5    -1/5  8/315  -1/560
      22              : !---------------------------------------------------------------------------------------------------
      23              : !> \par History
      24              : !>     init 17.03.2020
      25              : !>     complete refactoring 08.2026
      26              : !> \author JGH
      27              : ! **************************************************************************************************
      28              : MODULE qs_fgxc
      29              : 
      30              :    USE cp_control_types,                ONLY: dft_control_type
      31              :    USE input_section_types,             ONLY: section_get_ival,&
      32              :                                               section_get_lval,&
      33              :                                               section_get_rval,&
      34              :                                               section_vals_get_subs_vals,&
      35              :                                               section_vals_type
      36              :    USE kinds,                           ONLY: dp
      37              :    USE pw_env_types,                    ONLY: pw_env_get,&
      38              :                                               pw_env_type
      39              :    USE pw_grids,                        ONLY: pw_grid_compare
      40              :    USE pw_methods,                      ONLY: pw_axpy,&
      41              :                                               pw_scale,&
      42              :                                               pw_transfer,&
      43              :                                               pw_zero
      44              :    USE pw_pool_types,                   ONLY: pw_pool_type
      45              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      46              :                                               pw_r3d_rs_type
      47              :    USE qs_environment_types,            ONLY: get_qs_env,&
      48              :                                               qs_environment_type
      49              :    USE qs_fgxc_atom,                    ONLY: fgxc_atom_calc,&
      50              :                                               fgxc_atom_diff
      51              :    USE qs_fxc,                          ONLY: qs_fxc_create,&
      52              :                                               qs_fxc_fdiff
      53              :    USE qs_kind_types,                   ONLY: qs_kind_type
      54              :    USE qs_ks_types,                     ONLY: qs_ks_env_type
      55              :    USE qs_rho_atom_types,               ONLY: rho_atom_type
      56              :    USE qs_rho_methods,                  ONLY: qs_rho_copy,&
      57              :                                               qs_rho_scale_and_add,&
      58              :                                               qs_rho_scale_and_add_b,&
      59              :                                               qs_rho_transfer
      60              :    USE qs_rho_types,                    ONLY: qs_rho_create,&
      61              :                                               qs_rho_get,&
      62              :                                               qs_rho_release,&
      63              :                                               qs_rho_type
      64              :    USE qs_vxc,                          ONLY: qs_vxc_create
      65              :    USE xc,                              ONLY: xc_calc_2nd_deriv_analytical,&
      66              :                                               xc_calc_3rd_deriv_analytical,&
      67              :                                               xc_prep_3rd_deriv
      68              :    USE xc_derivative_set_types,         ONLY: xc_derivative_set_type,&
      69              :                                               xc_dset_release
      70              :    USE xc_derivatives,                  ONLY: xc_functionals_get_needs
      71              :    USE xc_rho_cflags_types,             ONLY: xc_rho_cflags_type
      72              :    USE xc_rho_set_types,                ONLY: xc_rho_set_create,&
      73              :                                               xc_rho_set_release,&
      74              :                                               xc_rho_set_type,&
      75              :                                               xc_rho_set_update
      76              : #include "./base/base_uses.f90"
      77              : 
      78              :    IMPLICIT NONE
      79              : 
      80              :    PRIVATE
      81              : 
      82              :    ! *** Public subroutines ***
      83              :    PUBLIC :: qs_fgxc_create, qs_fgxc_release
      84              : 
      85              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_fgxc'
      86              : 
      87              : ! **************************************************************************************************
      88              : 
      89              : CONTAINS
      90              : 
      91              : ! **************************************************************************************************
      92              : !> \brief ...
      93              : !> \param qs_env ...
      94              : !> \param rho0_struct ...
      95              : !> \param rho1_struct ...
      96              : !> \param rho0_atom_set ...
      97              : !> \param xc_section ...
      98              : !> \param do_onecenter ...
      99              : !> \param is_triplet ...
     100              : !> \param spinflip ...
     101              : !> \param fxc_rho ...
     102              : !> \param fxc_tau ...
     103              : !> \param gxc_rho ...
     104              : !> \param gxc_tau ...
     105              : !> \param rhof_atom_set ...
     106              : !> \param rhog_atom_set ...
     107              : !> \param qs_kind_set ...
     108              : ! **************************************************************************************************
     109          366 :    SUBROUTINE qs_fgxc_create(qs_env, rho0_struct, rho1_struct, rho0_atom_set, &
     110              :                              xc_section, do_onecenter, is_triplet, spinflip, &
     111              :                              fxc_rho, fxc_tau, gxc_rho, gxc_tau, &
     112              :                              rhof_atom_set, rhog_atom_set, qs_kind_set)
     113              : 
     114              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     115              :       TYPE(qs_rho_type), POINTER                         :: rho0_struct, rho1_struct
     116              :       TYPE(rho_atom_type), DIMENSION(:), POINTER         :: rho0_atom_set
     117              :       TYPE(section_vals_type), POINTER                   :: xc_section
     118              :       LOGICAL, INTENT(IN)                                :: do_onecenter, is_triplet, spinflip
     119              :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: fxc_rho, fxc_tau, gxc_rho, gxc_tau
     120              :       TYPE(rho_atom_type), DIMENSION(:), POINTER         :: rhof_atom_set, rhog_atom_set
     121              :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     122              : 
     123              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'qs_fgxc_create'
     124              : 
     125              :       INTEGER                                            :: handle, ispin, nspins, nsteps, order
     126              :       LOGICAL                                            :: analytic_2nd_deriv, analytic_3rd_deriv, &
     127              :                                                             has_rho, has_tau, uf_grid
     128              :       REAL(KIND=dp)                                      :: eps_delta, factor
     129              :       TYPE(dft_control_type), POINTER                    :: dft_control
     130          366 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: rho_g
     131              :       TYPE(pw_c1d_gs_type), POINTER                      :: rho_nlcc_g
     132              :       TYPE(pw_env_type), POINTER                         :: pw_env
     133              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool, uf_pw_pool, xc_pw_pool
     134          366 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: fxc_rho_uf, fxc_tau_uf, gxc_rho_uf, &
     135          366 :                                                             gxc_tau_uf, rho_r
     136              :       TYPE(pw_r3d_rs_type), POINTER                      :: rho_nlcc, weights, weights_uf
     137              :       TYPE(qs_rho_type), POINTER                         :: rho0_uf, rho1_uf
     138              : 
     139          366 :       CALL timeset(routineN, handle)
     140              : 
     141              :       ! Only rho0 and rho1 should be associated
     142          366 :       CPASSERT(.NOT. ASSOCIATED(fxc_rho))
     143          366 :       CPASSERT(.NOT. ASSOCIATED(fxc_tau))
     144          366 :       CPASSERT(.NOT. ASSOCIATED(gxc_rho))
     145          366 :       CPASSERT(.NOT. ASSOCIATED(gxc_tau))
     146          366 :       CPASSERT(ASSOCIATED(rho0_struct))
     147          366 :       CPASSERT(ASSOCIATED(rho1_struct))
     148              : 
     149          366 :       nsteps = section_get_ival(xc_section, "NSTEPS")
     150          366 :       order = 2*nsteps
     151          366 :       eps_delta = section_get_rval(xc_section, "STEP_SIZE")
     152          366 :       analytic_2nd_deriv = section_get_lval(xc_section, "2ND_DERIV_ANALYTICAL")
     153          366 :       analytic_3rd_deriv = section_get_lval(xc_section, "3RD_DERIV_ANALYTICAL")
     154          366 :       IF (analytic_3rd_deriv .AND. .NOT. analytic_2nd_deriv) THEN
     155              :          CALL cp_warn(__LOCATION__, "XC Analytic 3rd derivatives cannot be combined with "// &
     156            0 :                       "numeric 2nd derivatives.")
     157            0 :          CPABORT("XC derivative options")
     158              :       END IF
     159              : 
     160          366 :       CALL get_qs_env(qs_env, dft_control=dft_control)
     161          366 :       nspins = dft_control%nspins
     162              : 
     163          366 :       CALL get_qs_env(qs_env, pw_env=pw_env)
     164          366 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, xc_pw_pool=xc_pw_pool)
     165          366 :       uf_grid = .NOT. pw_grid_compare(auxbas_pw_pool%pw_grid, xc_pw_pool%pw_grid)
     166              : 
     167          366 :       NULLIFY (fxc_rho_uf, fxc_tau_uf, gxc_rho_uf, gxc_tau_uf)
     168          366 :       IF (analytic_2nd_deriv .AND. analytic_3rd_deriv) THEN
     169              : 
     170              :          ! NLCC
     171           30 :          NULLIFY (rho_nlcc, rho_nlcc_g)
     172           30 :          CALL get_qs_env(qs_env, rho_nlcc=rho_nlcc, rho_nlcc_g=rho_nlcc_g)
     173           30 :          IF (ASSOCIATED(rho_nlcc)) THEN
     174            0 :             NULLIFY (rho_r, rho_g)
     175            0 :             CALL qs_rho_get(rho0_struct, rho_r=rho_r, rho_g=rho_g)
     176            0 :             factor = 1.0_dp
     177            0 :             DO ispin = 1, nspins
     178            0 :                CALL pw_axpy(rho_nlcc, rho_r(ispin), factor)
     179            0 :                CALL pw_axpy(rho_nlcc_g, rho_g(ispin), factor)
     180              :             END DO
     181              :          END IF
     182              : 
     183              :          ! Integration weights
     184           30 :          NULLIFY (weights)
     185           30 :          CALL get_qs_env(qs_env, xcint_weights=weights)
     186              : 
     187           30 :          NULLIFY (weights_uf)
     188           30 :          IF (uf_grid) THEN
     189            0 :             IF (ASSOCIATED(weights)) THEN
     190            0 :                ALLOCATE (weights_uf)
     191            0 :                CALL xc_pw_pool%create_pw(weights_uf)
     192              :                BLOCK
     193              :                   TYPE(pw_c1d_gs_type) :: weights_g, weights_g_uf
     194            0 :                   CALL auxbas_pw_pool%create_pw(weights_g)
     195            0 :                   CALL xc_pw_pool%create_pw(weights_g_uf)
     196            0 :                   CALL pw_transfer(weights, weights_g)
     197            0 :                   CALL pw_transfer(weights_g, weights_g_uf)
     198            0 :                   CALL pw_transfer(weights_g_uf, weights_uf)
     199            0 :                   CALL xc_pw_pool%give_back_pw(weights_g_uf)
     200            0 :                   CALL auxbas_pw_pool%give_back_pw(weights_g)
     201              :                END BLOCK
     202              :             END IF
     203              :             !
     204            0 :             ALLOCATE (rho0_uf, rho1_uf)
     205            0 :             CALL qs_rho_create(rho0_uf)
     206            0 :             CALL qs_rho_create(rho1_uf)
     207            0 :             CALL qs_rho_transfer(rho0_struct, rho0_uf, auxbas_pw_pool, xc_pw_pool)
     208            0 :             CALL qs_rho_transfer(rho1_struct, rho1_uf, auxbas_pw_pool, xc_pw_pool)
     209            0 :             uf_pw_pool => xc_pw_pool
     210              :          ELSE
     211           30 :             weights_uf => weights
     212           30 :             rho0_uf => rho0_struct
     213           30 :             rho1_uf => rho1_struct
     214           30 :             uf_pw_pool => auxbas_pw_pool
     215              :          END IF
     216              : 
     217              :          ! Analytic third derivatives cover the spin-flip case and, in the
     218              :          ! reduced-gradient (gamma) formulation, the spin-restricted singlet one.
     219           30 :          IF (.NOT. spinflip .AND. is_triplet) THEN
     220            0 :             CPABORT("Analytic 3rd XC derivatives: no restricted triplets yet")
     221              :          END IF
     222              :          CALL qs_fgxc_analytic(rho0_uf, rho1_uf, xc_section, uf_pw_pool, weights_uf, &
     223              :                                is_triplet, spinflip, &
     224           30 :                                fxc_rho_uf, fxc_tau_uf, gxc_rho_uf, gxc_tau_uf)
     225              : 
     226              :          ! check for results
     227           30 :          has_rho = .FALSE.
     228           30 :          IF (ASSOCIATED(fxc_rho_uf) .AND. ASSOCIATED(gxc_rho_uf)) has_rho = .TRUE.
     229           30 :          has_tau = .FALSE.
     230           30 :          IF (ASSOCIATED(fxc_tau_uf) .AND. ASSOCIATED(gxc_tau_uf)) has_tau = .TRUE.
     231              :          ! transfer to standard grid
     232           30 :          IF (uf_grid) THEN
     233              :             ! rho
     234            0 :             IF (has_rho) THEN
     235            0 :                ALLOCATE (fxc_rho(SIZE(fxc_rho_uf)), gxc_rho(SIZE(gxc_rho_uf)))
     236              :                BLOCK
     237              :                   TYPE(pw_c1d_gs_type) :: xc_g, xc_g_uf
     238            0 :                   CALL auxbas_pw_pool%create_pw(xc_g)
     239            0 :                   CALL xc_pw_pool%create_pw(xc_g_uf)
     240            0 :                   DO ispin = 1, SIZE(fxc_rho)
     241            0 :                      CALL auxbas_pw_pool%create_pw(fxc_rho(ispin))
     242            0 :                      CALL pw_transfer(fxc_rho_uf(ispin), xc_g_uf)
     243            0 :                      CALL pw_transfer(xc_g_uf, xc_g)
     244            0 :                      CALL pw_transfer(xc_g, fxc_rho(ispin))
     245            0 :                      CALL xc_pw_pool%give_back_pw(fxc_rho_uf(ispin))
     246              :                   END DO
     247            0 :                   DO ispin = 1, SIZE(gxc_rho)
     248            0 :                      CALL auxbas_pw_pool%create_pw(gxc_rho(ispin))
     249            0 :                      CALL pw_transfer(gxc_rho_uf(ispin), xc_g_uf)
     250            0 :                      CALL pw_transfer(xc_g_uf, xc_g)
     251            0 :                      CALL pw_transfer(xc_g, gxc_rho(ispin))
     252            0 :                      CALL xc_pw_pool%give_back_pw(gxc_rho_uf(ispin))
     253              :                   END DO
     254            0 :                   CALL xc_pw_pool%give_back_pw(xc_g_uf)
     255            0 :                   CALL auxbas_pw_pool%give_back_pw(xc_g)
     256              :                END BLOCK
     257            0 :                DEALLOCATE (fxc_rho_uf, gxc_rho_uf)
     258              :             ELSE
     259            0 :                NULLIFY (fxc_rho, gxc_rho)
     260              :             END IF
     261              :             ! tau
     262            0 :             IF (has_tau) THEN
     263            0 :                ALLOCATE (fxc_tau(SIZE(fxc_tau_uf)), gxc_tau(SIZE(gxc_tau_uf)))
     264              :                BLOCK
     265              :                   TYPE(pw_c1d_gs_type) :: xc_g, xc_g_uf
     266            0 :                   CALL auxbas_pw_pool%create_pw(xc_g)
     267            0 :                   CALL xc_pw_pool%create_pw(xc_g_uf)
     268            0 :                   DO ispin = 1, SIZE(fxc_tau)
     269            0 :                      CALL auxbas_pw_pool%create_pw(fxc_tau(ispin))
     270            0 :                      CALL pw_transfer(fxc_tau_uf(ispin), xc_g_uf)
     271            0 :                      CALL pw_transfer(xc_g_uf, xc_g)
     272            0 :                      CALL pw_transfer(xc_g, fxc_tau(ispin))
     273            0 :                      CALL xc_pw_pool%give_back_pw(fxc_tau_uf(ispin))
     274              :                   END DO
     275            0 :                   DO ispin = 1, SIZE(gxc_tau)
     276            0 :                      CALL auxbas_pw_pool%create_pw(gxc_tau(ispin))
     277            0 :                      CALL pw_transfer(gxc_tau_uf(ispin), xc_g_uf)
     278            0 :                      CALL pw_transfer(xc_g_uf, xc_g)
     279            0 :                      CALL pw_transfer(xc_g, gxc_tau(ispin))
     280            0 :                      CALL xc_pw_pool%give_back_pw(gxc_tau_uf(ispin))
     281              :                   END DO
     282            0 :                   CALL xc_pw_pool%give_back_pw(xc_g_uf)
     283            0 :                   CALL auxbas_pw_pool%give_back_pw(xc_g)
     284              :                END BLOCK
     285            0 :                DEALLOCATE (fxc_tau_uf, gxc_tau_uf)
     286              :             ELSE
     287            0 :                NULLIFY (fxc_tau, gxc_tau)
     288              :             END IF
     289              :          ELSE
     290           30 :             fxc_rho => fxc_rho_uf
     291           30 :             fxc_tau => fxc_tau_uf
     292           30 :             gxc_rho => gxc_rho_uf
     293           30 :             gxc_tau => gxc_tau_uf
     294              :          END IF
     295              : 
     296              :          ! de-apply NLCC density
     297           30 :          IF (ASSOCIATED(rho_nlcc)) THEN
     298            0 :             factor = -1.0_dp
     299            0 :             DO ispin = 1, nspins
     300            0 :                CALL pw_axpy(rho_nlcc, rho_r(ispin), factor)
     301            0 :                CALL pw_axpy(rho_nlcc_g, rho_g(ispin), factor)
     302              :             END DO
     303              :          END IF
     304              : 
     305          336 :       ELSE IF (analytic_2nd_deriv .AND. .NOT. analytic_3rd_deriv) THEN
     306              : 
     307          336 :          NULLIFY (weights)
     308          336 :          CALL get_qs_env(qs_env, xcint_weights=weights)
     309              :          CALL qs_fgxc_gdiff(qs_env, rho0_struct, rho1_struct, xc_section, &
     310              :                             order, eps_delta, is_triplet, spinflip, &
     311          336 :                             fxc_rho, fxc_tau, gxc_rho, gxc_tau)
     312              : 
     313            0 :       ELSE IF (.NOT. (analytic_2nd_deriv .OR. analytic_3rd_deriv)) THEN
     314              : 
     315              :          CALL qs_fgxc_fgdiff(qs_env, rho0_struct, rho1_struct, xc_section, &
     316              :                              order, is_triplet, spinflip, &
     317            0 :                              fxc_rho, fxc_tau, gxc_rho, gxc_tau)
     318              : 
     319              :       ELSE
     320            0 :          CPABORT("EXC derivative option not available")
     321              :       END IF
     322              : 
     323          366 :       IF (do_onecenter) THEN
     324          114 :          IF (analytic_2nd_deriv .AND. analytic_3rd_deriv) THEN
     325            0 :             CPABORT("Analytic 3rd EXC derivatives not available")
     326          114 :          ELSE IF (analytic_2nd_deriv) THEN
     327              :             CALL fgxc_atom_diff(qs_env, rho0_atom_set, rhof_atom_set, rhog_atom_set, &
     328          114 :                                 qs_kind_set, xc_section, is_triplet, order, eps_delta)
     329            0 :          ELSE IF (analytic_3rd_deriv) THEN
     330              :             CALL cp_warn(__LOCATION__, "XC Analytic 3rd derivatives cannot be combined with "// &
     331            0 :                          "numeric 2nd derivatives.")
     332            0 :             CPABORT("XC derivative options")
     333              :          ELSE
     334              :             CALL fgxc_atom_calc(qs_env, rho0_atom_set, rhof_atom_set, rhog_atom_set, &
     335            0 :                                 qs_kind_set, xc_section, is_triplet, order)
     336              :          END IF
     337              :       END IF
     338              : 
     339          366 :       CALL timestop(handle)
     340              : 
     341          366 :    END SUBROUTINE qs_fgxc_create
     342              : 
     343              : ! **************************************************************************************************
     344              : !> \brief Calculates the values at the grid points  in real space (r_i), of the second and third
     345              : !>        functional derivatives of the exchange-correlation energy functional.
     346              : !>         fxc_rho(r_i) =  fxc[n](r_i)*n^(1)(r_i)            ! Second functional derivative
     347              : !>         gxc_rho(r_i) =  n^(1)(r_i)*gxc[n](r_i)*n^(1)(r_i) ! Third functional derivative
     348              : !> \param rho0_struct Ground state density, n(r).
     349              : !> \param rho1_struct Density used to fold the functional derivatives, n^(1)(r).
     350              : !> \param xc_section ...
     351              : !> \param pw_pool ...
     352              : !> \param weights ...
     353              : !> \param is_triplet Flag used to activate triplet kernel (not available)
     354              : !> \param spinflip Flag used to activate the spin-flip noncollinear kernel and kernel derivatives.
     355              : !> \param fxc_rho Second functional derivative with respect to the density, n(r).
     356              : !> \param fxc_tau mGGA contribution to the second functional derivative with respect to the density.
     357              : !> \param gxc_rho Third functional derivative with respect to the density, n(r).
     358              : !> \param gxc_tau mGGA contribution to the third functional derivative with respect to the density.
     359              : !> \par History
     360              : !>    * 07.2024 Created [LHS]
     361              : ! **************************************************************************************************
     362           30 :    SUBROUTINE qs_fgxc_analytic(rho0_struct, rho1_struct, xc_section, pw_pool, weights, &
     363              :                                is_triplet, spinflip, fxc_rho, fxc_tau, gxc_rho, gxc_tau)
     364              : 
     365              :       TYPE(qs_rho_type), POINTER                         :: rho0_struct, rho1_struct
     366              :       TYPE(section_vals_type), POINTER                   :: xc_section
     367              :       TYPE(pw_pool_type), POINTER                        :: pw_pool
     368              :       TYPE(pw_r3d_rs_type), POINTER                      :: weights
     369              :       LOGICAL, INTENT(IN)                                :: is_triplet, spinflip
     370              :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: fxc_rho, fxc_tau, gxc_rho, gxc_tau
     371              : 
     372              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'qs_fgxc_analytic'
     373              : 
     374              :       INTEGER                                            :: handle, ispin, nspins, spindim
     375              :       INTEGER, DIMENSION(2, 3)                           :: bo
     376              :       LOGICAL                                            :: do_sf, lsd
     377              :       REAL(KIND=dp)                                      :: fac
     378           60 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: rho0_g, rho1_g
     379           90 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho0_r, rho1_r, tau0_r, tau1_r
     380              :       TYPE(section_vals_type), POINTER                   :: xc_fun_section
     381              :       TYPE(xc_derivative_set_type)                       :: deriv_set
     382              :       TYPE(xc_rho_cflags_type)                           :: needs
     383              :       TYPE(xc_rho_set_type)                              :: rho0_set, rho1_set
     384              : 
     385           30 :       CALL timeset(routineN, handle)
     386              : 
     387              :       ! Only rho0 and rho1 should be associated
     388           30 :       CPASSERT(.NOT. ASSOCIATED(fxc_rho))
     389           30 :       CPASSERT(.NOT. ASSOCIATED(fxc_tau))
     390           30 :       CPASSERT(.NOT. ASSOCIATED(gxc_rho))
     391           30 :       CPASSERT(.NOT. ASSOCIATED(gxc_tau))
     392           30 :       CPASSERT(ASSOCIATED(rho0_struct))
     393           30 :       CPASSERT(ASSOCIATED(rho1_struct))
     394              : 
     395           30 :       CPASSERT(.NOT. is_triplet)
     396              : 
     397              :       ! Initialize parameters
     398           30 :       do_sf = spinflip
     399              :       !
     400              :       ! Get the values on the gridpoints of the rho0 density
     401           30 :       CALL qs_rho_get(rho0_struct, rho_r=rho0_r, rho_g=rho0_g, tau_r=tau0_r)
     402           30 :       nspins = SIZE(rho0_r)
     403              :       ! The perturbed fields have to be fetched here too: the meta-GGA branch
     404              :       ! below tests ASSOCIATED(tau1_r) before rho1_set is built, and tau1_r is a
     405              :       ! local pointer until this call defines it.
     406           30 :       CALL qs_rho_get(rho1_struct, rho_r=rho1_r, rho_g=rho1_g, tau_r=tau1_r)
     407              : 
     408              :       ! Analytic third derivatives cover the spin-flip case and, in the
     409              :       ! reduced-gradient (gamma) formulation, the spin-restricted singlet one.
     410           30 :       IF (.NOT. (do_sf .OR. nspins == 1 .OR. nspins == 2)) THEN
     411            0 :          CPABORT("Analytic 3rd XC derivatives: unsupported spin case")
     412              :       END IF
     413           30 :       lsd = (nspins == 2)
     414              :       !
     415           30 :       IF (do_sf) THEN
     416              :          spindim = 1
     417              :       ELSE
     418           26 :          spindim = nspins
     419              :       END IF
     420              :       !
     421           30 :       fac = 0._dp
     422           30 :       IF (nspins == 1) THEN
     423           14 :          fac = 1.0_dp
     424              :       END IF
     425              : 
     426              :       ! Read xc functional section and find out what the functional actually needs
     427           30 :       xc_fun_section => section_vals_get_subs_vals(xc_section, "XC_FUNCTIONAL")
     428           30 :       needs = xc_functionals_get_needs(xc_fun_section, lsd, .TRUE.)
     429              : 
     430              :       ! Create fields for the kernel and kernel derivative
     431          238 :       ALLOCATE (fxc_rho(spindim), gxc_rho(nspins))
     432           72 :       DO ispin = 1, spindim
     433           42 :          CALL pw_pool%create_pw(fxc_rho(ispin))
     434           72 :          CALL pw_zero(fxc_rho(ispin))
     435              :       END DO
     436           76 :       DO ispin = 1, nspins
     437           46 :          CALL pw_pool%create_pw(gxc_rho(ispin))
     438           76 :          CALL pw_zero(gxc_rho(ispin))
     439              :       END DO
     440              :       ! Create fields for mGGA functionals. This implementation is not ready yet!
     441           30 :       IF (needs%tau .OR. needs%tau_spin) THEN
     442           10 :          IF (.NOT. ASSOCIATED(tau1_r)) THEN
     443            0 :             CPABORT("Tau-dependent functionals requires allocated kinetic energy density grid")
     444              :          END IF
     445           58 :          ALLOCATE (fxc_tau(spindim), gxc_tau(nspins))
     446           24 :          DO ispin = 1, spindim
     447           14 :             CALL pw_pool%create_pw(fxc_tau(ispin))
     448           24 :             CALL pw_zero(fxc_tau(ispin))
     449              :          END DO
     450           24 :          DO ispin = 1, nspins
     451           14 :             CALL pw_pool%create_pw(gxc_tau(ispin))
     452           44 :             CALL pw_zero(gxc_tau(ispin))
     453              :          END DO
     454              :       END IF
     455              : 
     456              :       ! Build rho0_set
     457              :       ! calculate the arguments needed by the functionals
     458              :       ! Needs
     459              :       !   deriv_set  xc_derivative_set_type just declared
     460              :       !   rho0_set   xc_rho_set_type just declared
     461              :       !   rho0_r     pw_type calculated by qs_rho_get
     462              :       !   pw_pool    given by the calling subroutine
     463              :       !   xc_section given by the calling subroutine
     464              :       !   tau0_r     pw_type calculated by qs_rho_get
     465              :       CALL xc_prep_3rd_deriv(deriv_set, rho0_set, rho0_r, pw_pool, weights, &
     466           30 :                              xc_section, tau_r=tau0_r, do_sf=do_sf)
     467              : 
     468              :       ! Build rho1_set
     469          300 :       bo = rho1_r(1)%pw_grid%bounds_local
     470              :       ! create the place where to store the argument for the functionals
     471              :       ! Needs
     472              :       !   rho1_set xc_rho_set_type just declared
     473              :       !   bo 2x3   integer matrix should have bounds_local or rho1_r
     474              :       CALL xc_rho_set_create(rho1_set, bo, &
     475              :                              rho_cutoff=section_get_rval(xc_section, "DENSITY_CUTOFF"), &
     476              :                              drho_cutoff=section_get_rval(xc_section, "GRADIENT_CUTOFF"), &
     477           30 :                              tau_cutoff=section_get_rval(xc_section, "TAU_CUTOFF"))
     478              :       ! calculate the arguments needed by the functionals
     479              :       ! Needs
     480              :       !   rho1_set             object created by xc_rho_set_create
     481              :       !   rho1_r,rho1_g,tau1_r pw_type values of rho1 in real space grid
     482              :       !   needs                xc_rho_cflags_type defined through xc_functionals_get_needs
     483              :       !   pw_pool              Given by the calling subroutine
     484              :       CALL xc_rho_set_update(rho1_set, rho1_r, rho1_g, tau1_r, needs, &
     485              :                              section_get_ival(xc_section, "XC_GRID%XC_DERIV"), &
     486              :                              section_get_ival(xc_section, "XC_GRID%XC_SMOOTH_RHO"), &
     487           30 :                              pw_pool, spinflip=do_sf)
     488              : 
     489              :       ! Calculate exchange correlation kernel
     490              :       ! Needs
     491              :       !   fxc_rho, fxc_tau pw_type not associated
     492              :       !   deriv_set        created and defined by xc_prep_3rd_deriv
     493              :       !   rho0_set         xc_rho_set_type build by xc_prep_3rd_deriv
     494              :       !   rho1_set         xc_rho_set_type build by xc_rho_set_create/update
     495              :       !   pw_pool          needs to be given by the calling subroutine
     496              :       !   xc_section       needs to be given by the calling subroutine
     497              :       CALL xc_calc_2nd_deriv_analytical(fxc_rho, fxc_tau, deriv_set, rho0_set, rho1_set, pw_pool, &
     498           30 :                                         xc_section, .FALSE., spinflip=do_sf, tddfpt_fac=fac)
     499              :       ! Calculate exchange correlation kernel derivative
     500              :       CALL xc_calc_3rd_deriv_analytical(gxc_rho, gxc_tau, deriv_set, rho0_set, rho1_set, pw_pool, &
     501           30 :                                         xc_section, spinflip=do_sf)
     502              : 
     503           30 :       CALL xc_dset_release(deriv_set)
     504           30 :       CALL xc_rho_set_release(rho0_set)
     505           30 :       CALL xc_rho_set_release(rho1_set)
     506              : 
     507           30 :       CALL timestop(handle)
     508              : 
     509         1290 :    END SUBROUTINE qs_fgxc_analytic
     510              : 
     511              : ! **************************************************************************************************
     512              : !> \brief ...
     513              : !> \param qs_env ...
     514              : !> \param rho0_struct ...
     515              : !> \param rho1_struct ...
     516              : !> \param xc_section ...
     517              : !> \param accuracy ...
     518              : !> \param epsrho ...
     519              : !> \param is_triplet ...
     520              : !> \param spinflip ...
     521              : !> \param fxc_rho ...
     522              : !> \param fxc_tau ...
     523              : !> \param gxc_rho ...
     524              : !> \param gxc_tau ...
     525              : ! **************************************************************************************************
     526          336 :    SUBROUTINE qs_fgxc_gdiff(qs_env, rho0_struct, rho1_struct, xc_section, accuracy, epsrho, &
     527              :                             is_triplet, spinflip, fxc_rho, fxc_tau, gxc_rho, gxc_tau)
     528              : 
     529              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     530              :       TYPE(qs_rho_type), POINTER                         :: rho0_struct, rho1_struct
     531              :       TYPE(section_vals_type), POINTER                   :: xc_section
     532              :       INTEGER, INTENT(IN)                                :: accuracy
     533              :       REAL(KIND=dp), INTENT(IN)                          :: epsrho
     534              :       LOGICAL, INTENT(IN)                                :: is_triplet, spinflip
     535              :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: fxc_rho, fxc_tau, gxc_rho, gxc_tau
     536              : 
     537              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'qs_fgxc_gdiff'
     538              : 
     539              :       INTEGER                                            :: handle, ispin, istep, nspins, nstep
     540              :       LOGICAL                                            :: do_sf
     541              :       REAL(KIND=dp)                                      :: alpha, beta, exc, oeps1
     542              :       REAL(KIND=dp), DIMENSION(-4:4)                     :: ak
     543              :       TYPE(dft_control_type), POINTER                    :: dft_control
     544              :       TYPE(pw_env_type), POINTER                         :: pw_env
     545              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     546          336 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: v_tau_rspace, v_tau_rspaceb, vxc00, &
     547          336 :                                                             vxc00b
     548              :       TYPE(qs_rho_type), POINTER                         :: rhoin
     549          336 :       TYPE(rho_atom_type), DIMENSION(:), POINTER         :: rho0_atom_set, rho1_atom_set
     550              : 
     551          336 :       CALL timeset(routineN, handle)
     552              : 
     553          336 :       CPASSERT(.NOT. ASSOCIATED(fxc_rho))
     554          336 :       CPASSERT(.NOT. ASSOCIATED(fxc_tau))
     555          336 :       CPASSERT(.NOT. ASSOCIATED(gxc_rho))
     556          336 :       CPASSERT(.NOT. ASSOCIATED(gxc_tau))
     557          336 :       CPASSERT(ASSOCIATED(rho0_struct))
     558          336 :       CPASSERT(ASSOCIATED(rho1_struct))
     559              : 
     560          336 :       do_sf = spinflip
     561              : 
     562          336 :       ak = 0.0_dp
     563          336 :       SELECT CASE (accuracy)
     564              :       CASE (:4)
     565            0 :          nstep = 2
     566            0 :          ak(-2:2) = [1.0_dp, -8.0_dp, 0.0_dp, 8.0_dp, -1.0_dp]/12.0_dp
     567              :       CASE (5:7)
     568         2688 :          nstep = 3
     569         2688 :          ak(-3:3) = [-1.0_dp, 9.0_dp, -45.0_dp, 0.0_dp, 45.0_dp, -9.0_dp, 1.0_dp]/60.0_dp
     570              :       CASE (8:)
     571            0 :          nstep = 4
     572              :          ak(-4:4) = [1.0_dp, -32.0_dp/3.0_dp, 56.0_dp, -224.0_dp, 0.0_dp, &
     573          336 :                      224.0_dp, -56.0_dp, 32.0_dp/3.0_dp, -1.0_dp]/280.0_dp
     574              :       END SELECT
     575              : 
     576          336 :       CALL get_qs_env(qs_env, dft_control=dft_control, pw_env=pw_env)
     577          336 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
     578              : 
     579          336 :       nspins = dft_control%nspins
     580          336 :       exc = 0.0_dp
     581              : 
     582          336 :       IF (do_sf) THEN
     583              :          CALL qs_fxc_create(qs_env, rho0_struct, rho1_struct, rho0_atom_set, xc_section, &
     584              :                             .FALSE., fxc_rho, fxc_tau, rho1_atom_set, &
     585            8 :                             is_triplet=is_triplet, spinflip=do_sf)
     586              :       ELSE
     587              :          CALL qs_fxc_fdiff(qs_env, rho0_struct, rho1_struct, xc_section, &
     588          328 :                            accuracy, fxc_rho, fxc_tau, is_triplet)
     589              :       END IF
     590              : 
     591         2688 :       DO istep = -nstep, nstep
     592              : 
     593         2688 :          IF (ak(istep) /= 0.0_dp) THEN
     594         2016 :             alpha = 1.0_dp
     595         2016 :             beta = REAL(istep, KIND=dp)*epsrho
     596              :             NULLIFY (rhoin)
     597         2016 :             ALLOCATE (rhoin)
     598         2016 :             CALL qs_rho_create(rhoin)
     599         2016 :             NULLIFY (vxc00, vxc00b, v_tau_rspace, v_tau_rspaceb)
     600         2016 :             CALL qs_rho_copy(rho0_struct, rhoin, auxbas_pw_pool, nspins)
     601         2016 :             CALL qs_rho_scale_and_add(rhoin, rho1_struct, alpha, beta)
     602         2016 :             IF (do_sf) THEN
     603              :                ! variation in alpha density
     604              :                CALL qs_fxc_create(qs_env, rhoin, rho1_struct, rho0_atom_set, xc_section, &
     605              :                                   .FALSE., vxc00, v_tau_rspace, rho1_atom_set, &
     606           48 :                                   is_triplet=is_triplet, spinflip=do_sf)
     607              :                ! variation in beta density
     608           48 :                CALL qs_rho_copy(rho0_struct, rhoin, auxbas_pw_pool, nspins)
     609           48 :                CALL qs_rho_scale_and_add_b(rhoin, rho1_struct, alpha, beta)
     610              :                CALL qs_fxc_create(qs_env, rhoin, rho1_struct, rho0_atom_set, xc_section, &
     611              :                                   .FALSE., vxc00b, v_tau_rspaceb, rho1_atom_set, &
     612           48 :                                   is_triplet=is_triplet, spinflip=do_sf)
     613              :             ELSE
     614              :                CALL qs_fxc_fdiff(qs_env, rhoin, rho1_struct, xc_section, accuracy, &
     615         1968 :                                  fxc_rho=vxc00, fxc_tau=v_tau_rspace, is_triplet=is_triplet)
     616              :             END IF
     617         2016 :             CALL qs_rho_release(rhoin)
     618         2016 :             DEALLOCATE (rhoin)
     619         2016 :             IF (.NOT. ASSOCIATED(gxc_rho)) THEN
     620         1388 :                ALLOCATE (gxc_rho(nspins))
     621          716 :                DO ispin = 1, nspins
     622          380 :                   CALL auxbas_pw_pool%create_pw(gxc_rho(ispin))
     623          716 :                   CALL pw_zero(gxc_rho(ispin))
     624              :                END DO
     625              :             END IF
     626         2016 :             IF (do_sf) THEN
     627           48 :                CALL pw_axpy(vxc00(1), gxc_rho(1), ak(istep))
     628           48 :                CALL pw_axpy(vxc00b(1), gxc_rho(2), ak(istep))
     629              :             ELSE
     630         4152 :                DO ispin = 1, nspins
     631         4152 :                   CALL pw_axpy(vxc00(ispin), gxc_rho(ispin), ak(istep))
     632              :                END DO
     633              :             END IF
     634         2016 :             IF (ASSOCIATED(v_tau_rspace)) THEN
     635            0 :                IF (.NOT. ASSOCIATED(gxc_tau)) THEN
     636            0 :                   ALLOCATE (gxc_tau(nspins))
     637            0 :                   DO ispin = 1, nspins
     638            0 :                      CALL auxbas_pw_pool%create_pw(gxc_tau(ispin))
     639            0 :                      CALL pw_zero(gxc_tau(ispin))
     640              :                   END DO
     641              :                END IF
     642            0 :                IF (do_sf) THEN
     643            0 :                   CALL pw_axpy(v_tau_rspace(1), gxc_tau(1), ak(istep))
     644            0 :                   CALL pw_axpy(v_tau_rspaceb(1), gxc_tau(2), ak(istep))
     645              :                ELSE
     646            0 :                   DO ispin = 1, nspins
     647            0 :                      CALL pw_axpy(v_tau_rspace(ispin), gxc_tau(ispin), ak(istep))
     648              :                   END DO
     649              :                END IF
     650              :             END IF
     651         2016 :             CALL qs_fgxc_release(vxc00, v_tau_rspace, vxc00b, v_tau_rspaceb, auxbas_pw_pool)
     652              :          END IF
     653              : 
     654              :       END DO
     655              : 
     656          336 :       oeps1 = 1.0_dp/epsrho
     657          716 :       DO ispin = 1, nspins
     658          716 :          CALL pw_scale(gxc_rho(ispin), oeps1)
     659              :       END DO
     660          336 :       IF (ASSOCIATED(gxc_tau)) THEN
     661            0 :          DO ispin = 1, nspins
     662            0 :             CALL pw_scale(gxc_tau(ispin), oeps1)
     663              :          END DO
     664              :       END IF
     665              : 
     666          336 :       CALL timestop(handle)
     667              : 
     668          336 :    END SUBROUTINE qs_fgxc_gdiff
     669              : 
     670              : ! **************************************************************************************************
     671              : !> \brief ...
     672              : !> \param qs_env ...
     673              : !> \param rho0_struct ...
     674              : !> \param rho1_struct ...
     675              : !> \param xc_section ...
     676              : !> \param accuracy ...
     677              : !> \param is_triplet ...
     678              : !> \param spinflip ...
     679              : !> \param fxc_rho ...
     680              : !> \param fxc_tau ...
     681              : !> \param gxc_rho ...
     682              : !> \param gxc_tau ...
     683              : ! **************************************************************************************************
     684            0 :    SUBROUTINE qs_fgxc_fgdiff(qs_env, rho0_struct, rho1_struct, xc_section, &
     685              :                              accuracy, is_triplet, spinflip, &
     686              :                              fxc_rho, fxc_tau, gxc_rho, gxc_tau)
     687              : 
     688              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     689              :       TYPE(qs_rho_type), POINTER                         :: rho0_struct, rho1_struct
     690              :       TYPE(section_vals_type), POINTER                   :: xc_section
     691              :       INTEGER, INTENT(IN)                                :: accuracy
     692              :       LOGICAL, INTENT(IN)                                :: is_triplet, spinflip
     693              :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: fxc_rho, fxc_tau, gxc_rho, gxc_tau
     694              : 
     695              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'qs_fgxc_fgdiff'
     696              :       REAL(KIND=dp), PARAMETER                           :: epsrho = 5.e-4_dp
     697              : 
     698              :       INTEGER                                            :: handle, ispin, istep, nspins, nstep
     699              :       REAL(KIND=dp)                                      :: alpha, beta, exc, oeps1, oeps2
     700              :       REAL(KIND=dp), DIMENSION(-4:4)                     :: ak, bl
     701              :       TYPE(dft_control_type), POINTER                    :: dft_control
     702              :       TYPE(pw_env_type), POINTER                         :: pw_env
     703              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     704            0 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: v_tau_rspace, vxc00
     705              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     706              :       TYPE(qs_rho_type), POINTER                         :: rhoin
     707              : 
     708            0 :       CALL timeset(routineN, handle)
     709              : 
     710            0 :       CPASSERT(.NOT. ASSOCIATED(fxc_rho))
     711            0 :       CPASSERT(.NOT. ASSOCIATED(fxc_tau))
     712            0 :       CPASSERT(.NOT. ASSOCIATED(gxc_rho))
     713            0 :       CPASSERT(.NOT. ASSOCIATED(gxc_tau))
     714            0 :       CPASSERT(ASSOCIATED(rho0_struct))
     715            0 :       CPASSERT(ASSOCIATED(rho1_struct))
     716              : 
     717              :       ! no spinflip tested
     718            0 :       CPASSERT(.NOT. spinflip)
     719              : 
     720            0 :       ak = 0.0_dp
     721            0 :       bl = 0.0_dp
     722            0 :       SELECT CASE (accuracy)
     723              :       CASE (:4)
     724            0 :          nstep = 2
     725            0 :          ak(-2:2) = [1.0_dp, -8.0_dp, 0.0_dp, 8.0_dp, -1.0_dp]/12.0_dp
     726            0 :          bl(-2:2) = [-1.0_dp, 16.0_dp, -30.0_dp, 16.0_dp, -1.0_dp]/12.0_dp
     727              :       CASE (5:7)
     728            0 :          nstep = 3
     729            0 :          ak(-3:3) = [-1.0_dp, 9.0_dp, -45.0_dp, 0.0_dp, 45.0_dp, -9.0_dp, 1.0_dp]/60.0_dp
     730            0 :          bl(-3:3) = [2.0_dp, -27.0_dp, 270.0_dp, -490.0_dp, 270.0_dp, -27.0_dp, 2.0_dp]/180.0_dp
     731              :       CASE (8:)
     732            0 :          nstep = 4
     733              :          ak(-4:4) = [1.0_dp, -32.0_dp/3.0_dp, 56.0_dp, -224.0_dp, 0.0_dp, &
     734            0 :                      224.0_dp, -56.0_dp, 32.0_dp/3.0_dp, -1.0_dp]/280.0_dp
     735              :          bl(-4:4) = [-1.0_dp, 128.0_dp/9.0_dp, -112.0_dp, 896.0_dp, -14350.0_dp/9.0_dp, &
     736            0 :                      896.0_dp, -112.0_dp, 128.0_dp/9.0_dp, -1.0_dp]/560.0_dp
     737              :       END SELECT
     738              : 
     739            0 :       CALL get_qs_env(qs_env, ks_env=ks_env, dft_control=dft_control, pw_env=pw_env)
     740            0 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
     741              : 
     742            0 :       nspins = dft_control%nspins
     743              :       exc = 0.0_dp
     744              : 
     745            0 :       DO istep = -nstep, nstep
     746              : 
     747            0 :          alpha = 1.0_dp
     748            0 :          beta = REAL(istep, KIND=dp)*epsrho
     749              :          NULLIFY (rhoin)
     750            0 :          ALLOCATE (rhoin)
     751            0 :          CALL qs_rho_create(rhoin)
     752            0 :          NULLIFY (vxc00, v_tau_rspace)
     753            0 :          IF (is_triplet) THEN
     754            0 :             CPASSERT(nspins == 1)
     755              :             ! rhoin = (0.5 rho0, 0.5 rho0)
     756            0 :             CALL qs_rho_copy(rho0_struct, rhoin, auxbas_pw_pool, 2)
     757              :             ! rhoin = (0.5 rho0 + 0.5 rho1, 0.5 rho0)
     758            0 :             CALL qs_rho_scale_and_add(rhoin, rho1_struct, alpha, 0.5_dp*beta)
     759            0 :             CALL qs_vxc_create(ks_env, rhoin, xc_section, vxc00, v_tau_rspace, exc)
     760            0 :             CALL pw_axpy(vxc00(2), vxc00(1), -1.0_dp)
     761              :          ELSE
     762            0 :             CALL qs_rho_copy(rho0_struct, rhoin, auxbas_pw_pool, nspins)
     763            0 :             CALL qs_rho_scale_and_add(rhoin, rho1_struct, alpha, beta)
     764            0 :             CALL qs_vxc_create(ks_env, rhoin, xc_section, vxc00, v_tau_rspace, exc)
     765              :          END IF
     766            0 :          CALL qs_rho_release(rhoin)
     767            0 :          DEALLOCATE (rhoin)
     768            0 :          IF (.NOT. ASSOCIATED(fxc_rho)) THEN
     769            0 :             ALLOCATE (fxc_rho(nspins))
     770            0 :             DO ispin = 1, nspins
     771            0 :                CALL auxbas_pw_pool%create_pw(fxc_rho(ispin))
     772            0 :                CALL pw_zero(fxc_rho(ispin))
     773              :             END DO
     774              :          END IF
     775            0 :          IF (.NOT. ASSOCIATED(gxc_rho)) THEN
     776            0 :             ALLOCATE (gxc_rho(nspins))
     777            0 :             DO ispin = 1, nspins
     778            0 :                CALL auxbas_pw_pool%create_pw(gxc_rho(ispin))
     779            0 :                CALL pw_zero(gxc_rho(ispin))
     780              :             END DO
     781              :          END IF
     782            0 :          CPASSERT(.NOT. ASSOCIATED(v_tau_rspace))
     783            0 :          DO ispin = 1, nspins
     784            0 :             IF (ak(istep) /= 0.0_dp) THEN
     785            0 :                CALL pw_axpy(vxc00(ispin), fxc_rho(ispin), ak(istep))
     786              :             END IF
     787            0 :             IF (bl(istep) /= 0.0_dp) THEN
     788            0 :                CALL pw_axpy(vxc00(ispin), gxc_rho(ispin), bl(istep))
     789              :             END IF
     790              :          END DO
     791            0 :          DO ispin = 1, SIZE(vxc00)
     792            0 :             CALL auxbas_pw_pool%give_back_pw(vxc00(ispin))
     793              :          END DO
     794            0 :          DEALLOCATE (vxc00)
     795              : 
     796              :       END DO
     797              : 
     798            0 :       oeps1 = 1.0_dp/epsrho
     799            0 :       oeps2 = 1.0_dp/(epsrho**2)
     800            0 :       DO ispin = 1, nspins
     801            0 :          CALL pw_scale(fxc_rho(ispin), oeps1)
     802            0 :          CALL pw_scale(gxc_rho(ispin), oeps2)
     803              :       END DO
     804              : 
     805            0 :       CALL timestop(handle)
     806              : 
     807            0 :    END SUBROUTINE qs_fgxc_fgdiff
     808              : 
     809              : ! **************************************************************************************************
     810              : !> \brief ...
     811              : !> \param fxc_rho ...
     812              : !> \param fxc_tau ...
     813              : !> \param gxc_rho ...
     814              : !> \param gxc_tau ...
     815              : !> \param pw_pool ...
     816              : ! **************************************************************************************************
     817         2382 :    SUBROUTINE qs_fgxc_release(fxc_rho, fxc_tau, gxc_rho, gxc_tau, pw_pool)
     818              : 
     819              :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: fxc_rho, fxc_tau, gxc_rho, gxc_tau
     820              :       TYPE(pw_pool_type), POINTER                        :: pw_pool
     821              : 
     822              :       INTEGER                                            :: ispin
     823              : 
     824         2382 :       IF (ASSOCIATED(fxc_rho)) THEN
     825         5028 :          DO ispin = 1, SIZE(fxc_rho)
     826         5028 :             CALL pw_pool%give_back_pw(fxc_rho(ispin))
     827              :          END DO
     828         2382 :          DEALLOCATE (fxc_rho)
     829              :       END IF
     830         2382 :       IF (ASSOCIATED(fxc_tau)) THEN
     831           24 :          DO ispin = 1, SIZE(fxc_tau)
     832           24 :             CALL pw_pool%give_back_pw(fxc_tau(ispin))
     833              :          END DO
     834           10 :          DEALLOCATE (fxc_tau)
     835              :       END IF
     836         2382 :       IF (ASSOCIATED(gxc_rho)) THEN
     837          888 :          DO ispin = 1, SIZE(gxc_rho)
     838          888 :             CALL pw_pool%give_back_pw(gxc_rho(ispin))
     839              :          END DO
     840          414 :          DEALLOCATE (gxc_rho)
     841              :       END IF
     842         2382 :       IF (ASSOCIATED(gxc_tau)) THEN
     843           24 :          DO ispin = 1, SIZE(gxc_tau)
     844           24 :             CALL pw_pool%give_back_pw(gxc_tau(ispin))
     845              :          END DO
     846           10 :          DEALLOCATE (gxc_tau)
     847              :       END IF
     848              : 
     849         2382 :    END SUBROUTINE qs_fgxc_release
     850              : 
     851              : END MODULE qs_fgxc
        

Generated by: LCOV version 2.0-1